Hi Kris, On Sat, Feb 12, 2005 at 06:32:01PM -0800, Kris Kennaway wrote: > The following small makefile doesn't behave as one would naively > expect: > > MANLANG?=foo "" > all: > .for i in ${MANLANG} > .if empty(${i}) > @echo foo ${i} > .endif > .endfor > > ports-i386%make > foo foo > foo > > I think this is because the .if evaluation is happening too early, and > it's not being done after the .for loop is expanded and the i variable > is set. > This makefile is broken, you're abusing empty(). empty() expects a variable name (without `$') as an argument, and ``.if empty(foo)'' means "true if ${foo} has an empty value". Note that in 4.x, "foo" also needs to be a defined variable, for this to work at all. In 5.x and 6.x, undefined variables are treated like empty variable by empty().
> In order to get this to work I seem to have to do the following: > > MANLANG?=foo "" > .for i in ${MANLANG} > j= ${i} > .if (${j} != "\"\"") > .for l in ${j} > k+= ${l} > .endfor > .endif > .endfor > all: > @echo ${k} > > ports-i386%make > foo > > If I remove the inner .for it breaks, and if I remove the j assignment > it breaks. Also if I try and remove the use of k and put an echo > inside the inner .for (with the all: preceding the whole loop) it > breaks. > > This is extremely nasty. > Yes. This behavior is documented in the BUGS section of the make(1) manpage: .for loops are unrolled before tests, and .for variables aren't real variables, so a fragment like this: .for i in foo bar .if ${i} == "foo" echo ${i} .endif .endfor doesn't work. This fragment is rewritten by make(1) before further parsing as follows: .if foo == "foo" echo foo .endif .if bar == "foo" echo bar .endif And since .if expects a ${variable} as its first argument, it fails. About why you need an inner loop. Remember again that .for loops are unrolled before parsing, it means that a fragment like this: .for i in foo bar j=${i} k+=${j} .endfor is equivalent to j=foo k+=${j} j=bar k+=${j} which means that `k' will get a value of "bar bar". When you use an inner loop, .for i in foo bar j=${i} .for l in ${j} k+=${l} .endfor .endfor it first gets rewritten to: j=foo .for l in ${j} k+=${l} .endfor j=bar .for l in ${j} k+=${l} .endfor then to: j=foo k+=foo j=bar k+=bar which DTRT, but also has a side effect of setting "j" to "bar". > Am I missing an easier way to do this? > May I suggest the following instead: %%% MANLANG?= foo "" bar all: .for i in ${MANLANG:N""} @echo foo ${i} .endfor %%% Note that `""' is not an empty value in make(1), it's just a regular value consisting of two double quotes. Cheers, -- Ruslan Ermilov [EMAIL PROTECTED] FreeBSD committer
pgpjj2c9e1zVG.pgp
Description: PGP signature