Make中的变量扩展

时间:2015-06-21 15:24:06

标签: variables makefile gnu-make

我们假设我有以下Makefile

N := 1
.PHONY : target_$(N)
target_$(N) :
    @echo $(N)

N := 2
.PHONY : target_$(N)
target_$(N) :
    @echo $(N)

结果是:

$ make target_1
2
$ make target_2
2

有没有办法达到我想要的?我的想法是使用变量作为参数来复制粘贴配方。变量必须在目标名称和目标的配方中进行扩展,也许它也可能出现在依赖项中,但现在还不行。问题是配方扩展似乎在配方执行时发生,但我期待并且需要它在目标扩展的同时发生。

5 个答案:

答案 0 :(得分:2)

另一种选择是使用target-specific variables

N := 1
.PHONY : target_$(N)
target_$(N) :
        @echo $(N)
target_$(N) : N := $(N)

答案 1 :(得分:0)

必要时会发生make变量的扩展。在目标行中,例如target_$(N):,在读取行时发生。在命令(配方)行中,它在执行操作时发生。因此,您可以在读取文件时更改N的值,但最终值是执行命令时将使用的值,因此值2出现两次。 (这样做会导致混淆;不要在生产makefile中使用它。)

AFAIK,没有办法改变这种行为。您无法在读取命令行的位置冻结宏集。某些宏可能直到在命令行中使用之后才被定义,并且您需要能够更改默认规则使用的宏的值等。

答案 2 :(得分:0)

我发现做我想做的最好的方法是从目标名称本身条带化参数:

TARGETS := target_1 target_2
.PHONY : $(TARGETS)
$(TARGETS) :
    $(eval $@_N := $(subst target_,,$@))
    @echo $($@_N)

如果目标名称变得太复杂,可以从参数集开始以编程方式创建它们。

答案 3 :(得分:0)

而不是所有丑陋的嵌套函数调用,我会说KEEP IT SIMPLE并使用命令行变量作为单个目标的参数。

>>> g=[reduce(lambda x,y:{y:x},p) for p in [i[1:][::-1] for i in l]]
>>> dict(next(i.iteritems()) for i in g)
{'v8': {'k3': 0.3}, 'v7': {'k1': {0.1: {'c': {'5': {'r': 9}}}}}}

并使用

调用Makefile
target:
    @echo ${N}
    @if test ${N} -eq 1; then DO THIS; else DO THAT; fi

这样你就拥有了shell控件结构的所有功能。并且您的make target N=1 仍可完全移植到非GNU make。

答案 4 :(得分:0)

我可以使用automatic variables和模式规则来实现您想要的结果:

target_%:
    @echo $*

输出:

$ make target_1
1
$ make target_2
2

要使先决条件列表中的值可用,您需要.SECONDEXPANSION特殊目标:

.SECONDEXPANSION:
target_%: prerequisite_$$*
    @echo $<

prerequisite_%:
    @echo "do something here to build prerequisite nb.$*"

输出:

$ make target_1
do something here to build prerequisite nb.1
prerequisite_1