Makefile结合模式规则与通配符配置LaTeX可选子目录依赖
Makefile 实现 LaTeX 章节文件按需依赖子目录文件方案
问题原因
两种方案失效的核心是没搞对Make的执行时机和通配符规则:
- 直接在依赖里写
%/*.tex,Make会把这部分当成必须存在的强依赖,要是对应ch*子目录不存在,匹配不到符合规则的文件就直接报错终止。 - 直接在依赖里写
$(wildcard %/*.tex),wildcard函数会在Makefile第一次加载解析的时候就执行,这时候规则里的模式通配符%还没替换成具体的章节编号,函数实际找的是字面路径%/*.tex,根本匹配不到真实文件,自然加不上子目录的依赖。
正确实现
用Make的二次展开特性就行,全程不需要硬编码任何章节编号,子目录不存在也不会报错:
# 开启二次展开:依赖部分会在模式匹配到具体目标后再求值 .SECONDEXPANSION: # $* 是隐式规则的自动变量,代表%匹配到的词干,也就是对应ch*的文件名前缀 %.pdf: %.tex $$(wildcard $$*/*.tex) pdflatex $<
逻辑说明
- 开启
.SECONDEXPANSION后,依赖列表里用$$转义的部分,不会在第一次解析Makefile的时候求值,会等匹配到具体编译目标、替换完%之后再执行。 - 比如编译
ch3.pdf的时候,$$*会被替换成词干ch3,$$(wildcard $$*/*.tex)就等价于$(wildcard ch3/*.tex),自动查找ch3目录下的所有tex文件。 wildcard函数只会返回真实存在的文件路径:如果ch3目录不存在,或者目录里没有tex文件,函数返回空值,不会加额外依赖,Make直接用主文件ch3.tex编译,不会报错;如果目录下有tex文件,会全部自动加入依赖列表,任意子文件修改都会触发重新编译。
可选扩展
如果子目录下还有多层嵌套的TeX文件需要加依赖,可以把wildcard规则改成递归匹配:
.SECONDEXPANSION: %.pdf: %.tex $$(wildcard $$*/*.tex $$*/**/*.tex) pdflatex $<
如果要处理交叉引用、参考文献,直接把编译命令换成latexmk -pdf $<就行,依赖逻辑不用改。
内容的提问来源于stack exchange,提问作者Paul Kim
相关产品推荐
相关产品推荐

