bin/64327: [PATCH] make(1): document surprising behaviour of assign with expansion

Oliver Eikemeier eikemeier at fillmore-labs.com
Tue Mar 16 06:00:41 PST 2004


The following reply was made to PR bin/64327; it has been noted by GNATS.

From: Oliver Eikemeier <eikemeier at fillmore-labs.com>
To: Ruslan Ermilov <ru at freebsd.org>
Cc: FreeBSD-gnats-submit at freebsd.org
Subject: Re: bin/64327: [PATCH] make(1): document surprising behaviour of
 assign with expansion
Date: Tue, 16 Mar 2004 14:58:35 +0100

 Ruslan Ermilov wrote:
 
 > On Tue, Mar 16, 2004 at 12:49:27PM +0100, Oliver Eikemeier wrote:
 > 
 >>Try the Makefile from the patch:
 >>
 >>VAR1:=	Assigned with${OUT} expansion
 >>VAR2!=	echo Assigned with${OUT} expansion
 >>OUT=	out
 >>all:
 >>	@echo := - ${VAR1}
 >>	@echo != - ${VAR2}
 >>
 >>
 >>>Fix:
 >>
 >>diff -u -r1.29.2.15 make.1
 >>--- make.1	17 Dec 2002 19:01:18 -0000	1.29.2.15
 >>+++ make.1	16 Mar 2004 11:12:09 -0000
 >>@@ -1266,6 +1266,17 @@
 >> \&.endfor
 >> .Ed
 >> won't work, and should be rewritten the other way around.
 >>+.Pp
 >>+Undefined variables are not expanded when assigned with expansion.
 >>+This is intentional, but may lead to surprising results:
 >>+.Bd -literal
 >>+VAR1:=  Assigned with${OUT} expansion
 >>+VAR2!=  echo Assigned with${OUT} expansion
 >>+OUT=    out
 >>+all:
 >>+    @echo := - ${VAR1}
 >>+    @echo != - ${VAR2}
 >>+.Ed
 >> .Sh SEE ALSO
 >> .Xr mkdep 1 ,
 >> .Xr make.conf 5
 >>
 > 
 > So, expanding "Assigned with${OUT} expansion" with := when OUT is undefined
 > gives you the same string (have a look at the ``make -r -dv'' output), and it
 > becomes a value of VAR1, and when later you print it, it's expanded again (as
 > it still has the `$' character).  This time OUT is defined, and its value is
 > substituted.
 
 Of course you could move `OUT=out' after `all:'. The point is that you'll
 encounter problems with that pretty often in bsd.port.mk.
 
 > Expanding "echo Assigned with${OUT} expansion" through != gives you "Assigned
 > with expansion", and that's what gets printed later.
 
 I guess I tried my own example before posting it...
 
 > Whatever, "undefined variables are not expanded" sounds like a non-sense
 > to me.  ;)
 
 Basically that is what it does: it leaves undefined variables there for late
 expansion. If you try:
 
 SUFFIX?=	.txt
 _FILE:=		${FILE}${SUFFIX}
 
 .if exists(${_FILE})
 	....
 .endif
 
 FILE=		settings
 SUFFIX=		.opt
 
 .if exists(${_FILE})
 	....
 .endif
 
 You'll test for the existence of `.txt' in the first .if, and for `settings.txt'
 in the second. It took me a while to figure *that* out.
 
 > The following code fragment in make(1) is responsible for this, and has more
 > correct wording:
 > 
 > :     } else if (type == VAR_SUBST) {
 > :         /*
 > :          * Allow variables in the old value to be undefined, but leave their
 > :          * invocation alone -- this is done by forcing oldVars to be false.
 > :          * XXX: This can cause recursive variables, but that's not hard to do,
 > :          * and this allows someone to do something like
 > :          *
 > :          *  CFLAGS = $(.INCLUDES)
 > :          *  CFLAGS := -I.. $(CFLAGS)
 > :          *
 > :          * And not get an error.
 > :          */
 > :         Boolean   oldOldVars = oldVars;
 > : 
 > :         oldVars = FALSE;
 
 I know. Thats the reason I wrote: `This is intentional' and didn't file a bug report.
 
 > Perhaps you could convert it to fit the manpage?  Definitely we shouldn't put
 > it in the BUGS section.
 
 I though so. What should I use: HISTORY, CAVEATS, IMPLEMENTATION NOTES or something else?
 
 How about:
 
 Undefined variables are left untouched when assigned with expansion.
 This is intentional, but may lead to surprising results:
 
 VAR1:=  Assigned with${OUT} expansion
 all:
 	@echo ${VAR1}
 
 OUT=    out
 
 Outputs `Assigned without expansion'. You can use != and echo to avoid this effect.
 


More information about the freebsd-bugs mailing list