On Thu, Jul 18, 2024, at 5:09 AM, Tijl Coosemans wrote:
> Automake 1.17 produces a warning for the use of \# here:
>
> https://github.com/ddclient/ddclient/blob/d88e6438efbc53e977546693f6835f7517072a06/Makefile.am#L22
For reference, the construct in question is
subst = sed \
-e 's|@PACKAGE_VERSION[@]|$(PACKAGE_VERSION)|g' \
-e '1 s|^\#\!.*perl$$|\#\!$(PERL)|g' \
-e 's|@localstatedir[@]|$(localstatedir)|g' \
[etc]
and the warning triggers on the '1 s|^\#\!...' line.
> Is use within quotes also not portable?
I could be wrong about this, but I don't think any implementation of Make
pays _any_ attention to shell quotation in commands. Therefore, no, this
is not portable. If there was a portable way to define a Make variable
that expanded to a single # then you could write
subst = sed \
-e 's|@PACKAGE_VERSION[@]|$(PACKAGE_VERSION)|g' \
-e '1 s|^$(HASH)!.*perl$$|$(HASH)! $(PERL)|g' \
-e 's|@localstatedir[@]|$(localstatedir)|g' \
[etc]
but I think the only portable way to define that variable is from
outside the Makefile, e.g. by typing
make 'HASH=#'
every single time, ick.
My default recommendation for this sort of thing - for *any* circumstance
where you find yourself embedding more than a couple lines of shell script in
a Makefile, frankly - is that you split out the _entire_ troublesome construct
into a standalone script, like, put this in build-aux/subst
---
#! /bin/sh
set -e -u
if [ $# -ne 1 ]; then
printf 'usage: %s out-file\n' "$0" >&2
printf 'PACKAGE_VERSION, PERL, CURL, srcdir, localstatedir,\n' >&2
printf 'runstatedir, and sysconfdir must be set in environment\n' >&2
exit 1
fi
out="$1"
tmp="${out}.tmp.$$"
trap 'rm -f $tmp' 0
if [ -f "${out}.in" ]; then
in="${out}.in"
elif [ -f "${srcdir}/${out}.in" ]; then
in="${srcdir}/${out}.in"
else
printf '%s: error: %s not found in . or %s\n' \
"$0" "${out}.in" "$srcdir" >&2
exit 1
fi
sed < "$in" > "$tmp" \
-e 's|@PACKAGE_VERSION[@]|'"${PACKAGE_VERSION}"'|g' \
-e '1 s|^#!.*perl$|#! '"${PERL}"'|g' \
-e 's|@localstatedir[@]|'"${localstatedir}"'|g' \
-e 's|@runstatedir[@]|'"${runstatedir}"'|g' \
-e 's|@sysconfdir[@]|'"${sysconfdir}"'|g' \
-e 's|@CURL[@]|'"${CURL}"'|g'
if [ -x "$in" ]; then
chmod +x "$tmp"
fi
mv "$tmp" "$out"
trap '' 0
---
and then change your $(subst_files) rule to
---
$(subst_files): Makefile build-aux/subst
PACKAGE_VERSION="$(PACKAGE_VERSION)" \
PERL="$(PERL)" \
CURL="$(CURL)" \
srcdir="$(srcdir)" \
localstatedir="$(localstatedir)" \
runstatedir="$(runstatedir)" \
sysconfdir="$(sysconfdir)" \
$(SHELL) $(srcdir)/build-aux/subst $@
---
and then you don't have to worry about layering Makefile quotation
on top of shell quotation.
zw