我们假设我有以下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
有没有办法达到我想要的?我的想法是使用变量作为参数来复制粘贴配方。变量必须在目标名称和目标的配方中进行扩展,也许它也可能出现在依赖项中,但现在还不行。问题是配方扩展似乎在配方执行时发生,但我期待并且需要它在目标扩展的同时发生。
答案 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}}}}}}
并使用
调用Makefiletarget:
@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