" $(shell ...)"之间的区别和" $$(...)" in make

时间:2017-02-17 07:47:03

标签: gnu-make

我对#34; shell"之间的差异感到困惑。 MAKE功能和" $$"。在文档中我找到:

  

shell函数接受一个扩展的参数(与所有参数一样)并传递给子shell进行执行。然后读取命令的标准输出并作为函数的值返回。

我相信这是完全什么" $$"但是在这个小例子中也是如此:

a = $(shell find . -maxdepth 1 -type f -name "Makefile")
b = $$(find . -maxdepth 1 -type f -name "Makefile")

.PHONY: all A B

all: A B

A: $(a)
    @echo "Target: $(@)"
    @echo "Prereq: $(<)"
    @echo "Var a:  $(a)"
    @echo "Var b:  $(b)"

B: $(b)
    @echo "Target: $(@)"
    @echo "Prereq: $(<)"
    @echo "Var a:  $(a)"
    @echo "Var b:  $(b)"

输出如下:

Target: A
Prereq: Makefile
Var a:  ./Makefile
Var b:  ./Makefile
make: *** No rule to make target '$(find)', needed by 'B'.  Stop.

请注意,它表示&#34;没有规则可以使目标&#39; $(查找)&#39; &#34;,就好像参数尚未展开一样。 (我也尝试简单地扩展变量,&#34; b:=$$(...)&#34;,但这没有改变。)

我希望有人知道更多关于这个的知识,这对我来说似乎是一个微妙的区别,但可能比我现在能理解的要深刻得多。

1 个答案:

答案 0 :(得分:2)

$(shell ...)是一个Make 文字功能。 Make会对此进行扩展,因此在您的示例中,a会在替换时展开为find命令的结果。 (如果你把它作为一个简单扩展的变量,那么shell命令只会被评估一次)。

$$刚刚扩展为$,因此在您的示例中,b将替换为值$(find . -maxdepth 1 -type f -name "Makefile")。无论使用b还是=定义:=,都是一样的。

$(b)命令中使用echo $(b)时,运行该命令的 shell 会将此视为命令替换。换句话说,您有echo $(find ...)作为shell命令。

如您所见,在Make目标或依赖项中使用$(b)将不再执行进一步评估。

这是另一个示例Makefile,我希望能够展示正在发生的事情。我们使用单引号从字面上显示shell的内容:

a = $$(echo true)
b = $(shell echo true)

print:
    echo '$$a: $a' = "$a"
    echo '$$b: $b' = "$b"

.PHONY: print

这给了我

echo '$a: $(echo true)' = "$(echo true)"
$a: $(echo true) = true
echo '$b: true' = "true"
$b: true = true

显示在第一种情况下,shell在其命令中被赋予$(echo true),而在第二种情况下,Make评估echo true并简单地将结果true替换为命令。