这是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
test:
touch $(ENV)
这在返回时起作用
touch test.txt
相反,如果你改成
$$(ENV)
,它会抛出一个错误。
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}"
简而言之,您创建的变量是
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)"