Makefile 中的括号 $() 和大括号 $ 语法有啥区别?

Posted

技术标签:

【中文标题】Makefile 中的括号 $() 和大括号 $ 语法有啥区别?【英文标题】:What's the difference between parenthesis $() and curly bracket $ syntax in Makefile?Makefile 中的括号 $() 和大括号 $ 语法有什么区别? 【发布时间】:2014-09-30 21:03:24 【问题描述】:

$var$(var)语法调用变量有什么不同吗?例如,变量将被扩展的方式或其他什么?

【问题讨论】:

我有一个模糊的回忆,在 make 的一些早期版本中,只有括号 ($(...)) 会在 make 中扩展,而 not 大括号 ( $...)。然后可以将带有大括号的变量用于将由 shell 扩展的操作中;在某些情况下,这种区别可能是相关的。 【参考方案1】:

没有区别——它们的意思完全相同(在 GNU Make 和 POSIX make 中)。

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

(其他答案指向 GNU Make 文档的相关部分,请注意,您不应在单个表达式中混合语法)

【讨论】:

我在 make 中使用 $() 以避免在 make 和 shell 变量之间造成混淆(比已经存在的更多)。 GNU Make documentation on variable references. 感谢用户 @Eloy 建议扩展此答案,尽管我拒绝了他们的纲要,而只是简单地指出其他答案中有价值的额外点。 有些工具可能不尊重它们的相同性。 IntelliJ IDEA 将 deploy: $DEPS 突出显示为我的语法错误,但将 deploy: $(DEPS) 显示为正确,即使在 make 中调用时两种拼写具有相同的效果。 ifeq 条件要求使用圆括号进行相等检查。您不能在该行上安全地使用花括号。因此,我倾向于$(round brackets)【参考方案2】:

来自GNU make 文档状态的Basics of Variable References section 没有差异

要替换变量的值,请写一个美元符号,后跟 括号或大括号中的变量名称:$(foo)$foo 是对变量 foo 的有效引用

【讨论】:

【参考方案3】:

正如已经正确指出的那样,没有区别请注意不要混合使用这两种分隔符,因为这可能会导致像 GNU make example by unomadh 这样的神秘错误。 p>

来自the GNU make manual on the Function Call Syntax(强调我的):

[…] 如果参数本身包含其他函数调用或变量引用,则对所有引用使用相同类型的分隔符是最明智的;写$(subst a,b,$(x)),而不是$(subst a,b,$x)。这是因为它更清晰,并且因为只匹配一种类型的分隔符才能找到引用的结尾

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

其实,好像还挺不一样的:

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

但到目前为止,我仅在 $... 中的变量名包含逗号时才发现这种差异。我首先认为 $... 将逗号扩展为值的一部分,但事实证明我无法以这种方式破解它。我还是不明白...如果有人有解释,我很乐意知道!

【讨论】:

基于 Edouard 的回答,其中指出 GNU make 文档声明没有区别,我猜这可能只是一个错误。 正如 Alexandre Perrin 的回答中所指出的,这两种语法不应在同一行中混合使用。【参考方案6】:

如果表达式包含不平衡的括号会有所不同:

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

->

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

对于变量引用,这对于函数或包含括号的变量名(坏主意)会有所不同

【讨论】:

以上是关于Makefile 中的括号 $() 和大括号 $ 语法有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

用引号和大括号反应原生属性值

Replace() 不适用于多行字符串和大括号

VS Code 突然停止右括号、方括号和大括号

scala map 后加小括号和大括号的区别

Javascript大括号和中括号的区别

转义引号和大括号时遇到问题