2015-04-22 55 views
1

我试图理解GNU make的多行define指令,但我不能。例如:GNU make中的多行定义

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. Linux/x64上的GNU make v3.81

回答

2

$(word)函数在空间上分割。不是空格,空格。

您的A宏中没有空格,因此没有任何分隔。

1行或2行上的前导空格中添加尾部空格,您将得到预期的行为。

这在GNU make 3.81,3.82,4.0和4.1的一些快速测试中是一致的。

你看到“溢出”的原因就像你所说的那样,是因为定义被扩展了。它是从字面上扩展的,换行符和全部。 (Think template expansion。)

因此,将定义扩展到$(word 1,...)的调用中,然后将结果(包括换行符在内的整个定义)展开到配方模板中,最后以两行作为配方执行。

考虑这样一个宏:

define somecommands 
echo foo 
echo bar 
echo baz 
endef 

all: 
    $(somecommands) 

什么你希望发生在这里? all的正文有多少行?这里运行多少个shell?什么命令被执行?答案是三行,三个shell和三个echo命令。

如果换行不计算在内,那么你将有效地在一个命令运行echo foo echo bar echo baz并获得foo echo bar echo baz作为输出,而不是预期(和有用得多)foobarbaz在三个不同的线路。

+0

我不是询问'$(word)'函数。我要求解释'make:2:Command not found'错误信息。我对如何/为什么“2”出现在函数外面并进入make的执行流程感兴趣。这是我所问的问题。 – Dummy00001

+0

您问过“$(A)'的部分溢出$(word)函数外部”。我只是回答了这个问题......虽然我现在看到答案没有在我写的内容中得到充分解释(尽管它在那里)。等一下。 –

+0

不,这不是一个真正的答案。这基本上是官方(主题模糊)文件的推断,根本没有解决含糊不清的问题。我开始认为这只是实现多行定义时的一个错误。例如,尝试在'echo'命令的末尾添加分号并查看错误消息的更改方式。 (如果在Linux下,使用'strace -ff -e execve'运行以查看它的所有荣耀中的废话。) – Dummy00001

4

这里要记住的是,使将每个配方存储为单个递归变量。当使决定它必须运行你的配方时,它展开该变量。 制作然后将每个行传递到单独的shell中,如果其中任何一个shell执行返回错误,则会停止。

在你的例子中,在运行任何东西之前使扩展@echo W=$(word 1,$(A))

  1. $(A)成为1¶2(不知道这是什么看起来像你的浏览器,但我使用表示换行符)
  2. 现在,1¶2是一个单词尽可能使而言,所以$(word 1,1¶2)自然会扩大到1¶2(你能看到这里还在哪里吗?)
  3. 这留下使与字符串@echo W=1¶2。尽责地将第一行传递给shell(没有@,因为这对而言是特殊的,使得)。该shell执行echo W=1
  4. 使执行2新的壳。
  5. 第二个shell声称它找不到命令2

所以,是的,预期的行为。

[警告:在轻微简化上面,我粉饰位,其中使能够在的Elid外壳和调用命令本身如果字符串中有没有shell字符]