编译器如何知道何时不重新编译

How do compilers know when not to recompile?

本文关键字:编译 新编译 何知道 何时不 编译器      更新时间:2023-10-16

编译器如何知道何时不需要重新编译某些代码部分,尤其是在大型项目中?


例如,假设在C++中,我们有两个C++文件和两个头文件。头文件相互依赖。(他们使用每个其他文件中指定的类。)

编译器是否总是需要解析两个头文件(可能还有用于方法实现的C++文件)来获得类信息,以便生成这两个C++文件中的任何一个?


我一直认为,当你在命令提示符下运行编译器时,它会在输出对象文件后立即关闭,所以不可能缓存抽象语法树或中间代码。大多数C++编译器知道某个文件何时不需要输出到对象文件,因此被跳过吗?

我认识的所有编译器都编译它们的每个源文件告诉我。总是。他们生成了一个新版本的对象他们编译的每个源文件的文件。

只有编译必要的内容,这项工作通常留给构建系统(品牌或其他)。知道哪些对象需要重新生成取决于每个源文件直接包含的内容或间接地;大多数编译器都可以选择输出某种格式的信息,无论是动态的还是单独的调用和构建系统(至少是可用的系统)使用这些信息来确定依赖关系。

如上所述,编译器将编译被要求编译的每个文件。这取决于像make这样的工具来决定需要编译什么。

make中设置规则。每个规则都有一个目标,一个依赖项列表,后面是在不满足这些依赖项时要运行的命令。例如

target.o : target.c
    gcc -c -o target.o target.c

在大多数文件系统中,每个文件都有一个时间戳。如果target.o的时间戳比target.c(规则依赖项)新,则make不运行下面的gcc命令。这是因为首先编辑源文件,然后将源文件编译为对象文件。

但是,如果依赖的源文件比目标文件新,那么我们知道源文件是在编译之后编辑的,另一次编译是按顺序进行的。因此,make将执行该规则的构建命令。

当规则依赖于其他规则,但同样的原则适用时,情况会变得复杂得多。

我不知道他们是如何(不)实现它的(因为很多人没有……不要问我为什么),但我确信这会很容易。您可以在中间(obj)文件中保存源文件和正在编译的每个依赖文件的名称和哈希,以及正在使用的编译选项、编译器的哈希(或其内部版本)和编译结果(ok/error)。下次用户尝试重新编译文件时,编译器会检查是否已经有中间文件,检查所有哈希是否相同,编译选项是否相同,编译器是否相同。。。如果一切都一样,它会给出预先保存的错误消息,然后退出而不执行任何操作。

中间文件会稍微大一点(可能每个文件都有一些kb)。