Was ist der Unterschied zwischen der Syntax in Klammern $ () und der geschweiften Klammer $ {} in Makefile?

110

Gibt es Unterschiede beim Aufrufen von Variablen mit Syntax ${var}und $(var)? Zum Beispiel, wie die Variable erweitert wird oder so?

Édouard Lopez
quelle

Antworten:

95

Es gibt keinen Unterschied - sie bedeuten genau dasselbe (in GNU Make und in POSIX make).

Ich denke, das $(round brackets)sieht ordentlicher aus, aber das ist nur eine persönliche Präferenz.

(Andere Antworten verweisen auf die relevanten Abschnitte der GNU Make-Dokumentation und beachten Sie, dass Sie die Syntax nicht in einem einzigen Ausdruck mischen sollten.)

Norman Gray
quelle
11
Ich benutze das $()in make, um zu vermeiden, dass ich (mehr als bereits vorhanden) Verwechslungen zwischen make- und Shell-Variablen verursache. GNU Dokumentation zu Variablenreferenzen erstellen .
Etan Reisner
Vielen Dank an Benutzer @Eloy für den Vorschlag einer Erweiterung dieser Antwort, obwohl ich ihr Kompendium abgelehnt habe, um einfach die wertvollen zusätzlichen Punkte in anderen Antworten zu vermerken.
Norman Gray
1
Einige Werkzeuge werden ihrer Gleichheit möglicherweise nicht gerecht. IntelliJ IDEA wurde deploy: ${DEPS}für mich als Syntaxfehler hervorgehoben, aber deploy: $(DEPS)als korrekt angezeigt, obwohl beide Schreibweisen beim Aufrufen den gleichen Effekt haben make.
Amacleod
45

Im Abschnitt Grundlagen variabler Referenzen aus der GNU makeDokumentation werden keine Unterschiede angegeben :

Um den Wert einer Variablen zu ersetzen, schreiben Sie ein Dollarzeichen gefolgt vom Namen der Variablen in Klammern oder Klammern: entweder $(foo)oder ${foo}ist eine gültige Referenz auf die Variable foo.

Édouard Lopez
quelle
13

Wie bereits richtig ausgeführt, gibt es keinen Unterschied, aber seien Sie vorsichtig, die beiden Arten von Trennzeichen nicht zu mischen, da dies zu kryptischen Fehlern führen kann, wie sie beispielsweise bei unomadh GNU auftreten.

Machen Sie aus der GNU ein Handbuch zur Funktionsaufrufsyntax (Hervorhebung von mir):

[…] Wenn die Argumente selbst andere Funktionsaufrufe oder Variablenreferenzen enthalten, ist es am klügsten, für alle Referenzen dieselbe Art von Trennzeichen zu verwenden. schreibe $(subst a,b,$(x))nicht $(subst a,b,${x}). Dies liegt daran, dass es klarer ist und nur ein Trennzeichentyp übereinstimmt, um das Ende der Referenz zu finden .

Alexandre Perrin
quelle
11

Eigentlich scheint es ziemlich anders zu sein:

, = ,
list = a,b,c
$(info $(subst $(,),-,$(list))_EOL)
$(info $(subst ${,},-,$(list))_EOL)

Ausgänge

a-b-c_EOL
md/init-profile.md:4: *** unterminated variable reference. Stop.

Bisher habe ich diesen Unterschied jedoch nur festgestellt, wenn der Variablenname in $ {...} selbst ein Komma enthält. Ich dachte zuerst, $ {...} würde das Komma nicht als Teil des Wertes erweitern, aber es stellt sich heraus, dass ich es nicht auf diese Weise hacken kann. Ich verstehe das immer noch nicht ... Wenn jemand eine Erklärung hätte, würde ich mich freuen zu wissen!

unomadh
quelle
Basierend auf Edouards Antwort, in der festgestellt wird, dass die GNU-Dokumentation besagt, dass es keinen Unterschied gibt, würde ich vermuten, dass dies nur ein Fehler sein könnte.
Keith M
7
Wie in der Antwort von Alexandre Perrin ausgeführt, sollten die beiden Syntaxen nicht in derselben Zeile gemischt werden.
Lenz
11

Mit dem $ {} -Stil können Sie die make-Regeln in der Shell testen, wenn Sie die entsprechenden Umgebungsvariablen festgelegt haben, da dies mit bash kompatibel ist.

Warren MacEvoy
quelle
3

Es macht einen Unterschied, ob der Ausdruck unausgeglichene Klammern enthält:

${info ${subst ),(,:-)}}
$(info $(subst ),(,:-)))

->

:-(
*** insufficient number of arguments (1) to function 'subst'.  Stop.

Bei Variablenreferenzen macht dies einen Unterschied für Funktionen oder für Variablennamen, die Klammern enthalten (schlechte Idee).

Erik Carstensen
quelle