В чем разница между синтаксисом скобок $ () и фигурных скобок $ {} в Makefile?

111

Есть ли различия в вызове переменных с синтаксисом ${var}и $(var)? Например, как переменная будет расширяться или что-то в этом роде?

Эдуард Лопес
источник

Ответы:

95

Нет никакой разницы - они означают одно и то же (в GNU Make и в POSIX make).

я так думаю $(round brackets) выглядит аккуратнее, но это только личные предпочтения.

(Другие ответы указывают на соответствующие разделы документации GNU Make и обратите внимание, что вы не должны смешивать синтаксисы в одном выражении)

Норман Грей
источник
11
Я использую $()in make, чтобы не вызывать у себя путаницы (большей, чем уже существует) между переменными make и оболочки. GNU Make документация по ссылкам на переменные .
Etan Reisner
Спасибо пользователю @Eloy за предложение расширения к этому ответу, хотя я отклонил их сборник в пользу того, чтобы просто отметить ценные дополнительные баллы в других ответах.
Норман Грей
1
Некоторые инструменты могут не учитывать их сходство. IntelliJ IDEA выделена deploy: ${DEPS}для меня как синтаксическая ошибка, но отображается deploy: $(DEPS)как правильная, хотя оба написания имеют одинаковый эффект при вызове make.
amacleod
46

В разделе " Основы ссылок на переменные " GNU makeдокументации не указано никаких различий :

Чтобы заменить значение переменной, напишите знак доллара, за которым следует имя переменной в круглых или фигурных скобках: либо, $(foo)либо ${foo}является допустимой ссылкой на переменную foo.

Эдуард Лопес
источник
14

Как уже было правильно указано, нет никакой разницы, но будьте осторожны, чтобы не смешивать два типа разделителей, поскольку это может привести к загадочным ошибкам, таким как unomadh GNU make.

Из руководства GNU make по синтаксису вызова функций (выделено мной):

[…] Если сами аргументы содержат вызовы других функций или ссылки на переменные, разумнее всего использовать одинаковые разделители для всех ссылок; пиши $(subst a,b,$(x)), а не $(subst a,b,${x}). Это потому, что он более ясен, и потому , что только один тип разделителя соответствует, чтобы найти конец ссылки .

Александр Перрен
источник
11

На самом деле, вроде бы все иначе:

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

выходы

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

Но до сих пор я обнаружил эту разницу только тогда, когда имя переменной в $ {...} содержит запятую. Сначала я подумал, что $ {...} расширяет запятую не как часть значения, но оказалось, что я не могу взломать его таким образом. Я до сих пор этого не понимаю ... Если бы у кого-то были объяснения, я был бы рад узнать!

уномадх
источник
Основываясь на ответе Эдуарда, в котором отмечается, что в документации GNU make говорится, что нет никакой разницы, я предполагаю, что это может быть просто ошибкой.
Keith M
8
Как указано в ответе Александра Перрена, два синтаксиса не должны смешиваться в одной строке.
lenz
11

Стиль $ {} позволяет тестировать правила make в оболочке, если у вас установлены соответствующие переменные среды, поскольку это совместимо с bash.

Уоррен Макэвой
источник
3

Имеет значение, если выражение содержит несбалансированные скобки:

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

->

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

Для ссылок на переменные это имеет значение для функций или для имен переменных, содержащих скобки (плохая идея).

Эрик Карстенсен
источник