help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: fun with eval


From: Markus Mauhart
Subject: Re: fun with eval
Date: Wed, 4 Aug 2004 12:32:10 +0200

"David Wuertele" <address@hidden> wrote ...
>
> Can anyone explain to me why running GNU Make 3.80 on the following
> makefile:
>
>
>   THINGS := one two three
>
>   define THING_template
>     ALL += `date +%s; sleep 1`
>     THIS = $(shell date +%s; sleep 1)
>     ALL2 += $(THIS)
>   endef
>
>   $(foreach thing,$(THINGS),$(eval $(call THING_template,$(thing))))
>
>   debug:
>           @echo ALL = $(ALL)
>           @echo ALL2 = $(ALL2)
>
>
> ...results in the following output:
>
>   $ make
>   ALL = 1091577190 1091577191 1091577192
>   ALL2 = 1091577187 1091577188
>
> I would have expected something more like this:
>
>   $ make
>   ALL = 1091577190 1091577191 1091577192
>   ALL2 = 1091577186 1091577187 1091577188
>
> Where did the other append to ALL2 go?


With your foreach loop, first THING_template's value (a 3-lined string) is
expanded (but not "evaluated") by the call-function to the 3-lined string ...

  ALL += `date +%s; sleep 1`
  THIS = 1091577187
  ALL2 +=

(during call's expansion the assignment "THIS = 1091577187" is not
"evaluated", hence the latter $(THIS) expands to its old value (empty))

... and only then the eval function "evaluates" the resulting three lines,
i.e. then it performs the 3 variable assignments.

You can check this out by putting the following 3 lines before the
foreach loop:

 ALL = old_all
 THIS = old_this
 ALL2 = old_all2

... then the result will be like ...

 ALL = old_all 1091611617 1091611618 1091611619
 ALL2 = old_all2 old_this 1091611614 1091611615


There are some solutions:


* If you need the args $1/2/3 inside your function body and therefore
 use $(eval $(call function,x1,x2,x3)), then you have to replace some
 $ inside the function with $$ -> e.g. $$(THIS).
 Typically one replaces all $ with $$, but the result is hard to understand
 and especially hard to change later.


* if the function doesnt need arguments $1/2/.., then dont call it:
  use        $(eval $(value THING_template))
  instead of $(eval $(call THING_template))


* if the function needs arguments only to change simply expanded variables,
  then you can also use $(eval $(value THING_template)):

N := e
$(foreach x,1 2 3 4 5 6 7 8,$(eval N += $N))
time_ := 0
time = $(time_)$(eval time_ := $(words e $(wordlist 1,$(time_),$N)))

ALL := $(ALL)   #old value, but now simply exanded
ALL2 := $(ALL2) #old value, but now simply exanded

define THING_template
ALL += $(thing)a$(time)a
THIS := $(thing)z$(time)z
ALL2 += $(THIS)
endef

$(foreach thing,$(THINGS),$(eval $(value THING_template)))

Or, if you dont want to give function "THING_template" its own variable "thing",
then use ...

evalWithArgs = $(eval $1)

define THING_template
ALL += $2a$(time)a
THIS = $2z$(time)z
ALL2 += $(THIS)
endef

ALL := $(ALL)   #old value, but now simply exanded
ALL2 := $(ALL2) #old value, but now simply exanded

$(foreach thing,$(THINGS),$(call evalWithArgs,$(value THING_template),$(thing)))


Regards,
Markus.








reply via email to

[Prev in Thread] Current Thread [Next in Thread]