在Makefile中,括号$()和花括号${}语法有什么区别?

172

使用语法${var}$(var)调用变量有什么区别吗?例如,变量展开的方式或其他方面是否有区别?


2
我模糊地记得,在一些早期版本的make中,只有圆括号($(...))会在make中展开,而不是花括号(${...})。大括号中的变量可以在操作中使用,在那里它们将由shell扩展;在某些情况下,这种区别可能是相关的。 - Chris Dodd
6个回答

149

这两者没有区别——它们在GNU Make和POSIX make中完全相同。

我认为$(圆括号)看起来更整洁,但这只是个人喜好。

(其他答案指向了GNU Make文档的相关部分,并指出不应在单个表达式中混合使用语法)


38
我在Makefile中使用$(),以避免混淆Make和Shell变量,并使自己更加清晰明了。关于变量引用的信息请参考GNU Make文档 - Etan Reisner
感谢用户@Eloy提出了对这个答案的扩展建议,尽管我拒绝了他们的综合建议,而是选择在其他答案中简要记录有价值的额外观点。 - Norman Gray
1
有些工具可能不会识别它们的相同之处。对我来说,IntelliJ IDEA将deploy: ${DEPS}标记为语法错误,但显示deploy: $(DEPS)是正确的,即使在make中调用时两种拼写都具有相同的效果。 - amacleod
ifeq条件语句需要使用圆括号进行相等性检查。你不能在该行中安全地使用花括号。因此,我更喜欢使用$(round brackets) - Teemu Ilmonen
2
不幸的是,“$()”也是有效的POSIX sh家族语法,用于将shell命令的输出捕获为字符串。我没有在GNU make文档中看到它说ifeq不能使用花括号宏扩展。 - mcandre

62

变量引用基础章节来自GNU make文档,声明“没有任何区别”:

要替换变量的值,请在括号或花括号中写入变量名称的美元符号:无论是$(foo)还是${foo}都是对变量foo的有效引用


25
如先前所指出的那样,它们没有区别,但要注意不要混淆这两种分隔符,因为它可能会导致类似于GNU make example by unomadh中的加密错误。
来自 GNU make手册上的函数调用语法(我强调):
“[…]如果参数本身包含其他函数调用或变量引用,则最明智的做法是对所有引用使用相同类型的分隔符;写$(subst a,b,$(x)),而不是$(subst a,b,${x})。这是因为它更清晰,且只有一种类型的分隔符与找到参考的结尾相匹配。”

不小心写成了 $(call-function ${VARIABLE}),发现像 Bash 那样更容易阅读和书写。 - leppaott
2
作为对GNU make手册的批评:然而,给定的示例完全正常工作。所有的$(subst a,b,$(x))$(subst a,b,${x})以及${subst a,b,$(x)}${subst a,b,${x}}都产生相同的结果。只匹配一个分隔符的推理几乎没有意义——当然,如果引用以(开头,它必须以)结尾,$(x}显然是错误的,但似乎与混合不同引用的语法无关。除了像unomadh这样变量名是逗号的病态情况外,混合语法似乎可以工作。 - Mark Gates

19

${}样式允许您在shell中测试make规则,如果您设置了相应的环境变量,则与bash兼容。


12

实际上,看起来相当不同:

, = ,
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.

但到目前为止,我只在变量名称中包含逗号时发现了这种差异。我原以为${...}会将逗号展开为值的一部分,但事实证明我无法以这种方式操纵它。我仍然不理解这个问题… 如果有人有解释,我很乐意知道!


1
根据Edouard的答案,他指出GNU make文档说明没有区别,我猜这可能只是一个错误。 - Keith M
13
正如Alexandre Perrin的答案所指出的那样,在同一行中不应混合使用这两种语法。 - lenz
1
首先,显然,在变量名中不要使用逗号。其次,${info ${subst ${,},-,${list}}_EOL}可以与所有大括号一起使用,因此似乎是混合圆括号和大括号的错误。 - Mark Gates

5

如果表达式中包含不平衡的括号,那么这会产生巨大的影响:

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

->

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

对于变量引用,这对于包含函数的变量或变量名中包含括号(不好的做法)是有影响的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接