GNU Make:如何执行前置预备操作且不触发目标重复构建?
核心问题原因
你遇到的重复构建问题,根源是被.PHONY标记的directories属于伪目标,make 会默认伪目标每次执行后都已更新,所有依赖它的普通文件目标都会被强制触发重建,这就是 Foo 每次都重复链接的原因。
最优解决方案:使用 Order-Only 依赖
GNU make 专门提供了 Order-Only 依赖用于处理这种「仅当依赖不存在时才执行,依赖存在时不触发目标重建」的场景,依赖项写在竖线|之后即可。
你只需要修改obj/%.o的模式规则,将obj目录设为 Order-Only 依赖即可:
# 其余原有规则保持不变 obj/%.o : %.cpp | obj $(COMPILE.cc) $(OUTPUT_OPTION) $<
这种方案的优势:
- 无论执行
make all还是make clean Foo,生成.o文件前都会自动检查obj目录是否存在,不存在则自动创建 - 不会因为
obj目录的时间戳变化触发.o重编译,更不会导致Foo重复链接 - 不需要额外添加伪目标,也不需要手动执行前置准备步骤
兼容旧版 make 的方案
如果需要兼容不支持 Order-Only 依赖的旧版本 make,可以直接在模式规则中用mkdir -p自动创建目录,不需要手动写目录存在判断逻辑:
# 其余原有规则保持不变 obj/%.o : %.cpp @mkdir -p $(@D) $(COMPILE.cc) $(OUTPUT_OPTION) $<
其中自动变量$(@D)代表目标文件所在的目录,即使后续你新增了多级子目录的编译目标,这行代码也能通用,前缀@是避免打印mkdir命令的执行日志,保持输出干净。
内容的提问来源于stack exchange,提问作者Joseph Larson
相关产品推荐
相关产品推荐

