1. 文件的时间戳
make 主要依靠文件的时间戳来判断依赖文件是否有更新。每个文件在文件系统中都有一个时间戳,记录了文件的三种重要时间:
- 访问时间(Accesstime):文件最后一次被访问的时间。
- 修改时间(Modifytime):文件内容最后一次被修改的时间。
- 状态改变时间(Changetime):文件的状态(如权限、所有者等)最后一次被修改的时间。
make 主要关注的是文件的修改时间(mtime)。
2. 比较时间戳的过程
当 make 读取 makefile 中的规则时,会按照以下步骤检查依赖文件是否有更新:
步骤一:确定目标和依赖文件
假设 makefile 中有这样一个规则:
main: main.o add.o sub.ogcc main.o add.o sub.o -o main
这里 main 是目标文件,main.o、add.o 和 sub.o 是依赖文件。
步骤二:检查目标文件是否存在
- 如果目标文件
main不存在,那么make会认为目标文件是最新的(因为还没有生成),需要执行规则中的命令来生成目标文件。 - 如果目标文件
main存在,继续下一步。
步骤三:比较目标文件和依赖文件的修改时间
make会获取目标文件main的修改时间(mtime)。- 然后依次获取每个依赖文件(
main.o、add.o和sub.o)的修改时间。
步骤四:判断是否需要重新生成目标文件
- 如果任何一个依赖文件的修改时间比目标文件的修改时间新,说明依赖文件有更新,
make会执行规则中的命令来重新生成目标文件。 - 如果所有依赖文件的修改时间都不比目标文件的修改时间新,说明目标文件已经是最新的,
make不会执行任何命令。
3. 示例说明
假设当前目录下有以下文件及其修改时间:
main:2025-04-04 10:00:00main.o:2025-04-04 09:00:00add.o:2025-04-04 9:30:00sub.o:2025-04-04 10:30:00
当运行 make 时:
make发现目标文件main存在。- 获取
main的修改时间为 2025-04-04 10:00:00。 - 检查依赖文件:
main.o的修改时间为 2025-04-04 09:00:00,比main的修改时间旧。add.o的修改时间为 2025-04-04 09:30:00,比main的修改时间旧。sub.o的修改时间为 2025-04-04 10:30:00,比main的修改时间新。
由于 sub.o 的修改时间比 main 的修改时间新,make 会认为 main 需要重新生成,因此会执行规则中的命令:
gcc main.o add.o sub.o -o main
4. 特殊情况处理
- 依赖文件不存在:如果规则中的某个依赖文件不存在,
make会认为这个依赖文件需要生成,从而执行相应的命令来生成这个依赖文件,然后再重新检查目标文件是否需要更新。 - 手动修改时间戳:如果手动修改了文件的时间戳,但没有实际修改文件内容,
make可能会错误地认为该文件已经更新,从而重新生成依赖它的目标文件。为了避免这种情况,可以使用touch命令来正确更新文件的时间戳。
总结
- 时间戳机制:
make主要依靠文件的时间戳(特别是修改时间 mtime)来判断依赖文件是否有更新。 - 比较过程:
make会获取目标文件和依赖文件的修改时间,并比较它们的大小。如果任何一个依赖文件的修改时间比目标文件的修改时间新,make会执行规则中的命令来重新生成目标文件。