我正在尝试在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会在其中扩展变量。这样可以进行递归扩展以及创建函数宏。
答案 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/(从最早的博客开始)。