繁体   English   中英

我可以简化这个涉及子文件夹中文件的 Makefile 吗?

[英]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 f2f3相同。 这可行,但声明似乎不必要地重复。

有没有办法将这三个规则组合成一个通用规则? 也就是说,无需显式写出 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM