Makefile中如何为静态模式构建的目标配置.DELETE_ON_ERROR
Makefile构建失败时.DELETE_ON_ERROR不删除目标文件的解决方法
问题现象
需要让Makefile中.xv后缀的所有构建目标应用.DELETE_ON_ERROR规则,实现构建命令报错时自动删除损坏的目标文件,先后尝试给.DELETE_ON_ERROR指定通配符、完整目标列表、单个目标等写法均不生效。
已验证:
- 构建命令(iverilog)报错时返回错误码2,Make可以识别到错误退出
- 在规则中直接写
exit 1时,.DELETE_ON_ERROR可以正常删除目标 - 实际iverilog编译报错退出后,损坏的
.xv目标文件会残留,即使将.DELETE_ON_ERROR放在Makefile最开头也无法解决。
根本原因
.DELETE_ON_ERROR的正确全局开启方式是不带任何前置目标直接写.DELETE_ON_ERROR:,不需要给它指定目标列表、通配符,加了反而可能触发旧版本Make的兼容问题。- 失效的核心原因是Makefile中给所有测试目标单独写了仅带
dirs顺序依赖的空显式规则:
在GNU Make 4.4之前的版本中,这种「空显式规则+隐式模式规则提供构建命令」的组合,会导致$(tests): | dirs $(riscv_tests): | dirs $(wavedumps): | dirs.DELETE_ON_ERROR无法正确关联到模式规则构建的目标,因此命令报错时不会触发删除逻辑。
修复方案
- 删除上述三行空的显式规则,将
| dirs顺序依赖直接添加到对应的模式规则中,避免显式空规则干扰.DELETE_ON_ERROR的判定:# 原空规则全部删除 $(PREFIX)/%.xv: %.sv $(common_src) | dirs $(VV) -o $@ -g2012 -DSEED=$(RANDOM) -I$(INC) -Wall -Wno-timescale -DVCD="\"$@.vcd\"" $^ $(RISCV_TEST_DIR)/%.xv: $(TSRCRV)/%.sv $(common_src) $(riscv_src) | dirs $(VV) -o $@ -g2012 -DSEED=$(RANDOM) -I$(INC) -Wall -Wno-timescale -DVCD="\"$@.vcd\"" $^ $(PREFIX)/%.xv.vcd: $(PREFIX)/%.xv | dirs $(VVP) $< $(RISCV_TEST_DIR)/%.xv.vcd: $(RISCV_TEST_DIR)/%.xv | dirs $(VVP) $< - 保留Makefile中无目标的
.DELETE_ON_ERROR:即可,无需额外添加参数。 - (可选兼容保险)如果使用的iverilog版本存在特殊的文件写入逻辑,可在编译命令前增加删除目标的语句,彻底避免损坏文件残留:
该写法会在每次编译前先删除旧的目标文件,即使$(PREFIX)/%.xv: %.sv $(common_src) | dirs @rm -f $@ $(VV) -o $@ -g2012 -DSEED=$(RANDOM) -I$(INC) -Wall -Wno-timescale -DVCD="\"$@.vcd\"" $^ $(RISCV_TEST_DIR)/%.xv: $(TSRCRV)/%.sv $(common_src) $(riscv_src) | dirs @rm -f $@ $(VV) -o $@ -g2012 -DSEED=$(RANDOM) -I$(INC) -Wall -Wno-timescale -DVCD="\"$@.vcd\"" $^.DELETE_ON_ERROR因版本问题未触发,也不会留下损坏的文件导致Make误判目标已更新。
内容的提问来源于stack exchange,提问作者Martel
相关产品推荐
相关产品推荐

