如何在构建规则中使用GNUmake的“简单扩展”变量,而没有得到最后的定义?

问题描述

我需要编写一组复杂的规则来生成大量的“参数化”输出文件,并认为,与其手动将它们全部扩展,我可以反复“包含”带有模板集的模板文件规则和使用(GNU)make的工具,它允许"simply expanded"变量避免痛苦。

过去,我一直在使用“递归扩展”变量方法,因此这对我来说是新的

作为我想法可行的简单示例,我尝试将以下内容放入Makefile

Targ:=A
Param1:=Pa
Param2:=Qa
$(Targ):
    @echo expect A,get $(Targ),Target is $@. Params are $(Param1) and $(Param2) 

Targ:=B
Param1:=Pb
Param2:=Qb
$(Targ):
    @echo expect B,Target is $@. Params are $(Param1) and $(Param2) 

Targ:=C
Param1:=Pc
Param2:=Qc
$(Targ):
    @echo expect C,Target is $@. Params are $(Param1) and $(Param2) 

最终的计划是用包含数十个不同规则的包含文件替换规则,每个规则都引用各种“参数”变量。

但是,我得到的是...

prompt> make A
expect A,get C,Target is A. Params are Pc and Qc


prompt> make B
expect B,Target is B. Params are Pc and Qc

本质上,与每个规则的目标不同,选择目标定义,每个规则的中的$(Targ)$(Param1)$(Param2)命令而是使用 final 定义运行。

有人知道如何防止这种情况发生,即在Makefile中遇到该定义时,如何强制命令使用该定义?

解决方法

简单扩展与递归扩展在这里没有什么区别;无论使用哪种方式,您都会看到相同的行为。一个GNU make变量是 global ,显然只能有一个值。

您必须了解何时扩展变量。文档提供了detailed description的内容。在读取文件时会扩展目标和先决条件,因此将使用解析文件时Targ的值。

将在调用配方时扩展配方 ,直到解析所有makefile并开始构建目标时,才会扩展配方。当然,那时变量Targ具有其最后的设置值。

在不知道您的makefile真正起作用的情况下,很难提出替代方案。一种选择是使用特定于目标的变量:

Targ := A
$(Targ): LocalTarg := $(Targ)
$(Targ):
        @echo expect A,get $(LocalTarg),Target is $@

另一种选择是使用构造的变量名:

Targ := A
Targ_$(Targ) := $(Targ)
$(Targ):
        @echo expect A,get $(Targ_$@),Target is $@
,

很抱歉回答我自己的问题,但是我现在意识到可以递归运行make来解决我遇到的问题。

例如如果规则的参数变量是Targ,Param1和Param2,则

#Set up "default" values for the parameters (As @madscientist points out,#these will safely be overridden by the defs on the @(make) commands below

Targ=XXXXXXXXXX
Param=XXXXXXXXXX
Param2=XXXXXXXXXX
Recursing=

#
# define N (==3) templated rule(s)
#
$(Targ)%a:
    @echo Run Combo_a $(Targ) $(Param1) $(Param2) $@

$(Targ)%b:
    @echo Run Combo_b $(Targ) $(Param2) $(Param1) reversed $@

$(Targ)%c:
    @echo Run Combo_c  $(Param1) $(Targ) $(Param2) mixed again $@

#
#Enumerate "M" (==2) sets of parameters,# (Except if we are already recursing because unrecognised targets may cause
# it to descend forever)
#
ifneq ($(Recursing),Yes)
Set1%:
    @$(MAKE) Targ=Set1 Param1=foo Param2=bar Recursing=Yes $@

Set2%:
    @$(MAKE) Targ=Set2 Param1=ray Param2=tracing Recursing=Yes $@
endif

然后,这将允许N * M个不同的组合用于N + M个打字费用。 例如。 (从make递归中删除邮件)

>make Set1.a
Run Combo_a Set1 foo bar Set1.a

>make Set2.c
Run Combo_c ray Set2 tracing mixed again Set2.c