Makefile 规则中的通配符

Wildcards in Makefile rules

我在 Makefile 中有以下规则

%.00.png: %.dat
    genimg.py $< $@

%.10.png: %.dat
    genimg.py $< $@

%.20.png: %.dat
    genimg.py $< $@

%.30.png: %.dat
    genimg.py $< $@

其中 genimg.py 是一个脚本,它根据 *.dat 文件中的数据和存储在目标文件名中的参数 (00, 10, 20, 30).是否可以将所有这些规则合而为一?我尝试了显而易见的:

%.*.png: %.dat
    genimg.py $< $@

但这不起作用。

不,无法将其合并为一条规则。

但是,您可以 auto-generate 规则。假设你可以把它写成一行,你可以使用类似的东西:

SIZES := 00 10 20 30

$(foreach S,$(SIZES),$(eval %.$S.png: %.dat ; genimg.py $$< $$@))

您可以使用 secondary expansion, the automatic variable $* and the basename 函数实现与此非常接近的结果:

.SECONDEXPANSION:
%.png: $$(basename $$*).dat
    genimg.py $< $@

但这有以下限制,即名为 foo.png 的文件仍将符合此规则并取决于 foo.dat。 如果这不是您的应用程序可接受的行为,您可以使用更详细的版本:

.SECONDEXPANSION:
# This relies on the assumption that there's no file named '/-'
%.png: $$(if $$(word 2,$$(subst ., ,$$*)),$$(word 1,$$(subst ., ,$$*)).dat,/-)
    genimg.py $< $@

但这带来了额外的限制,即名为 a.b.10.png 的文件将作为先决条件 a.dat 而不是预期的 a.b.dat.