makefile subst 没有按预期使用 make 变量

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

在 makefile 中,我使用 subst 为 make 变量赋值,并且它在 subst 参数中使用另一个 make 变量,但它并没有真正按预期工作:

USER_HOME := $(shell echo ~$$SUDO_USER)
EXP_VAR := $(subst $$HOME_PATH,$(USER_HOME),"$$HOME_PATH/project/dir"))

all:
    @echo $(USER_HOME)
    @echo $(EXP_VAR)

make 的输出是:

/home/me
~/project/dir

而不是预期的:

/home/me
/home/me/project/dir

所以看来变量

$(USER_HOME)
被正确分配了值
/home/me
,但在 subst 函数中使用时错误地分配了
~

在 subst 函数的演示中,我没有看到任何解释 make 变量的特殊处理的内容:https://www.gnu.org/software/make/manual/html_node/Text-Functions.html

我可以想象 subst 函数不使用

$(USER_HOME)
的值,而是再次运行
$(shell echo ~$$SUDO_USER)
命令,但肯定有一些东西阻止了 shell 命令的扩展,所以它只输出文字字符串
~$$SUDO_USER
并且无法消耗
$SUDO_USER
所以最终变成
~

我可以用我在这里找到的更复杂的命令来解决问题https://unix.stackexchange.com/a/247582,但我不明白为什么我首先需要它:

USER_HOME := $(shell eval echo "~$$SUDO_USER")

在这种情况下,如果我理解正确的话:

  • makefile 展开
    $$
    USER_HOME := $(shell eval echo "~$SUDO_USER")
  • 然后 echo 输出一个字符串:
    ~$SUDO_USER
  • 然后 eval 展开字符串:
    /home/me
  • 这个输出被分配给变量
    $(USER_HOME)
    和 subst 函数

但是为什么 subst 函数不使用 make 变量

$(USER_HOME)
的值,而是再次扩展
$(shell echo ~$$SUDO_USER)
命令?

还有,但不是那么重要的是,为什么 subst 函数中的展开式的工作方式不同?

makefile subst
2个回答
0
投票

你做了很多有问题的事情,导致你感到困惑。

首先,当您尝试调试 makefile 时,切勿使用

@
来隐藏配方的 make 输出。这就像将编译器的输出发送到
/dev/null
。这始终是调试 Makefile 的第一条规则。

其次,当您通过

echo
显示变量时,应该始终引用它们。否则 shell 会获取它们并为您操作它们,这样您就看不到真正的内容。例如,您应该使用
echo '$(USER_HOME)'
而不是
echo $(USER_HOME)

第三,您应该只使用像

$(info ...)
这样的内置make函数来显示变量的值,而不是像
echo
这样的shell命令,因为在shell的调用和生成的输出之间,您无法分辨真正的内容是什么值是。例如,您应该说
$(info USER_HOME is $(USER_HOME))
或类似的内容。

如果您执行了上述所有操作,您对正在发生的事情的理解将会非常不同(注意,我忽略了示例第二行中额外的闭括号的语法错误:我假设这是某种剪切和粘贴神器)。

事实上,这一行:

USER_HOME := $(shell echo ~$$USER)

(假设环境变量

$USER
设置为
me
)将
USER_HOME
的值设置为
~me
,而不是
/home/me
。还有这一行:

EXP_VAR := $(subst $$HOME_PATH,$(USER_HOME),"$$HOME_PATH/project/dir")

EXP_VAR
的值设置为
"~me/project/dir"
(请注意这里的双引号! make 在几乎任何情况下都不知道或关心引号;到目前为止,它们只是另一个字符,如
a
b
就 make 而言)。

现在,如果您查看配方中运行的内容(删除

@
命令之前的
echo
),您将看到它运行:

echo ~me
echo "~me/project/dir"

第一行的输出是

/home/me
,第二行的输出是
~me/project/dir
,因为字符串被引用,shell 不会对文本进行波形符扩展。


0
投票

@MadScientist,我的朋友,你能对我的问题添加一些评论吗? 简单的扩展变量赋值有多重要?

© www.soinside.com 2019 - 2024. All rights reserved.