2017-02-17 200 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

謝謝你的回答,這個例子非常好。我必須承認,擴展變量對我來說一直有點神奇。 –

相關問題