我的静态HTML博客中有很多不同的源文件。最外面的扩展解释了接下来要处理的格式。
示例:源文件article.html.md.gz
(带有目标article.html
)应由gunzip
处理,然后由我的markdown处理器处理。
更多详情:
article.html.gz
)article.html
理想情况下,我希望只按如下方式编写规则:
...
all-articles: $(ALL_HTML_FILES)
%: %.gz
gunzip ...
%: %.md
markdown ...
%: %.zip
unzip ...
让make
根据扩展序列找出要走的路径。
但是,从文档中我了解到匹配所有规则存在约束,上述情况是不可能的。
前进的最佳方式是什么? make
可以处理这种情况吗?
扩展是由示例组成的。我的实际源文件更有意义:-)
我正在度假,所以我会咬人。
我不是模式规则的粉丝,它们太受限制,但同时又太随意了我的口味。你可以在纯粹的制作中很好地实现你想要的东西:
.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-hierarchy依次剥离每个扩展,生成相应的make语法,并将其传递给qazxsw poi。 emit-hierarchy继续执行,直到文件只剩下一个扩展名。
因此$(eval …)
成为这个make语法:
a.html.md.gz
同样,a.html.md: a.html.md.gz ; gunzip <$< >$@
a.html: a.html.md ; mdtool $< -o $@
all: a.html
成为:
b.html.gz
Neato,还是什么?
如果你给emit-rules一个带有无法识别的扩展名的文件(b.html: b.html.gz ; gunzip <$< >$@
all: b.html
说),你会得到一个编译时错误:
c.html.pp
编译时?是的,在运行任何shell命令之前。
您可以通过定义1:20: *** Cannot handle .pp files: [c.html.pp]. Stop.
告诉make如何处理.pp
文件:-)
对于额外的积分,它也是平行安全的。因此,您可以在8 CPU笔记本电脑上使用cmds<.pp>
,在32 CPU工作站上使用-j9
。现代生活呃?