Make 的主要缺点之一是它无法以合理的方式处理通配符。
这是一种粗略但有效的方法。使用 Make 的 string manipulation functions 将目标拆分为多个部分(例如“img somename 1”)并选择第二个,然后添加“.py”。并且不要忘记使用.SECONDEXPANSION 将所有这些推迟到通配符实际具有值为止。
.SECONDEXPANSION:
%.png: $$(word 2,$$(subst _, ,%)).py
python $<
编辑:如果目标名称可以包含下划线,那么模式规则方法会变得非常笨拙。这是一个更好的方法。假设我们只有一个目标,img_some_name_1.png,那么我们可以这样写规则:
img_some_name_1.png: some_name.py
python $<
现在我们想变得聪明(和懒惰),让 Make 从目标名称构造脚本名称:
IMAGE := img_some_name_1.png
SCRAP := $(lastword $(subst _, ,$(IMAGE))) # this is 1.png
SCRIPT := $(patsubst img_%_$(SCRAP),%.py, $(IMAGE)) # this is some_name.py
$(IMAGE): $(SCRIPT)
@echo python $<
我们不想为每个目标都输入所有这些,所以我们定义了一个模板:
define thing
IMAGE := $(1)
SCRAP := $$(lastword $$(subst _, ,$$(IMAGE)))
SCRIPT := $$(patsubst img_%_$$(SCRAP),%.py, $$(IMAGE))
$$(IMAGE): $$(SCRIPT)
python $$<
endef
$(eval $(call thing, img_some_name_1.png))
一旦我们确认了这么多工作(在我们的 Make 版本上),我们就会遍历目标列表:
IMAGES=img_some_name_1.png img_somename_2.png img_some_other_name_1.png
allImages: $(IMAGES)
$(foreach IMAGE, $(IMAGES), $(eval $(call thing, $(IMAGE))))