我的静态HTML博客中有一堆不同的源文件。最外层的扩展说明了接下来要处理的格式。
示例:源文件article.html.md.gz
(目标为article.html
)应先由gunzip
处理,然后由我的降价处理器处理。
更多详细信息:
article.html.gz
)article.html
理想情况下,我希望只编写如下规则:
...
all-articles: $(ALL_HTML_FILES)
%: %.gz
gunzip ...
%: %.md
markdown ...
%: %.zip
unzip ...
然后让make
根据扩展顺序找出要采用的路径。
但是,从文档中,我了解到“全部匹配”规则存在一些限制,而上述情况是不可能的。
最好的前进方向是什么? make
可以完全解决这种情况吗?
扩展是示例。我实际的源文件更有意义:-)
答案 0 :(得分:2)
我在度假,所以我要咬。
我不是模式规则的忠实拥护者,它们对我的口味来说过于严格,但同时又过于随意。您可以通过纯粹的方式很好地实现您想要的东西:
.DELETE_ON_ERROR:
all: # Default target
files := a.html.md.gz b.html.gz
cmds<.gz> = gzip -d <$< >$@
cmds<.md> = mdtool $< -o $@
define rule-text # 1:suffix 2:basename
$(if $(filter undefined,$(flavor cmds<$1>)),$(error Cannot handle $1 files: [$2$1]))
$2: $2$1 ; $(value cmds<$1>)
all: $2
endef
emit-rule = $(eval $(call rule-text,$1,$2))# 1:suffix 2:basename
emit-hierachy = $(if $(suffix $2),$(call emit-rule,$1,$2)$(call emit-hierachy,$(suffix $2),$(basename $2)))# 1:suffix 2:basename
emit-rules = $(foreach _,$1,$(call emit-hierachy,$(suffix $_),$(basename $_)))# 1:list of source files
$(call emit-rules,${files})
.PHONY: all
all: ; : $@ Success
此处的关键是将$files
设置为文件列表。
然后,此列表将传递到 emit-rules 。
emit-rules 一次将每个文件传递给 emit-hierachy 。
emit-hierachy 依次剥离每个扩展名,
生成适当的 make 语法,并将其传递给$(eval …)
。
emit-hierachy 一直进行到文件只剩下一个扩展名为止。
因此a.html.md.gz
成为以下 make 语法:
a.html.md: a.html.md.gz ; gunzip <$< >$@
a.html: a.html.md ; mdtool $< -o $@
all: a.html
类似地,b.html.gz
变为:
b.html: b.html.gz ; gunzip <$< >$@
all: b.html
尼托,还是什么?
如果您给 emit-rules 文件添加了无法识别的扩展名(例如c.html.pp
),
您会收到编译时错误:
1:20: *** Cannot handle .pp files: [c.html.pp]. Stop.
编译时?是的,在运行任何shell命令之前。
您可以通过定义.pp
来告诉 make 如何处理cmds<.pp>
文件:-)
对于加分点,它也是并行安全的。因此,您可以在8 CPU笔记本电脑上使用-j9
,在32 CPU工作站上使用-j33
。现代生活是吗?