问题场景重现
在处理字幕文件转换时,我们经常遇到这样的构建流程:
%.idx %.sub: %.sup
bdsup2subpp --language en -o $*.sub $<
%.srt: %.sub
vobsub2srt $*
%.ass: %.srt
ffmpeg -hide_banner -y -nostdin -i $< $@
Make的中间文件处理机制
Make默认会将所有通过隐式规则生成的文件视为中间文件(Intermediate files),并在构建完成后自动删除。但在我们的案例中:
- .sub和.srt文件被正确识别为中间文件
- .idx文件却被保留下来
根本原因分析
这是由于Make对多目标规则的特殊处理方式造成的:
- Make只将实际被其他规则依赖的产出视为中间文件
- 在我们的例子中,只有.sub文件被后续规则显式依赖
- .idx文件虽然同时生成,但未被任何规则引用
解决方案实现
以下是完整的改进方案,包含依赖声明和清理处理:
# 声明所有中间文件
.INTERMEDIATE: %.sub %.idx %.srt
# 多目标生成规则
%.idx %.sub: %.sup
bdsup2subpp --language en -o $*.sub $<
# 显式声明idx依赖
%.srt: %.sub %.idx
vobsub2srt $*
# 最终目标规则
%.ass: %.srt
ffmpeg -hide_banner -y -nostdin -i $< $@
# 自定义清理规则
clean:
find . -name "*.sub" -o -name "*.idx" -o -name "*.srt" | xargs rm -f
进阶技巧:使用Secondary机制
如果某些中间文件需要保留供后续手动检查,可以使用:
.SECONDARY: %.idx
这样.idx文件将不会被自动删除,而其他中间文件仍按常规处理。
实际应用示例
假设我们处理movie.sup文件:
# 生成过程
$ make movie.ass
bdsup2subpp --language en -o movie.sub movie.sup
vobsub2srt movie
ffmpeg -hide_banner -y -nostdin -i movie.srt movie.ass
# 检查文件
$ ls
movie.ass # 仅保留最终目标文件
跨平台兼容方案
对于Windows环境,清理规则需要调整为:
clean:
del /Q /F *.sub *.idx *.srt 2>nul