你应该在 Makefile 中为 bash shell 变量使用双美元符号吗?

问题描述 投票:0回答:2

这是Makefile内容:

sgr0 := $(shell tput sgr0)
bold := $(shell tput bold)
orange := $(shell tput setaf 166)

test:
    @echo "$(bold)$(orange)ENV_VARIABLE:(sgr0) ${ENV_VARIABLE}"

您在 bash 中运行以下命令:

export ENV_VARIABLE=value

然后您调用 call

make test
并获得以下输出:

ENV_VARIABLE: value

相反,如果您像这样修改 Makefile

test
目标:

test:
        @echo "$(bold)$(orange)ENV_VARIABLE:(sgr0) $${ENV_VARIABLE}"

调用

make test
的结果是:

ENV_VARIABLE: $ENV_VARIABLE

所以我很困惑,因为 GNU make 官方文档 说使用

$$
作为 shell 变量:

配方中的变量和函数引用具有相同的语法和 makefile 中其他地方引用的语义。他们还有 相同的引用规则:如果你想让美元符号出现在你的 食谱,你必须加倍(‘$$’)。对于像默认 shell 这样的 shell, 使用美元符号引入变量,重要的是要保持 在您的脑海中清楚您要引用的变量是否是 make 变量(使用单个美元符号)或 shell 变量(使用两个 美元符号)。

但是如果我使用

$$
,那么我看不到我的变量是如何扩展的。因此,为了遵循将
$$
用于 shell 变量和
$
用于 make 变量的最佳实践,我需要放弃能够读取 shell 变量如何扩展的能力?

更新:
你执行

export ENV=test.txt

Makefile 内容:

test:
    touch $(ENV)

这在返回时起作用

touch test.txt

相反,如果你改成

$$(ENV)
,它会抛出一个错误。

bash makefile gnu-make
2个回答
0
投票

When you put

$$
in the recipe, it becomes a single
$
.然后命令被传递给 shell,shell 将
$
解释为它扩展的变量的前缀。所以你在
value
输出中得到
echo

要在 shell 中获得文字

$
,您需要在 makefile 中将
$
加倍,并将其放在单引号而不是双引号中

test:
        @echo '$(bold)$(orange)ENV_VARIABLE:(sgr0) $${ENV_VARIABLE}'

或用反斜杠转义(反斜杠也需要加倍,因为反斜杠在 makefile 中有特殊含义)。

test:
        @echo "$(bold)$(orange)ENV_VARIABLE:(sgr0) \\$${ENV_VARIABLE}"

0
投票

简而言之,您创建的变量是

make
变量。在 shell 运行之前,它们被
make
替换。

如果你 wanted 推迟由 shell 执行的扩展,那么是的,你将不得不使用不同的语法(美元符号通过加倍转义,并且没有括号,可能用大括号替换它们)。

export bold sgr0

demo:
    @echo "Make expanded $(bold)bold$(sgr0) before the shell ran"
    @echo "The shell can do this too: $${bold}bold$${sgr0}"

对于后者

echo
工作,你必须包括
export
线。

当变量已经是一个单独的标记时,大括号是不必要的。所以在上面,

$$sgr0
也可以。另见我们什么时候需要用大括号括住 shell 变量?

如果您要尝试

$$(bold)
,那是一个命令替换,其中 shell 将尝试将括号内的文本作为命令运行,并将命令替换替换为该命令的输出。如果括号内的文本不是有效命令,那么您当然会收到错误消息。

weird:
    @echo "Today is $$(date)"
    @echo "You don't want a $$(syntax error)"
© www.soinside.com 2019 - 2024. All rights reserved.