始终处理最外层的文件扩展名(并沿途剥离扩展名)
Always process outermost file extension (and strip extensions along the way)
我的静态 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
根据扩展的顺序找出要采用的路径。
然而,从文档中,我了解到对 match-all 规则有限制,上述情况是不可能的。
最好的前进方向是什么? 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<>)),$(error Cannot handle files: []))
: ; $(value cmds<>)
all:
endef
emit-rule = $(eval $(call rule-text,,))# 1:suffix 2:basename
emit-hierachy = $(if $(suffix ),$(call emit-rule,,)$(call emit-hierachy,$(suffix ),$(basename )))# 1:suffix 2:basename
emit-rules = $(foreach _,,$(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
Neato,还是什么?
如果你给 emit-rules 一个带有无法识别扩展名的文件(c.html.pp
说),
你得到一个编译时错误:
1:20: *** Cannot handle .pp files: [c.html.pp]. Stop.
编译时?是的,在任何 shell 命令之前是 运行.
你可以通过定义 cmds<.pp>
告诉 make 如何处理 .pp
文件 :-)
对于加分,它也是并行安全的。因此,您可以在 8 CPU 笔记本电脑上使用 -j9
,在 32 CPU 工作站上使用 -j33
。现代生活嗯?
我的静态 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
根据扩展的顺序找出要采用的路径。
然而,从文档中,我了解到对 match-all 规则有限制,上述情况是不可能的。
最好的前进方向是什么? 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<>)),$(error Cannot handle files: []))
: ; $(value cmds<>)
all:
endef
emit-rule = $(eval $(call rule-text,,))# 1:suffix 2:basename
emit-hierachy = $(if $(suffix ),$(call emit-rule,,)$(call emit-hierachy,$(suffix ),$(basename )))# 1:suffix 2:basename
emit-rules = $(foreach _,,$(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
Neato,还是什么?
如果你给 emit-rules 一个带有无法识别扩展名的文件(c.html.pp
说),
你得到一个编译时错误:
1:20: *** Cannot handle .pp files: [c.html.pp]. Stop.
编译时?是的,在任何 shell 命令之前是 运行.
你可以通过定义 cmds<.pp>
告诉 make 如何处理 .pp
文件 :-)
对于加分,它也是并行安全的。因此,您可以在 8 CPU 笔记本电脑上使用 -j9
,在 32 CPU 工作站上使用 -j33
。现代生活嗯?