奇怪的foreach +在Makefiles中用户定义的函数行为 [英] Weird foreach + user-defined function behavior in Makefiles

查看:137
本文介绍了奇怪的foreach +在Makefiles中用户定义的函数行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的Makefile:

$ $ p $ $ $ c $ 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))

定义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.ja r
/var/tmp/abc/b.jar
make:***目标`/var/tmp/abc/tmp/c.jar'没有规则,'all'需要。停止。

现在滑稽部分:如果在声明all规则之后添加下面一行:

  X + = d 

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

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

这不仅仅是循环的最后一次迭代是不好的。基本上调用 $(dst),当调用被调用,而不是在计算新代码时。然后对新的代码进行评估,然后在下一次迭代中将定义扩展 - 用前面的新代码块设置的值。所以,而不是{a,b,c}它给{,a,b}(你必须盯着这一段时间才有意义)。

:加入一些额外的 $ s:

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


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!

解决方案

It's not just the last iteration of the loop that's bad. Basically call expands $(dst) to whatever value it has when call 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:

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

这篇关于奇怪的foreach +在Makefiles中用户定义的函数行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆