GNU make 中的多行定义
Multi-line define in GNU make
我试图理解 GNU make 的多行 define
指令,但我做不到。示例:
define A
1
2
endef
all:
@echo W=$(word 1,$(A))
运行 make
产生了我最不期望的结果:
W=1
make: 2: Command not found
make: *** [all] Error 127
$(A)
的一部分似乎溢出了 $(word)
函数。
这是错误还是预期的行为?如果 "spill" 是故意的,那么它是如何起作用的?
P.S。 GNU 在 Linux/x64
上制作 v3.81
$(word)
函数正在 space 上拆分。不白space,spaces.
您的 A
宏中没有 space,因此不会拆分任何内容。
在 1
行上添加尾随 space 或在 2
行上添加前导 space 即可获得预期的行为。
在此处的一些快速测试中,这在 GNU make 3.81、3.82、4.0 和 4.1 中是一致的。
您看到 "spill" 的原因是因为定义的扩展方式。它从字面上扩展,换行和所有。 (想想模板扩展。)
因此 make 将定义扩展到对 $(word 1,...)
的调用中,然后将该结果(包括换行符的整个定义)扩展到配方模板中,最后以两行作为配方执行。
考虑这样的宏:
define somecommands
echo foo
echo bar
echo baz
endef
all:
$(somecommands)
您希望这里发生什么? all
的正文有多少行? 运行这里有多少炮弹?执行什么命令?答案是三行,三个 shell 和三个 echo 命令。
如果不计算换行符,那么您将在一个命令中有效地 运行 echo foo echo bar echo baz
并获得 foo echo bar echo baz
作为输出而不是预期的(并且更有用) foo
、bar
和 baz
在三个不同的行上。
这里要记住的是 make 将每个配方存储为单个递归变量。当 make 决定它必须 运行 您的食谱时,它会扩展该变量。 Make 然后将结果扩展中的 each 行传递到单独的 shell,如果其中任何 shell 执行 return一个错误。
在您的示例中,在 运行ning 之前 make 扩展 @echo W=$(word 1,$(A))
.
$(A)
变为 1¶2
(不知道这在您的浏览器上是什么样子,但我使用 ¶
表示换行符)
- 现在,就 make 而言,
1¶2
是一个单词,所以 $(word 1,1¶2)
自然扩展为 1¶2
(你能看到这是怎么回事了吗?)
- 这使得 make 带有字符串
@echo W=1¶2
。 Make 尽职尽责地将其第一行传递给 shell(没有 @
,因为它对 make 是特殊的)。 shell 执行 echo W=1
.
- make 在 new shell.
中执行 2
- 第二个shell抱怨找不到命令
2
。
所以,是的,预期的行为。
[警告:在上面略作简化,我忽略了 make 能够省略 shell 并在字符串具有的情况下调用命令本身的位其中没有 shell 个元字符]
我试图理解 GNU make 的多行 define
指令,但我做不到。示例:
define A
1
2
endef
all:
@echo W=$(word 1,$(A))
运行 make
产生了我最不期望的结果:
W=1
make: 2: Command not found
make: *** [all] Error 127
$(A)
的一部分似乎溢出了 $(word)
函数。
这是错误还是预期的行为?如果 "spill" 是故意的,那么它是如何起作用的?
P.S。 GNU 在 Linux/x64
上制作 v3.81$(word)
函数正在 space 上拆分。不白space,spaces.
您的 A
宏中没有 space,因此不会拆分任何内容。
在 1
行上添加尾随 space 或在 2
行上添加前导 space 即可获得预期的行为。
在此处的一些快速测试中,这在 GNU make 3.81、3.82、4.0 和 4.1 中是一致的。
您看到 "spill" 的原因是因为定义的扩展方式。它从字面上扩展,换行和所有。 (想想模板扩展。)
因此 make 将定义扩展到对 $(word 1,...)
的调用中,然后将该结果(包括换行符的整个定义)扩展到配方模板中,最后以两行作为配方执行。
考虑这样的宏:
define somecommands
echo foo
echo bar
echo baz
endef
all:
$(somecommands)
您希望这里发生什么? all
的正文有多少行? 运行这里有多少炮弹?执行什么命令?答案是三行,三个 shell 和三个 echo 命令。
如果不计算换行符,那么您将在一个命令中有效地 运行 echo foo echo bar echo baz
并获得 foo echo bar echo baz
作为输出而不是预期的(并且更有用) foo
、bar
和 baz
在三个不同的行上。
这里要记住的是 make 将每个配方存储为单个递归变量。当 make 决定它必须 运行 您的食谱时,它会扩展该变量。 Make 然后将结果扩展中的 each 行传递到单独的 shell,如果其中任何 shell 执行 return一个错误。
在您的示例中,在 运行ning 之前 make 扩展 @echo W=$(word 1,$(A))
.
$(A)
变为1¶2
(不知道这在您的浏览器上是什么样子,但我使用¶
表示换行符)- 现在,就 make 而言,
1¶2
是一个单词,所以$(word 1,1¶2)
自然扩展为1¶2
(你能看到这是怎么回事了吗?) - 这使得 make 带有字符串
@echo W=1¶2
。 Make 尽职尽责地将其第一行传递给 shell(没有@
,因为它对 make 是特殊的)。 shell 执行echo W=1
. - make 在 new shell. 中执行
- 第二个shell抱怨找不到命令
2
。
2
所以,是的,预期的行为。
[警告:在上面略作简化,我忽略了 make 能够省略 shell 并在字符串具有的情况下调用命令本身的位其中没有 shell 个元字符]