2017-02-17 3 views
1

Ich bin verwirrt durch den Unterschied zwischen der "shell" MAKE-Funktion und "$$". In der Dokumentation finde ich:

Die Shell-Funktion nimmt ein einziges Argument, das (wie alle Argumente) erweitert wird und zu einer Subshell zur Ausführung übergeben. Die Standardausgabe des Befehls wird dann gelesen und als Wert der Funktion zurückgegeben.

Ich glaubte, dies war genau was "$$" wurde als gut, aber in diesem kleinen Beispiel tun:

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)" 

der Ausgang ist der folgende:

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

Hinweis hier, dass es sagt "Keine Regel zu Ziel '$ (finden)'", als ob das Argument noch nicht erweitert wurde. (Ich habe auch versucht, die Variable einfach zu erweitern, "b:=$$(...)", aber das änderte nichts).

Ich hoffe, dass jemand das Wissen hat, mehr darüber zu erarbeiten, was mir wie ein subtiler Unterschied erscheint, aber wahrscheinlich ist viel tiefer, als ich in dieser Zeit verstehen kann.

Antwort

2

$(shell ...) ist eine Marke Textfunktion. Make wird das erweitern, also wird in Ihrem Beispiel a, wenn substituiert, zu dem Ergebnis des find Befehls erweitert. (Wenn Sie es zu einer einfach erweiterten Variable gemacht haben, würde der Shell-Befehl natürlich nur einmal ausgewertet werden).

$$ ist nur $ erweitert, so in Ihrem Beispiel b wird als der Wert $(find . -maxdepth 1 -type f -name "Makefile") ersetzen. Dies ist gleich, ob b mit = oder := definiert ist.

Wenn Sie $(b) in einem Befehl wie echo $(b) verwenden, die Shell läuft, die Befehl wird dies als Befehl Substitution. Mit anderen Worten, Sie haben echo $(find ...) als Shell-Befehl.

Die Verwendung von $(b) in einem Make-Ziel oder einer Abhängigkeit führt, wie Sie gesehen haben, zu keiner weiteren Auswertung.

Hier ist ein weiteres Beispiel Makefile, das, wie ich hoffe, zeigt, was vor sich geht. Wir verwenden einfache Anführungszeichen buchstäblich zu zeigen, was die Schale gegeben:

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

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

.PHONY: print 

Das gibt mir

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

, dass im ersten Fall zeigt, die Shell $(echo true) in seinem Befehl gegeben wird, während in der Im zweiten Fall wertet Make echo true aus und ersetzt einfach das Ergebnis true in den Befehl.

+0

Vielen Dank für eine gründliche Antwort, das Beispiel ist ausgezeichnet.Ich muss zugeben, dass die Erweiterung von Variablen für mich immer etwas magisch war. –

Verwandte Themen