If I have the following at the top of a gnu makefile:
$(if _,a:=1)
$(info a=$a)
Compilation fails (make-3.81: *** No rule to make target '=1', needed by 'a'. Stop.
, or *** missing separator. Stop.
if I exclude the colon). I know I can get around this by using an eval
, but I'm not understanding why it's required. Shouldn't this expand to a:=1
, be parsed, and set a
to 1
?
I'm not understanding why it's required
Well, such is the design.
Evaluation procedure always performs a (recursive) expansion (except for "the initial evaluation" where subsequent expansion can be effectively stopped by =
, i.e. "lazy assignment"), but expansion procedure never does evaluation, unless it's explicitly told so (basically, $(eval ...)
is such an order to switch from expansion to evaluation).
Consider this:
x := 0
y := 1
# z is set to "y<space><equal><space><dollar>x"
z = y = $x
# [0] [1] [y = $x]
$(info [$x] [$y] [$(value z)])
# error as "y = $x" will not be re-evaluated
#$z
# effectively sets y to "0"
$(eval $z)
# [0] [0] [y = $x]
$(info [$x] [$y] [$(value z)])
From make's point of view $(if cond,x=y)
does not differ much from $z
--- it's expanded but not evaluated. No matter where it stands. Just think anything of a form $(...)
to be "data", not "code".