[Top][All Lists]
[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.
- fun with eval, David Wuertele, 2004/08/03
- Re: fun with eval,
Markus Mauhart <=