[英]Can I simplify this Makefile involving files in subfolders?
例如,我有以下 Makefile 从子目录中的 Markdown 文件生成 PDF 文件:
FOLDERS = f1 f2 f3
.PHONY: $(FOLDERS)
f1: f1/f1.md
cd $@ && pandoc $(notdir $^) -o $(patsubst %.md,%.pdf,$(notdir $^))
f2: f2/f2.md
cd $@ && pandoc $(notdir $^) -o $(patsubst %.md,%.pdf,$(notdir $^))
f3: f3/f3.md
cd $@ && pandoc $(notdir $^) -o $(patsubst %.md,%.pdf,$(notdir $^))
预期的结果是make f1
需要f1/f1.md
的存在,并生成结果 PDF 为f1/f1.pdf
。 f2
和f3
相同。 这可行,但声明似乎不必要地重复。
有没有办法将这三个规则组合成一个通用规则? 也就是说,无需显式写出 PDF 文件或 Markdown 文件的所有路径,因为我可能会动态添加子文件夹,我更愿意只更改第一行中FOLDERS
的定义。 我四处搜索并尝试了一些东西,但我觉得要么我找不到正确的咒语来使用,要么我错过了有关 Makefile 如何工作的知识。 有人可以指出我正确的方向吗?
首先,请注意这里没有充分的理由使用 PHONY 目标,因为这些规则似乎正在构建名称事先已知的文件。 像f1/f1.pdf
这样的目标会好得多。
不幸的是,当词干(例如f1
)在先决条件中重复时,我们不能使用模式规则。 但是“罐头食谱”可以解决问题:
define pdf_template
$(1): $(1)/$(1).md
cd $$@ && pandoc $$(notdir $$^) -o $$(patsubst %.md,%.pdf,$$(notdir $$^))
endef
$(eval $(call pdf_template,f1))
$(eval $(call pdf_template,f2))
$(eval $(call pdf_template,f3))
(注意您必须如何转义模板中的$
符号。)
如果这些$(eval...)
行看起来过于重复,您可以用循环替换它们:
$(foreach folder,$(FOLDERS),$(eval $(call pdf_template,$(folder))))
编辑:想想看,还有另一种方法。 您不能构造多次使用词干的模式规则:
$(FOLDERS): %: %/%.md
cd $@ && ... this won't work
而且您不能使用先决条件列表中的自动变量,因为它们在需要时尚未定义:
$(FOLDERS): $@/$@.md
cd $@ && ... this won't work either
但是如果你使用Secondary Expansion ,你可以在那里使用它们,这会导致 Make 第二次扩展 prereq 列表:
.SECONDEXPANSION:
$(FOLDERS): $$@/$$@.md
cd $@ && ... this works
再次注意转义的$
符号。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.