Makefile中的括号$()和大括号$ {}语法有什么区别?

Édo*_*pez 90 variables syntax makefile

是否有语法调用变量的任何差异${var}$(var)?例如,变量将被扩展的方式还是什么?

Nor*_*ray 76

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

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

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

  • 我在make中使用`$()`来避免make和shell变量之间的混淆(比已经存在的更多).[GNU Make变量引用文档](http://www.gnu.org/software/make/manual/make.html#Reference). (9认同)
  • 不幸的是,“$()”也是有效的 POSIX sh 系列语法,用于将 shell 命令的输出捕获为字符串。我在 GNU make 文档中没有看到说大括号宏扩展不能在 ifeq 中使用。 (3认同)

Édo*_*pez 38

变量引用的基础部分GNU make文档声明没有差别:

要替换一个变量的值,写一个美元符号后面的括号或大括号的变量名:要么$(foo)或者 ${foo}是一个有效的引用给变量foo中.


小智 12

正如已经正确指出的那样,没有区别但是要小心不要混合两种分隔符,因为它可能导致像unomadh GNU make 这样的神秘错误.

函数调用语法的GNU make手册(强调我的):

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

  • 正如对 GNU make 手册的批评:然而给出的例子却工作得很好。所有“$(subst a,b,$(x))”和“$(subst a,b,${x})”以及“${subst a,b,$(x)}”和“${ subst a,b,${x}}` 产生相同的结果。仅匹配一个分隔符的推理毫无意义——当然,如果引用以(它必须以)结尾,则“$(x}”显然是错误的,但似乎与_不同_引用的混合语法无关。除非病理情况就像 unomadh 的变量名称是逗号一样,混合语法似乎有效。 (2认同)

uno*_*adh 11

实际上,它似乎是完全不同的:

, = ,
list = a,b,c
$(info $(subst $(,),-,$(list))_EOL)
$(info $(subst ${,},-,$(list))_EOL)
Run Code Online (Sandbox Code Playgroud)

输出

a-b-c_EOL
md/init-profile.md:4: *** unterminated variable reference. Stop.
Run Code Online (Sandbox Code Playgroud)

但到目前为止,当$ {...}中的变量名称包含逗号时,我才发现这种差异.我首先想到$ {...}正在扩展逗号而不是作为值的一部分,但事实证明我无法以这种方式破解它.我仍然不明白......如果有人有解释,我会很高兴知道!

  • 正如Alexandre Perrin的回答所指出的,这两种语法不应该在同一行中混合使用. (4认同)

War*_*voy 9

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


小智 5

如果表达式包含不平衡的括号,则会产生影响:

${info ${subst ),(,:-)}}
$(info $(subst ),(,:-)))
Run Code Online (Sandbox Code Playgroud)

->

:-(
*** insufficient number of arguments (1) to function 'subst'.  Stop.
Run Code Online (Sandbox Code Playgroud)

对于变量引用,这会对函数或包含括号的变量名产生影响(坏主意)