奇怪的 foreach + Makefile 中用户定义的函数行为
我有以下 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.
现在“有趣”的部分:如果我在声明“all”规则后添加以下行:
X+=d
所有三个 jar 文件都已处理,“make”不会提及任何有关“ d'(即使文件'd'不存在),并且运行成功。
所以看起来 foreach 循环没有经历最后一次迭代(或者很可能发生其他导致相同结果的事情)。有谁知道问题是什么以及如何解决它?
谢谢!
I have the following 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 exist)
Basically, for each file name in $X, I want to find the full path in $Y and create a rule that copies that file to /var/tmp/abc/tmp (I know there's a much easier way to do this, but my actual Makefile is more complicated and needs a construct like this).
When I run this Makefile, I get the following output:
/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.
Now the "funny" part: If I add the following line after declaring the "all" rule:
X+=d
all three jar files are processed, 'make' doesn't mention anything about 'd' (even if file 'd' doesn't exist), and the run is a success.
So it looks like the foreach loop doesn't go through the last iteration (or most probably something else that leads to the same results happens). Does anybody know what the problem is and how to fix it?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
糟糕的不仅仅是循环的最后一次迭代。基本上,
call
将$(dst)
扩展为调用call
时的任何值,而不是在调用新代码时被评估。然后评估新代码,然后在下一次迭代中扩展定义——使用上一个新代码块设置的值。因此,它给出的不是 {a, b, c},而是 { , a, b} (你必须盯着它看一会儿,然后它才有意义)。解决方案:添加几个额外的
$
:It's not just the last iteration of the loop that's bad. Basically
call
expands$(dst)
to whatever value it has whencall
is invoked, not when the new code is evaluated. Then the new code is evaluated, and then in the next iteration the definition is expanded-- with the values that have been set by the previous block of new code. So instead of {a, b, c} it gives { , a, b} (you have to stare at this for a while before it makes sense).Solution: put in a couple of extra
$
s: