Qual é a diferença entre parênteses $ () e chave $ {} sintaxe no Makefile?

110

Existe alguma diferença na chamada de variáveis ​​com sintaxe ${var}e $(var)? Por exemplo, na forma como a variável será expandida ou algo assim?

Édouard Lopez
fonte

Respostas:

95

Não há diferença - eles significam exatamente o mesmo (no GNU Make e no POSIX make).

Acho que $(round brackets)parece mais arrumado, mas isso é apenas preferência pessoal.

(Outras respostas apontam para as seções relevantes da documentação do GNU Make, e observe que você não deve misturar as sintaxes dentro de uma única expressão)

Norman Gray
fonte
11
Eu uso o $()in make para evitar confusão (mais do que já existe) entre as variáveis ​​make e shell. GNU Faça documentação sobre referências de variáveis .
Etan Reisner
Agradeço ao usuário @Eloy por sugerir uma expansão para esta resposta, embora eu rejeitei seu compêndio em favor de simplesmente observar os valiosos pontos extras em outras respostas.
Norman Gray,
1
Algumas ferramentas podem não respeitar sua semelhança. IntelliJ IDEA destacado deploy: ${DEPS}como um erro de sintaxe para mim, mas mostrado deploy: $(DEPS)como correto, embora ambas as grafias tenham o mesmo efeito quando invocadas em make.
amacleod
45

A seção Noções básicas de referências de variáveis da GNU makedocumentação afirma que não há diferenças :

Para substituir o valor de uma variável, escreva um cifrão seguido do nome da variável entre parênteses ou colchetes: ou $(foo)ou ${foo}é uma referência válida para a variável foo.

Édouard Lopez
fonte
13

Como já corretamente apontado, não há diferença, mas seja cauteloso para não misturar os dois tipos de delimitadores, pois isso pode levar a erros crípticos como o unomadh GNU faz exemplo.

Do GNU make manual sobre a sintaxe de chamada de função (grifo meu):

[...] Se os próprios argumentos contiverem outras chamadas de função ou referências de variáveis, é mais sensato usar o mesmo tipo de delimitadores para todas as referências; escrever $(subst a,b,$(x)), não $(subst a,b,${x}). Isso ocorre porque é mais claro e porque apenas um tipo de delimitador é correspondido para localizar o final da referência .

Alexandre Perrin
fonte
11

Na verdade, parece ser bastante diferente:

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

saídas

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

Mas até agora eu só encontrei essa diferença quando o nome da variável em $ {...} contém uma vírgula. A princípio pensei que $ {...} estava expandindo a vírgula não como parte do valor, mas descobri que não sou capaz de hackear dessa forma. Ainda não entendi ... Se alguém tiver alguma explicação, fico feliz em saber!

unomadh
fonte
Com base na resposta de Edouard, que observa que o GNU faz a documentação afirma que não há diferença, acho que isso pode ser apenas um bug.
Keith M
8
Conforme apontado na resposta de Alexandre Perrin, as duas sintaxes não devem se misturar na mesma linha.
lenz
11

O estilo $ {} permite que você teste as regras do make no shell, se você tiver as variáveis ​​de ambiente correspondentes definidas, desde que seja compatível com o bash.

Warren MacEvoy
fonte
3

Faz diferença se a expressão contiver colchetes não balanceados:

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

->

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

Para referências de variáveis, isso faz diferença para funções ou para nomes de variáveis ​​que contêm colchetes (má ideia)

Erik Carstensen
fonte