首页 > 解决方案 > 您如何在构建规则中使用(GNU)make 的“简单扩展”变量而不得到最后的定义?

问题描述

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

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

作为我认为可行的一个简单示例,我尝试将以下内容放入 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, get $(Targ), Target is $@. Params are $(Param1) and $(Param2) 

Targ:=C
Param1:=Pc
Param2:=Qc
$(Targ):
    @echo expect C, get $(Targ), 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, get C, Target is B. Params are Pc and Qc

从本质上讲,与每个规则的目标不同,每个规则的目标获取预期的定义,每个规则的命令$(Targ)中的, $(Param1), 和是使用最终定义运行的。$(Param2)

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

标签: makefilegnu-make

解决方案


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

您必须了解何时扩展变量。该文档提供了对此的详细描述读入 makefile 时扩展目标和先决条件,因此Targ使用正在解析 makefile 的值。

当配方被调用时,配方会被扩展,直到所有的 makefile 都被解析并且 make 开始构建目标。在那个时候,当然变量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 $@

推荐阅读