Jaka jest różnica między składnią nawiasów $ () i nawiasów klamrowych $ {} w Makefile?

111

Czy są jakieś różnice w wywoływaniu zmiennych ze składnią ${var}i $(var)? Na przykład, w jaki sposób zmienna zostanie rozwinięta, czy coś?

Édouard Lopez
źródło

Odpowiedzi:

95

Nie ma różnicy - mają na myśli dokładnie to samo (w GNU Make i POSIX make).

Myślę, że $(round brackets)wygląda to bardziej schludnie, ale to tylko osobiste preferencje.

(Inne odpowiedzi wskazują na odpowiednie sekcje dokumentacji GNU Make i zauważ, że nie powinieneś mieszać składni w jednym wyrażeniu)

Norman Gray
źródło
11
Używam $()make, aby uniknąć pomieszania (większego niż już istnieje) między zmiennymi make i shell. GNU Tworzy dokumentację dotyczącą odwołań do zmiennych .
Etan Reisner
Podziękowania dla użytkownika @Eloy za zasugerowanie rozszerzenia tej odpowiedzi, mimo że odrzuciłem ich kompendium na rzecz po prostu odnotowania cennych dodatkowych punktów w innych odpowiedziach.
Norman Gray
1
Niektóre narzędzia mogą nie honorować ich identyczności. IntelliJ IDEA wyróżniony deploy: ${DEPS}jako błąd składniowy, ale pokazany deploy: $(DEPS)jako poprawny, mimo że obie pisownie mają ten sam efekt po wywołaniu make.
amacleod
46

W sekcji Podstawy odwołań do zmiennych w GNU makedokumentacji nie podano żadnych różnic :

Aby podstawić wartość zmiennej, napisz znak dolara, po którym następuje nazwa zmiennej w nawiasach lub nawiasach klamrowych: albo $(foo)albo ${foo}jest poprawnym odniesieniem do zmiennej foo.

Édouard Lopez
źródło
14

Jak już słusznie wskazano, nie ma różnicy, ale uważaj, aby nie mieszać dwóch rodzajów separatorów, ponieważ może to prowadzić do tajemniczych błędów, takich jak unomadh GNU make.

Z podręcznika GNU make na temat składni wywołania funkcji (moje wyróżnienie):

[…] Jeśli same argumenty zawierają inne wywołania funkcji lub odwołania do zmiennych, najrozsądniej jest użyć tego samego rodzaju separatorów dla wszystkich odwołań; pisz $(subst a,b,$(x)), nie $(subst a,b,${x}). Dzieje się tak, ponieważ jest jaśniejszy i ponieważ tylko jeden typ separatora jest dopasowywany w celu znalezienia końca odwołania .

Alexandre Perrin
źródło
11

W rzeczywistości wydaje się być całkiem inny:

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

wyjścia

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

Ale jak dotąd zauważyłem tę różnicę tylko wtedy, gdy nazwa zmiennej w $ {...} zawiera w sobie przecinek. Na początku myślałem, że $ {...} rozszerza przecinek nie jako część wartości, ale okazuje się, że nie jestem w stanie tego zhakować w ten sposób. Nadal tego nie rozumiem ... Gdyby ktoś miał wyjaśnienie, byłbym szczęśliwy, gdyby się dowiedział!

unomadh
źródło
Opierając się na odpowiedzi Edouarda, która zauważa, że ​​dokumentacja GNU stwierdza, że ​​nie ma różnicy, myślę, że to może być po prostu błąd.
Keith M
8
Jak wskazano w odpowiedzi Alexandre Perrina, tych dwóch składni nie należy mieszać w tej samej linii.
Lenz
11

Styl $ {} pozwala przetestować reguły make w powłoce, jeśli masz ustawione odpowiednie zmienne środowiskowe, ponieważ jest to zgodne z bash.

Warren MacEvoy
źródło
3

Ma znaczenie, jeśli wyrażenie zawiera niezrównoważone nawiasy:

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

->

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

W przypadku odwołań do zmiennych ma to znaczenie dla funkcji lub nazw zmiennych zawierających nawiasy (zły pomysł)

Erik Carstensen
źródło