This is a reprise of an e-mail I sent to the freebsd-ports@freebsd.org mailing list last January.
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 (and preferrably should) use ${LIST:Mthis} instead, but using this construct only works when matching constant text:
% 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}} = }
Also note: as a matter of style, when matching a constant string, don't enclose that string in "quote marks" when it isn't necessary:
.if ${item} == "this" # Wrong!