我试图理解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)
函数。
这是一个错误还是预期的行为?如果“泄漏”是故意的,它是如何运作的?
P.S。 GNU在Linux / x64上制作v3.81
答案 0 :(得分:4)
这里要记住的是 make 将每个食谱存储为一个递归变量。在 make 确定它必须运行您的配方时,它会扩展该变量。 生成然后将生成的扩展中的每个行传递给一个单独的shell,如果这些shell执行中的任何一个返回错误,则停止。
在您的示例中,在运行任何内容之前 make 展开@echo W=$(word 1,$(A))
。
$(A)
变为1¶2
(不知道您的浏览器上的内容是什么,但我使用¶
来表示换行符)1¶2
只是一个单词,因此$(word 1,1¶2)
自然会扩展为1¶2
(你能看到它的发展方向吗?了吗?)@echo W=1¶2
。尽职尽责地将第一行传递给shell(没有@
,因为 make 是特殊的。 shell执行echo W=1
。2
。2
。所以,是的,预期的行为。
[警告:上面略微简化,我掩饰了 make 能够忽略shell的位,如果字符串中没有shell元字符,则调用命令本身)
答案 1 :(得分:2)
$(word)
函数在空格上分割。不是空格,空格。
您的A
宏中没有空格,因此无法分割。
在1
行或2
行的前导空格处添加尾随空格,即可获得预期的行为。
这在一些快速测试中对于GNU make 3.81,3.82,4.0和4.1是一致的。
您在调用它时看到“溢出”的原因是因为定义的扩展方式。它按字面意思,换行符和所有内容进行扩展。 (想想模板扩展。)
因此make将define扩展为对$(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
,{{ 1}}和bar
在三个不同的行上。