makefile 中的函数内部变量是如何扩展的?

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

我正在尝试在我的 makefile 中使用 canned Recipes 为我的项目中的几个子目录动态定义菜谱。然而,我定义的变量并没有像我期望的那样扩展:

define project

$(1)_dir := $(realpath $(2))

.PHONY: $(1)
$(1):
    $(info $(1)_dir = "$($(1)_dir)")

endef

$(eval $(call project,hello_world,./hello-world))

我希望当我运行

hello_world_dir = "/path/to/hello-world"
时,上面的 makefile 会打印
make hello_world
。但是,它会打印
hello_world_dir = ""
。我不明白为什么当变量名被正确替换时嵌套扩展无法正常工作。

makefile
1个回答
0
投票

我不明白为什么当变量名被正确替换时嵌套扩展无法正常工作。

这是一个时间问题。

$(call)
只是一种扩展变量的奇特方式。当您使用它来扩展变量
project
时,其中的所有变量和函数引用也会扩展。此时,
$(1)
是对
call
提供的临时变量的引用,因此
$(1)_dir
会按您的预期展开,无论它出现在
project
的值中的任何位置。该变量的赋值也被正确扩展,但此时它只是文本。此时
$(info ...)
也被扩展,但尚未定义变量
hello_world_dir
——直到结果被
$(eval)
ed 时才会发生这种情况。
$(info)
的输出正确地反映了当时
$(hello_world_dir)
扩展为空。

首先,帮自己一个忙,扔掉内部嵌入的

$(info)
。除了与扩展有关的时间问题之外,它还存在内容问题:它会扩展为空,从而使您的规则
hello_world_dir
的配方仅包含空命令。如果您希望规则在运行时显示文本,请在其中使用
echo
命令。

其次,在规则的配方运行之前您不希望扩展的任何内容都需要通过

$(call)
来防止扩展。更简单的方法之一是将
$
符号加倍来引用。

总的来说,你可能会得到这样的结果:

define project

$(1)_dir := $(realpath $(2))

.PHONY: $(1)
$(1):
        @echo '$(1)_dir = "$$($(1)_dir)"'

endef

$(eval $(call project,hello_world,./hello-world))

当然,请确保

./hello-world
实际上指定了现有文件或目录。

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