Makefile问题:避免同一规则生成多依赖时重复执行规则
解决Makefile多目标重复执行规则的问题
你的问题很典型——Make默认会把每个目标独立处理,所以当log_file、output_1、output_2都依赖input和myprogram时,Make会为每个目标单独触发一次规则,导致三次执行。要实现一次性生成所有目标且只调用一次规则,有两种可靠的解决方案:
方案1:使用中间标记文件(推荐)
创建一个虚拟的标记文件(比如.generated),让所有输出目标依赖这个标记文件,而标记文件的规则负责一次性生成所有输出。这样Make只会检查标记文件的状态,触发一次生成命令:
# 定义所有需要生成的输出文件 OUTPUT_FILES := log_file output_1 output_2 # 让每个输出文件依赖标记文件 $(OUTPUT_FILES): .generated # 标记文件的规则:生成所有输出,然后创建标记 .generated: input myprogram # 这里替换成你的实际生成命令,一次性生成所有三个文件 ./myprogram input log_file output_1 output_2 # 创建标记文件,确保下次Make知道已经生成过 touch $@ generate: $(OUTPUT_FILES)
执行make generate时,Make会检查三个输出文件是否存在:
- 如果不存在,会触发
.generated的规则,一次性生成所有文件并创建标记 - 标记文件存在后,所有输出文件的依赖都满足,不会重复执行规则
方案2:使用多目标规则并确保命令一次性生成所有文件
如果不想用标记文件,可以直接把所有输出写在一个规则里,同时确保命令一次性生成所有目标。不过要注意:Make仍然会为每个目标检查依赖,但如果你的命令能一次性生成所有文件,并且所有目标的时间戳都更新了,Make可能不会重复执行(不过标记文件的方法更稳定):
log_file output_1 output_2: input myprogram # 一次性生成所有三个文件的命令 ./myprogram input log_file output_1 output_2 # 强制更新所有目标的时间戳,让Make认为它们都已生成 touch $@ generate: log_file output_1 output_2
不过这个方法有个小问题:如果其中一个文件已经存在但其他不存在,Make还是会触发一次规则,但命令会生成所有文件,这其实也没问题,但标记文件的方法更清晰,能明确告诉Make这些文件是一起生成的。
为什么原来的写法会重复执行?
Make的核心逻辑是每个目标独立验证依赖:当你执行make generate,Make会依次检查log_file、output_1、output_2是否需要更新。每个目标都会发现自己依赖input或myprogram(如果目标不存在),所以会分别触发一次规则,导致三次执行。
内容的提问来源于stack exchange,提问作者baraaorabi
相关产品推荐
相关产品推荐

