替换Makefile模式规则

时间:2018-06-25 21:27:15

标签: makefile

我有这样的文件:

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正确,但是如何用通配符替换更复杂的内容?

2 个答案:

答案 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编程的角度来定义“丑陋”。

相关问题