用于编译所有LaTeX文件的Makefile

编程语言 2026-07-12

我有一个目录,其中包含分布在不同子目录下的 .tex 文件。我想用 latexmk -pdf -pdflatex="pdflatex --shell-escape %O %S" 将它们全部编译,生成的文件(PDF以及中间输出)都放在与源文件位于同一子目录中。原因是某些TeX文件在不同子目录中同名,例如 ./foo/baz.tex./bar/baz.tex 应分别编译成 ./foo/baz.pdf./bar/baz.pdf。这些 .tex 文件当前都位于深度为2 的子目录中(./foo/bar/baz.tex),但理想情况下,我希望这个方案能够适用于该目录中任意深度的TeX文件。

我想为这个仓库写一个Makefile,但有点卡壳。目前我有:

LATEXMK = latexmk -pdf -pdflatex="pdflatex --shell-escape %O %S"
SRCS := $(shell find -name '*.tex')
PDFS := $(addsuffix .pdf,$(basename $(SRCS)))

.PHONY: all

all: $(PDFS)

$(PDFS): $(SRCS)
    $(LATEXMK) $<

这似乎只会编译第一个TeX文件(因为 $< 的原因;不过我不确定如何指定“逐个/按每个”之类的变量),并把输出放在根目录,而不是TeX文件所在的子目录中。

我曾考虑仅为此写一个简单的shell脚本,但我想用Makefile,以便未修改的TeX文件不会重新编译;这个目录里有相当多的TeX文件。不幸的是,我以前只写过一些简单的Makefile,因此对如何让这件事在这方面工作有点卡。非常感谢你提供的任何线索。

解决方案

这似乎只编译第一份TeX文件(因为 $< 的原因;不过我不确定如何在配方中指定“逐个”的变量)并将输出放在根目录,而不是TeX文件所在的子目录中。

不仅仅是它只编译了列出的第一份TeX源,而且它会把同一份源用于每一个请求的PDF。与此同时,如果任一TeX源比某个PDF更旧,它就会被视为过时。

一个具有多个目标的规则意味着该配方及其所有前置条件对每一个目标都适用。要让这合理,这样的规则通常在配方中使用 $@ 这个特殊变量来命名正在构建的具体目标。

如果你使用GNU make,那么你可能想改用模式规则,可能像这样:

%.pdf: %.tex
        $(LATEXMK) $<

这表示任何名称以 .pdf 结尾的目标都可以从相应以 .tex 结尾的文件构建(如果该文件存在),通过应用指定的配方。你已经有一个针对 all 的规则,指定了你要构建的所有PDF,因此你不需要再多余的东西。通常在makefile中几乎不需要进行任何显式迭代。

如果你使用的是不同的 make,那么你可能更愿意使用后缀规则:

.tex.pdf:
        $(LATEXMK) $<

这与模式规则表达的含义相同,但灵活性略少。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章