Makefile宏的一级扩展,同时仍可用作宏

时间:2018-10-22 17:06:05

标签: makefile

我正在尝试在Makefile中构建一个宏,该宏可以扩展一次,但在扩展后仍然可以作为宏工作。这对我很有用,因为第一级扩展将填充不会持续的递归参数。这是一个示例:

all: aperiod

TGT = hello
hello.TGT = world
world.TGT = period
define CREATE_TARGET
.SECONDARY: $(1)
$(3)$(1): $(4)$(2)
    @echo $$$$(@)
$(foreach t,$($(1).TGT),$(call CREATE_TARGET,$(t),$(1),$$(1),$$(1)))
endef
define CREATE
$(call CREATE_TARGET,$(TGT),,$$(1),)
endef

CREATE_EXP := $(call CREATE)
TGT :=
$(eval $(call CREATE_EXP,a))

运行make时出错: make:***没有规则将目标aperiod', needed by全部设为'。停止。

TGT包含一组变化的值。我希望CREATE_EXP包含完整的扩展创建方法,该方法接受一个参数来为目标提供前缀。

因此,最佳情况下,我可以呼叫make aperiod并获得世界问候,或在make bperiod之后致电$(eval $(call CREATE_EXP,b))并获得相同的结果

这是一个高度简化的测试用例!

CREATE_EXP的值是正确的,但对于我来说不再适合作为宏了。

$(info $(value CREATE_EXP))

.SECONDARY: hello
$(1)hello: 
    @echo $$(@)
.SECONDARY: world
$(1)world: $(1)hello
    @echo $$(@)
.SECONDARY: period
$(1)period: $(1)world
    @echo $$(@)

我想知道为什么Make会有这种行为,以及是否有更好的方法来完成我要尝试的工作的基本要领。

编辑:尽管我仍然对调用$(call)是否可以创建仍然需要扩展的宏感到好奇,但我找到了解决方案来实现此目的。

define CREATE
define CREATE_EXP
$(call CREATE_TARGET,$(TGT),,$$(1),)
endef
endef

使用$(eval $(call CREATE))

第一次,make会在其中扩展变量。这样可以进行递归扩展以及创建函数宏。

1 个答案:

答案 0 :(得分:0)

我将不得不对“一种更好的方法”进行更深入的思考,并真正理解您正在尝试做的事情,但要回答“为什么make这样表现”​​:您将CREATE_EXP分配为简单的-扩展变量,带有:=

CREATE_EXP := $(call CREATE)

该信息与变量一起存储,并且当make扩展$(CREATE_EXP)之类的内容时,它知道CREATE_EXP的值已被扩展,因此不应再次扩展。实际上,这就是使用:=的全部要点。

以下是可能适合您的替代模型:

$(foreach 1,a,$(eval $(CREATE_EXP)))

(我还没有尝试过)。此处的区别在于,首先我们将变量1设置为foreach变量,然后在该上下文中调用eval。尽管$(CREATE_EXP)会扩展为该值,而不进行进一步扩展,但是eval会将其解析为makefile,并在设置了1=a的情况下再次对其进行扩展。

仅需注意:此:

CREATE_EXP := $(call CREATE)

绝对与此相同:

CREATE_EXP := $(CREATE)

如果不向call传递参数,则与简单的宏扩展相同。

您可能有兴趣在此处阅读以下博客文章集:http://make.mad-scientist.net/category/metaprogramming/(从最早的博客开始)。