如何编写Makefile以跳过缺失输入文件的目标?
解决Makefile中缺失源文件时跳过目标并继续执行的问题
你的问题核心在于:当foo.tex不存在时,Make找不到生成foo.pdf的有效规则(模式规则%.pdf: %.tex要求依赖的.tex文件必须存在才能触发),因此直接报错终止。要实现跳过缺失源文件的目标、继续处理其他项,这里有几种实用方案:
方案1:动态生成存在的源文件对应的目标(推荐)
这种方法会先筛选出当前目录下实际存在的.tex文件,只构建这些文件对应的.pdf,从根源避免处理不存在的源文件:
# 收集当前目录下所有存在的.tex文件 EXISTING_TEX := $(wildcard *.tex) # 将存在的.tex文件转换为对应的.pdf目标 TARGET_PDFS := $(EXISTING_TEX:.tex=.pdf) default: $(TARGET_PDFS) %.pdf: %.tex @if [ -s $< ]; then \ pdflatex -interaction=batchmode $<; \ else \ echo 'Skipped empty file: $<'; \ fi
原理说明:
$(wildcard *.tex)只会返回当前目录下真实存在的.tex文件,不存在的文件不会被纳入列表;default目标仅依赖这些存在的.tex对应的.pdf,因此Make不会尝试构建无源头的目标,自然不会报错。
方案2:修改目标规则,脱离对.pdf文件的依赖
如果你需要default明确指定foo、bar这类固定目标(不管源文件是否存在),可以把它们作为独立目标,直接在规则内检查源文件状态:
default: foo bar # 定义可复用的处理宏,减少重复代码 define PROCESS_TEX @if [ -f $(1).tex ]; then \ if [ -s $(1).tex ]; then \ pdflatex -interaction=batchmode $(1).tex; \ else \ echo 'Skipped empty file: $(1).tex'; \ fi; \ else \ echo 'Skipped missing file: $(1).tex'; \ fi; \ touch $(1) # 生成空文件标记目标已完成,避免重复执行 endef foo: $(call PROCESS_TEX,foo) bar: $(call PROCESS_TEX,bar) # 清理生成的临时文件和标记文件 clean: rm -f *.pdf *.aux *.log foo bar
原理说明:
foo和bar不再依赖.pdf文件,而是直接执行自定义处理逻辑;touch $(1)生成同名空文件,Make会认为该目标已完成,下次运行时不会重复执行(除非源文件被修改);- 宏
PROCESS_TEX先检查文件是否存在,再检查是否为空,分情况给出提示和处理。
方案3:使用make -k强制继续执行
如果不想修改Makefile,也可以在运行时添加-k(或--keep-going)参数,让Make遇到错误时继续处理其他目标:
make -k default
注意:
这个方法会忽略所有构建错误(包括编译失败等非源文件缺失的问题),如果只想精准跳过源文件缺失的情况,前两种方案更合适。
内容的提问来源于stack exchange,提问作者epR8GaYuh
相关产品推荐
相关产品推荐

