我正在尝试构建一个GNU Make Canned Recipe,如下所示:
define this-will-fail
my_var=1
$(info your variable is $(my_var))
endef
$(this-will-fail)
这会导致错误*** missing separator. Stop.
但是,以下工作符合预期:
define why-does-this-work
$(eval my_var=1)
$(info your variable is $(my_var))
endef
$(why-does-this-work)
打印your variable is 1
。
我正在查看AOSP's build system并经常看到eval
与define
配对的用法。什么是这两个项目之间的关系,为什么我不能创建变量"通常"使用define
时?
答案 0 :(得分:0)
答案源于一个带有大分歧的简单点 - 一个makefile有两个方言,1)make语言本身和2)你用来调用gcc
之类的东西的shell语言。
提醒正常制作“规则”语法:
targets : prerequisites
recipe
虽然make目标和先决条件在make中 语法,配方中的东西是shell语法中的,而不是语法。
这就解释了为什么你不能把make变量作为配方的一部分来做,因为:
all: the_dependencies_of_all
this_will_not_work := because_the_shell_does_not_know_what_this_line_means
在shell语法位中,make执行三个特殊的文本操作,然后将剩余的字符串逐字传递给shell。这三个步骤是
$(filter ....)
和$(eval ..)
$@
)在正常情况下,这个3-steps-then-shell进程每个配方行发生一次,因此makefile配方的每一行都在不同的shell中运行(因此为什么对make
的一些调用会产生许多/bin/sh
子流程)。
上面的操作#2解释了为什么你可以在食谱中使用eval
为你的食谱添加一些make语法。 Eval将变成一个空字符串,这将导致shell没有问题,但make将评估语句中的字符串,因此可以使用变量定义之类的东西。
评估发生的精确时刻有点难以确定 - 它似乎发生在变量首次展开时,它本身取决于你在makefile中引用该变量的位置。也许有人可以更多地澄清这一点,因为当发生这种情况时,对使用-j
标志并行运行多个配方行的make的调用会产生影响
更多信息: