我有这样的文件:
IMAGES=img_some_name_1.png img_somename_2.png img_some_other_name_1.png ...
其中前两个是通过脚本构建的
some_name.py
第三个是
some_other_name.py
,依此类推。我想写这样的makefile规则
%.png: $(remove 'img_' and replace '_?.png' with '.py')
python $<
如何在依赖项中进行替换?我认为此answer正确,但是如何用通配符替换更复杂的内容?
答案 0 :(得分:3)
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))))
答案 1 :(得分:1)
如果您愿意动态构建规则,则可以使用glob-match
function from gmtt。您可以按照@Beta的建议,将所有内容塞入.SECONDEXPANSION
表达式中,但我认为这样做会很丑陋。
include gmtt.mk
IMAGES = img_some_name_1.png img_somename_2.png img_some_other_name_1.png
$(info $(foreach fname,$(IMAGES),$(call glob-match,$(fname),img_*_?.png)))
输出:
img_ some_name _ 1 .png img_ somename _ 2 .png img_ some_other_name _ 1 .png
现在我尝试了,毕竟看起来并不那么丑(*):
%.png: $$(word 2,$$(call glob-match,%,img_*_?)).py
但是,如果您更多地参与到字符串构建约定中,它仍然会令人讨厌。
(*),用于从GNUmake编程的角度来定义“丑陋”。