始终处理最外层文件扩展名(并沿途展开条带扩展)

问题描述 投票:1回答:1

我的静态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可以处理这种情况吗?

扩展是由示例组成的。我的实际源文件更有意义:-)

makefile gnu-make
1个回答
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-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。现代生活呃?

© www.soinside.com 2019 - 2024. All rights reserved.