On 3 February 2012 21:20, Conrad J. Sabatier <conr...@cox.net> wrote: > On Fri, 27 Jan 2012 16:05:37 +0000 > Matthew Seaman <m.sea...@infracaninophile.co.uk> wrote: > >> >> Dear all, >> >> Posting this mostly for the archives, but it's probably relevant to >> some people here too. >> >> When hacking on Makefiles, should you wish to match an item in a list, >> you might write something like this: >> >> .for item in ${LIST} >> .if ${item} == ${THING} # Ooops! >> THING_FOUND= 1 >> .endif >> .endfor >> >> This however is a snare and a delusion, and will lead to much weeping >> and wailing, and error messages like so: >> >> % make >> "Makefile", line 7: Malformed conditional (foo == ${THING}) >> "Makefile", line 9: if-less endif >> "Makefile", line 7: Malformed conditional (bar == ${THING}) >> "Makefile", line 9: if-less endif >> "Makefile", line 7: Malformed conditional (baz == ${THING}) >> "Makefile", line 9: if-less endif >> "Makefile", line 7: Malformed conditional (blurfl == ${THING}) >> "Makefile", line 9: if-less endif >> make: fatal errors encountered -- cannot continue >> >> Instead you should write your loops like this: >> >> .for item in ${LIST} >> .if ${THING} == ${item} >> THING_FOUND= 1 >> .endif >> .endfor >> >> As the make(1) manual page says on the subject of string comparisons >> using == or != : >> >> An expression may also be a numeric or string comparison: in >> this case, the left-hand side must be a variable expansion, whereas >> the right-hand side can be a constant or a variable expansion. >> >> So it seems that despite appearing and behaving almost exactly like >> one, the iterator in a .for loop is not actually a variable as such. >> It also means that to match a constant string, you can't just write: >> >> .for item in ${LIST} >> .if ${item} == "this" # Ooops >> THIS_FOUND=1 >> .endif >> .endfor >> >> but have to assign the text "this" to a variable somewhere, and use >> the second form. >> >> Yes, you can use ${LIST:Mthis} instead, but using this construct can >> be a bit tricky in itself... >> >> % cat Makefile >> >> LIST= foo bar baz blurfl >> >> THING= baz >> >> all: >> @echo "OK \$${LIST:Mfoo} = ${LIST:Mfoo}" >> @echo "Not OK \$${LIST:M\$${THING}} = ${LIST:M${THING}}" >> % make >> OK ${LIST:Mfoo} = foo >> Not OK ${LIST:M${THING}} = } >> >> Cheers, >> >> Matthew >> > > Wow, that is a pretty obscure bit of an oddity, isn't it? How'd you > ever discover that? > > Looking at the man page, it seems more than a little misleading, as it > does call the iterator in .for loops a "variable" (which for all > intents and purposes, I'd say that it is, in fact). One could easily > lose one's marbles trying to "debug" something like this! > > Looks like a bug, smells like a bug to me. Or at least, some *very* > quirky behavior/a serious design flaw that surely wouldn't be missed, > were someone to take the initiative to change it. <hint-hint> No > language should require you to jump through this sort of torturous, > totally anti-intuitive hoop to accomplish what you want to do. Talk > about your POLA! :-)
Judging by the sheer volume of Makefiles out there that quite possibly rely on this 'bug' for some things, it's not worth fixing ;) Just think of it as yet another quirk of make. Chris _______________________________________________ freebsd-ports@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-ports To unsubscribe, send any mail to "freebsd-ports-unsubscr...@freebsd.org"