为何第二次及后续make执行时最后一个.c文件未重新编译?
问题原因分析
核心问题出在将obj目录作为普通依赖,而非仅顺序依赖(order-only prerequisite),结合目录的修改时间特性导致了该现象:
1. 目录修改时间的特性
文件系统中,目录的修改时间(mtime)会在目录内新增、删除文件时被更新,更新为操作发生的时间——而非目录本身的内容(比如目录权限)修改时才更新。
2. 首次编译的时间线
- 初始状态下
obj目录为空,make首先执行创建obj目录的规则。 - 随后逐个编译
a.c到e.c,生成对应的.o文件存入obj目录:每生成一个.o文件,obj目录的mtime就会被更新一次。最终obj目录的mtime等于生成e.o时的时间。 - 由于
e.o是最后生成的文件,它的mtime和obj目录的mtime几乎完全一致(甚至略晚一点,因为写入文件需要消耗少量时间)。
3. 后续编译的判定逻辑
make会检查每个.o文件的依赖是否比目标文件更新:
- 对于
a.o到d.o:它们的mtime都早于obj目录的mtime(obj目录的mtime是最后生成e.o时的时间,远晚于这些早期生成的.o的时间),所以make判定依赖(obj目录)比目标新,会重新编译对应的.c文件;而每次重新编译生成新的.o时,又会再次更新obj目录的mtime。 - 对于
e.o:它的mtime不早于obj目录的mtime,同时src/e.c也没有被修改,make判定所有依赖都没有比e.o新,因此不会重新编译e.c。
解决方法
将obj目录改为仅顺序依赖,即在规则中用| obj替代直接写obj,这样make只会确保obj目录存在,不会检查它的修改时间,既避免不必要的重复编译,也不会出现单个文件不编译的异常。
内容的提问来源于stack exchange,提问作者tahzibi.jafar
相关产品推荐
相关产品推荐

