我有以下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循环没有经历最后一次迭代(或者很可能是导致相同结果发生的其他东西)。有谁知道问题是什么以及如何解决它?
谢谢!
答案 0 :(得分:2)
这不仅仅是循环的最后一次迭代。基本上call
会将$(dst)
扩展为调用call
时的值,而不是在评估新代码时。然后评估新代码,然后在下一次迭代中扩展定义 - 使用前一个新代码块设置的值。所以代替{a,b,c}它给出{,a,b}(你必须先盯着它看一段时间才有意义)。
解决方案:加入一些额外的$
s:
define AddRule
dst=$1
src=$2
/var/tmp/abc/tmp/$$(dst): $$(src)
...
endef