我对#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;,但这没有改变。)
我希望有人知道更多关于这个的知识,这对我来说似乎是一个微妙的区别,但可能比我现在能理解的要深刻得多。
答案 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
替换为命令。