[bug#60535] [PATCH] depend2: switch echo|sed to automatic vars

Mike Frysinger <[email protected]> Wed, 4 Jan 2023 22:41:15 -0500
Newsgroups gmane.comp.sysutils.automake.patches
Message-ID <Y7ZG2ztiPyfbcebg@vapier>
On 04 Jan 2023 21:10, Nick Bowler wrote:
> Except for one minor detail, $(@F) and $(@D) are highly portable.  I
> expect they were in the very first POSIX.2 specs as they predate the
> earliest standards; I believe they first appeared in UNIX System V (ca.
> 1983) and were later added to BSD in 4.3BSD-Reno (ca. 1990).
> 
> The only potential problem I am aware of with these features is one
> implementation (dmake) which does not follow the POSIX rule of excluding
> the trailing slash from the directory part, and (a bit more troublesome)
> will expand $(@D) to the empty string if the directory part is empty,
> instead of . as required by POSIX.  Usually this is not a major issue,
> as writing something like ./$(@D)/$(@F) is usually sufficient to avoid
> any problems with empty $(@D).

thanks ... i vaguely recall seeing a thread somewhere in the last year or
two talking about portable $(@D)/$(@F) issues somewhere which is how i
learned about these in the first place, but i can't seem to locate it, and
the syntax is not conducive to Google searches.  you don't happen to know
what i'm remembering ?  or have a link to some docs about how portable
these vars are ?  i thought it'd be useful to include them in our docs
and/or manual somewhere.

i can build & install dmake easily since someone is maintaining it in GH:
	https://github.com/jimjag/dmake
i'll throw some bugs at them :)

> It's worth noting that $(?F), $(?D), $(%F) and $(%D) were never added
> to BSD and as a result are missing from many BSD derivatives.  However,
> these variables are of limited utility and are unlikely to be missed.

that'll be good to note in our docs too

> The $(x:a=b) suffix substitutions are of identical vintage, and as
> far as I know every make supporting file/directory variables also,
> in principle, supports suffix substitution too.  However, there are
> many bugs in real-world implementations of this feature.
> 
> Of particular relevance to this patch: older versions of NetBSD make,
> while they do support suffix substitution, fail to correctly parse
> $(@F:.o=):
> 
>   % cat >Makefile <<'EOF'
> foo/bar.o:
> 	echo $(@F:.o=)
> EOF
>   % make
>   echo bar.o.o=)
>   Syntax error: ")" unexpected
>   *** Error code 2
> 
> NetBSD make was widely adopted by other systems, so this particular
> issue may actually be found elsewhere.  This bug was present as recently
> as NetBSD 7.2 (ca. 2018).  Furthermore, old versions of FreeBSD (before
> they ditched their own make in favour of NetBSD's version) also fail to
> correctly handle $(@F:.o=), but in a different way.
> 
> The good news is that these problems can be worked around pretty easily
> simply by using another variable:
> 
>   % cat >Makefile <<'EOF'
> at_f = $(@F)
> foo/bar.o:
> 	echo $(at_f:.o=)
> EOF
>   % make
>   echo bar
>   bar
> 
> But this workaround trips over a different suffix substitution bug on
> ULTRIX, which would otherwise work just fine with plain $(@F:.o=).
> Maybe ULTRIX is not worth worrying about these days, but nevertheless,
> it is not too hard to detect and work around both problems in pure
> shell, which should still work to avoid the additional forks/sed,
> maybe something like:
> 
>   % cat >Makefile <<'EOF'
> at_f = $(@F)
> foo/bar.o:
> 	a='$(@F:.o=)' b='$(at_f:.o=)'; test x"$$a.o" = x"$(@F)" || a=$$b;\
> 	  echo $$a
> EOF

this is interesting.  we actually have some uses of this already in
the tree.  no one seems to have complained though afaict.

automake-1.13+ has:
lib/am/subdirs.am:AM_RECURSIVE_TARGETS += $(am__recursive_targets:-recursive=)

automake-1.9+ has:
lib/am/texibuild.am:      for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \

dmake is one implementation that fails, and your suggestion doesn't work :/.
$ dmake foo/bar.o
dmake:  Error: -- Incomplete macro expression [)' b='$(at_f:.o=)'; test x"$$a.o" = x"$(@F)" || a=$$b;\
                echo $$a]

how portable is $() ?  that seems to work in GNU make & dmake.
$ cat Makefile
DEPDIR = ./$(@D)/depdir/$(@F:.o=$())
foo/bar.o:
	@echo $(DEPDIR)
$ dmake
./foo//depdir/bar
-mike
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEuQK1JxMl+JKsJRrUQWM7n+g39YEFAmO2RtsACgkQQWM7n+g3
9YFcRg//VbESwjBO1w6pzuJbC4J1Se8N+S7csYCCh1k8M4FPjiIm4C+84+IGWIuX
R5G9LWZMzh7CvyJWrKpaHQzWDST5+wTNphByImezYwmf42YgrnV4Jf0+WNh4XgSa
PVmp062f9FFu6egMWr9NkwyuJMX//LAd9KVUR7kccez/te60bczvZlUskGdFxmaZ
1dvY10Ys9KT+gdpf/f9Ga6AdM4tUflX5+ciHhOMfZAqPk4Ff4PMv9qPKYG5JErjP
MoqNizVxeWoTUFyILXvyB5wKHQWxI8sJfEp1HmDwrNrq0q9B3+jHp01b26yAo0ZT
1c7Yt/0kJxximinI6BgPjSzn5pBdUVkpSuV4G3uVT1K4FJWZEUH42+v7rJGZ5pOz
eHYkP9dC9LTsb7+01SznmsvQkmWhTHZKagv/YQ3sxq1eh9zRvbLXt6mrOsVuRi7A
oF0Gok4nMwPU7AW3OxJ9qyGPqOG28olVQxNCbRS0EbUR3XnQVQNbnd4/hTYmxIpc
CsPJ+jb2Bfq/0dx0ruf2B7aP5wM/c0fdAM1w/wYMT7+9dDt23AOrAyt168MoE7hO
46ln8k4y1KS7/b2s0esQ04hz0F5bpkSI6LDMifcJR8j4NjEOkxvjhCSvD0WN8K54
mEJytGwcnCsqbnn90GddIIurhJPqb32FW0KRd5JnvXw24PeitDs=
=Jj5E
-----END PGP SIGNATURE-----