使用GNU make,我正在尝试解决类似于make recipe execute twice的问题-即,使Makefile配方运行两次。但是,在我的情况下,配方在.SECONDEXPANSION
目标下运行,并且将使用不同的参数调用两次不同的运行,以从同一输入文件生成输出文件的不同版本。也就是说,对于输入文件foo
,此示例Makefile应该可通过make foo.pdf
或make foo.expanded.pdf
进行调用以构建一个.pdf文件,或通过make all
来构建两个.pdf文件:
.PHONY: all
all: foo.pdf foo.expanded.pdf
.SECONDEXPANSION:
%.expanded.pdf %.pdf: %
@echo building $(basename $@)
在该答案给出的两个解决方案中,第一个不合适,因为它总是运行两次规则;我希望它在用户要求时运行两次。
在此发布的第二个解决方案从概念上讲是我想要的并在上面的示例Makefile中实现,只有一个小问题,即它不起作用:尽管all
目标将两个.pdf文件都列为依赖项,运行make all
时只会构建一个。
是否有一种方法可以告诉GNU make在.SECONDEXPANSION
下使用相同的规则来构建两个不同的文件?
编辑:在问题描述中澄清了使用相同的输入文件来构建输出文件的两个版本,并修改了示例Makefile以包括此依赖性。
编辑:我想要一个尽可能可扩展的解决方案;也就是说,如果输入文件名包含点,则应该工作,指定其他输出文件foo.reduced.pdf
仅需要适当调整目标和配方,等等。这限制了依赖于文件名的字符串操作完全按照这个狭窄的示例(例如,如果输入文件可以是%.pdf: $$(firstword $$(subst ., ,$$*))
或foo
,则将规则更改为foo.bar
失败)。
答案 0 :(得分:1)
您的问题与.SECONDEXPANSION
无关。您只需删除它,问题就会一样。
您的问题是您正在使用具有多个目标模式的模式规则,并且期望它的工作原理类似于具有多个目标的显式规则。但事实并非如此(实际上,您不能同时具有模式目标和显式目标的规则)。
对于具有多个目标模式的模式规则,Make将相同的模式与所有%
进行匹配,包括在目标中进行多次匹配,然后假定它只需对该模式执行一次配方,然后它将确定所有匹配的目标。
对于您而言,最好的方法是使用多个规则(我更改了您的食谱,因为将echo
用作制作食谱是一个坏主意):
.PHONY: all
all: foo.expanded.pdf foo.pdf
RECIPE = touch $@
%.expanded.pdf:
$(RECIPE)
%.pdf:
$(RECIPE)
答案 1 :(得分:1)
您可能正在寻找Pattern-specific Variable Values。假设您的配方依赖于名为BUILDFLAGS
的make变量,该变量默认情况下具有值normal
,而对于<< em> expanded ”目标来说,其值为special
。然后是这个Makefile:
BUILDER := builder
BUILDFLAGS := normal
.PHONY: all
all: foo.pdf foo.expanded.pdf
%.expanded.pdf: BUILDFLAGS := special
%.pdf:
$(BUILDER) $(BUILDFLAGS) $@
应该对所有目标使用相同的规则,再加上一个特定于模式的变量值声明,来完成所需的操作。将builder
,normal
和special
替换为适合您的情况。演示:
$ make foo.pdf
builder normal foo.pdf
$ make foo.expanded.pdf
builder special foo.expanded.pdf
$ make
builder normal foo.pdf
builder special foo.expanded.pdf