这是一个玩具Makefile。 我想创建文件“a”,“b”,“c”以及“a.out”,“b.out”,“c.out”。
LIST=a b c
all: $(addsuffix .out,$(LIST))
define FUN
in := $(1)
out := $(1).out
$$(in) :
echo $(1) > $$(in)
$$(out) : $$(in)
echo $$(in) > $$(out)
endef
$(foreach p,$(LIST),\
$(eval $(call FUN,$(p))))
当我使用“make -n”测试运行它时,版本GNU Make 4.1, 执行的实际命令是:
echo a > c
echo c > c.out
echo b > c
echo c > c.out
echo c > c
echo c > c.out
然而,预期的结果是:
echo a > a
echo a > a.out
echo b > b
echo b > b.out
echo c > c
echo c > c.out
有人可以帮助解释Makefile的行为或如何修复此脚本吗?感谢。
答案 0 :(得分:3)
为什么不在任何地方使用$1
变量而不是创建新变量?没有规则说你必须在扩展中使用变量。你可以把它写成:
define FUN
$1 :
echo $1 > $1
$1.out : $1
echo $1 > $1.out
endef
如果您不想这样做,可以像这样使用automatic variables:
define FUN
$1 :
echo $$@ > $$@
$1.out : $1
echo $$< > $$@
endef
修改强>
如果没有看到某种现实的例子,很难判断。对你的问题的简短回答是否定的,没有什么神奇的方法来创造&#34;变量范围&#34;在makefile中。
您应始终使用$@
,$<
和其他自动变量。这就是他们的目标。如果您有其他需要的变量赋值,并且您希望将它们设置为变量而不是直接使用调用参数,则只有两个选择:特定于目标的变量或constructed macro names。
但我并没有真正看到&#34;特定目标变量列表的问题&#34;。为什么还要全局设置变量然后再将它们设置为特定目标?如果您只是将它们直接设置为特定于目标的变量,则只需编写一次。它并不清楚你到底发现了什么&#34;尴尬&#34;关于它们的使用,所以我不能说这是否足够。
此外,您应该在主目标上设置特定于目标的变量,而不是先决条件,因为特定于目标的变量是&#34;继承&#34;通过先决条件清单。
所以,就像这样:
define FUN
$1.out : FOO = $(some complex thing)
$1 :
echo $$(FOO) > $$@
$1.out : $1
echo $$(FOO) from $$< > $$@
endef
答案 1 :(得分:1)
这是我尝试回答这个问题,它附带了对代码的繁琐修复。我在这里发布的原因是等待更好的答案。
从GNU Make手册(https://www.gnu.org/software/make/manual/make.html#Reading-Makefiles),立即评估目标和先决条件,并延迟配方部分。
在我的示例中,立即评估$$(out) : $$(in)
。这就是我的预期。但echo $$(in) > $$(out)
稍后会扩展。那时,$$(in)
变为c
,$$(out)
变为c.out
。但那不是我想要的。
在我看来,一个尴尬的解决方法是使用特定于目标的变量(https://www.gnu.org/software/make/manual/make.html#Target_002dspecific)。现在Makefile如下所示:
LIST=a b c
all: $(addsuffix .out,$(LIST))
define FUN
in := $(1)
out := $(1).out
$$(in) : in=$(1)
$$(in) :
echo $(1) > $$(in)
$$(out) : $$(in)
echo $$(in) > $$(out)
endef
$(foreach p,$(LIST),\
$(eval $(call FUN,$(p))))
特定于目标的变量在$$(in) : in=$(1)
中指定。
但是,如果配方部件中有多个变量,则必须添加多个特定于目标的变量,这看起来不太好。