为什么我不能在 GNU make 'define' 指令中创建变量
Why can I not create variables in a GNU make 'define' directive
我正在尝试构建 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
时不能创建变量"normally"?
答案源于一个简单的观点,但有很大的影响 - 一个 makefile 有两种方言,1) make 语言本身和 2) 你用于调用 gcc
之类的东西的 shell 语言。
正常 make "rule" 语法的提示:
targets : prerequisites
recipe
虽然 make 目标和先决条件在 make 中
语法,食谱中的东西是 in the shell syntax,而不是 make syntax.
这解释了为什么您不能像这样将 make 变量赋值作为配方的一部分:
all: the_dependencies_of_all
this_will_not_work := because_the_shell_does_not_know_what_this_line_means
在 shell 语法位中,make 进行了三个特殊的文本操作,然后将剩余的字符串逐字传递给 shell。这三个步骤是
- 处理转义的换行符(例如反斜杠后跟换行符)
- 运行 任何 make 函数(如
$(filter ....)
和 $(eval ..)
- 扩展任何 make 目标变量(如
$@
)
在正常情况下,这个 3-steps-then-shell 过程在每个配方行发生一次,所以你的 makefile 配方的每一行都是 运行 在不同的 shell (因此为什么有些调用 make
会产生许多 /bin/sh
sub-processes).
上面的操作 #2 解释了为什么可以在配方中使用 eval
来向配方中添加一些 make 语法。 Eval 将变成一个空字符串,这不会导致 shell 出现问题,但是 make 会在您的语句中计算字符串,因此可以进行变量定义之类的操作。
这个评估发生的精确时刻有点难以确定 - 它似乎发生在变量第一次展开时,这本身取决于您在 makefile 中引用该变量的位置。也许有人可以更清楚地说明这一点,因为当这种情况发生时,使用 -j
标志对 运行 多个并行的配方行的调用产生了后果
更多信息:
我正在尝试构建 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
时不能创建变量"normally"?
答案源于一个简单的观点,但有很大的影响 - 一个 makefile 有两种方言,1) make 语言本身和 2) 你用于调用 gcc
之类的东西的 shell 语言。
正常 make "rule" 语法的提示:
targets : prerequisites
recipe
虽然 make 目标和先决条件在 make 中 语法,食谱中的东西是 in the shell syntax,而不是 make syntax.
这解释了为什么您不能像这样将 make 变量赋值作为配方的一部分:
all: the_dependencies_of_all
this_will_not_work := because_the_shell_does_not_know_what_this_line_means
在 shell 语法位中,make 进行了三个特殊的文本操作,然后将剩余的字符串逐字传递给 shell。这三个步骤是
- 处理转义的换行符(例如反斜杠后跟换行符)
- 运行 任何 make 函数(如
$(filter ....)
和$(eval ..)
- 扩展任何 make 目标变量(如
$@
)
在正常情况下,这个 3-steps-then-shell 过程在每个配方行发生一次,所以你的 makefile 配方的每一行都是 运行 在不同的 shell (因此为什么有些调用 make
会产生许多 /bin/sh
sub-processes).
上面的操作 #2 解释了为什么可以在配方中使用 eval
来向配方中添加一些 make 语法。 Eval 将变成一个空字符串,这不会导致 shell 出现问题,但是 make 会在您的语句中计算字符串,因此可以进行变量定义之类的操作。
这个评估发生的精确时刻有点难以确定 - 它似乎发生在变量第一次展开时,这本身取决于您在 makefile 中引用该变量的位置。也许有人可以更清楚地说明这一点,因为当这种情况发生时,使用 -j
标志对 运行 多个并行的配方行的调用产生了后果
更多信息: