Makefile中奇怪的foreach +用户定义的函数行为

时间:2011-11-12 01:49:54

标签: foreach makefile user-defined-functions

我有以下Makefile:

X=a.jar b.jar c.jar
Y=/var/tmp/abc/a.jar /var/tmp/abc/b.jar /var/tmp/abc/c.jar

all: $(addprefix /var/tmp/abc/tmp/, $(X))

define AddRule
dst=$1
src=$2
/var/tmp/abc/tmp/$(dst): $(src)
        @echo $$@
        @echo $$^
        @mkdir -p $$(dir $$@)
        @cp $$^ $$@
endef
$(foreach jar, $(X), $(eval $(call AddRule, $(jar), $(filter %$(jar), $(Y)))))

(/ var / tmp / abc / {a,b,c} .jar存在)

基本上,对于$ X中的每个文件名,我想在$ Y中找到完整路径,并创建一个将该文件复制到/ var / tmp / abc / tmp的规则(我知道有一个更容易的方法)这个,但我的实际Makefile更复杂,需要这样的结构。)

当我运行这个Makefile时,我得到以下输出:

/var/tmp/abc/tmp/a.jar
/var/tmp/abc/a.jar
/var/tmp/abc/tmp/b.jar
/var/tmp/abc/b.jar
make: *** No rule to make target `/var/tmp/abc/tmp/c.jar', needed by `all'.  Stop.

现在是“有趣”的部分:如果我在声明“全部”规则后添加以下行:

X+=d

所有三个jar文件都被处理,'make'没有提及'd'(即使文件'd'不存在),并且运行成功。

所以看起来foreach循环没有经历最后一次迭代(或者很可能是导致相同结果发生的其他东西)。有谁知道问题是什么以及如何解决它?

谢谢!

1 个答案:

答案 0 :(得分:2)

这不仅仅是循环的最后一次迭代。基本上call会将$(dst)扩展为调用call的值,而不是在评估新代码时。然后评估新代码,然后在下一次迭代中扩展定义 - 使用前一个新代码块设置的值。所以代替{a,b,c}它给出{,a,b}(你必须先盯着它看一段时间才有意义)。

解决方案:加入一些额外的$ s:

define AddRule
dst=$1
src=$2
/var/tmp/abc/tmp/$$(dst): $$(src)
    ...
endef