2017-02-17 192 views
1

我对“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. 

注在这里它说:“没有规则制定目标'(查找)'”,好像该参数尚未扩展。 (我也试图让变量简单地扩展,“b:=$$(...)”,但这没有改变)。

我希望有人有这方面的知识来详细说明,这对我来说似乎是一个微妙的差异,但可能比我目前能够理解的要深刻得多。

回答

2

$(shell ...)是制作文本函数。 Make会扩展这个,所以在你的例子中,a将被替换为find命令的结果。 (如果你把它做成一个简单扩展的变量,shell命令当然只会被评估一次)。

$$只是扩大到$,所以在你的例子中,b将替代值为$(find . -maxdepth 1 -type f -name "Makefile")。无论b是用=还是:=定义的,这都是一样的。

当您在命令使用$(b)echo $(b),将shell中运行该命令会认为这是命令替换。换句话说,你有echo $(find ...)作为shell命令。

在制作目标或依赖关系中使用$(b)将如您所见,执行任何进一步评估。

下面是另一个示例Makefile,我希望演示发生了什么。在

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 

显示,在第一种情况下,外壳在其命令中给出$(echo true),而:我们使用单引号字面显示壳给出什么第二种情况,进行评估echo true,并简单地将结果true代入命令中。

+0

谢谢你的回答,这个例子非常好。我必须承认,扩展变量对我来说一直有点神奇。 –