GNU Make:如何避免其他目标出错时删除已成功生成的中间文件
构建出错时保留Make已生成的中间文件
问题背景
现有如下Makefile:
.RECIPEPREFIX = + .ONESHELL: all: one vars := one.a two.a three.a .INTERMEDIATE: $(vars) one: $(vars) + touch $@ %.a: %.b + touch $@ %.b: + if [ "$@" = "three.b" ]; + then + exit 1; + fi + touch $@
所有目标构建耗时较长,正常情况下.INTERMEDIATE标记的中间文件会被自动清理,符合预期。但当某目标构建出错(如示例中three.b生成失败)时,Make会停止并删除所有已成功生成的中间文件,并行构建时该问题影响更严重。需要实现构建出错时保留已成功生成的中间文件的需求。
解决方案
方案1:用.SECONDARY替代.INTERMEDIATE
将Makefile中的.INTERMEDIATE: $(vars)替换为:
.SECONDARY: $(vars)
.SECONDARY是Make的特殊目标,标记的文件永远不会被自动删除——不管构建成功还是失败,已生成的中间文件都会保留。如果需要清理这些文件,可以手动添加clean目标:
clean: + rm -f $(vars) one
执行make clean即可完成清理。
方案2:-k参数配合自定义清理逻辑
如果希望正常构建完成时自动清理中间文件,出错时保留产物,可以采用以下方式:
- 执行Make时添加
-k(或--keep-going)参数:
该参数会让Make在遇到错误时继续尝试构建其他可完成的目标,同时不会删除已成功生成的中间文件。make -k - 保留原
.INTERMEDIATE配置,同时添加自定义清理目标,在构建成功后手动执行清理(如果需要)。
原理说明
.INTERMEDIATE的核心特性:只要文件不再被任何目标依赖,无论构建成功与否,都会被Make自动删除。.SECONDARY的核心特性:标记的文件不会被Make自动删除,仅能通过手动清理或其他规则删除。-k参数的作用:让Make忽略单个目标的失败,继续构建其他依赖链,同时保留已生成的所有中间产物。
内容的提问来源于stack exchange,提问作者Colombo
相关产品推荐
相关产品推荐

