4

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


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

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


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

4

3 回答 3

3

我知道的所有编译器都会编译他们被告知的每个源文件。总是。他们为他们编译的每个源文件生成一个新版本的目标文件。

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

于 2013-08-05T13:12:38.957 回答
2

如上所述,编译器将编译要求编译的每个文件。由 make 等工具决定需要编译的内容。

make一个设置规则。每个规则都有一个目标、依赖项列表,如果不满足这些依赖项则运行命令。例如

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

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

然而,如果依赖源文件比目标文件新,那么我们知道源文件在编译发生后被编辑,并且另一个编译是有序的。make因此将执行规则的构建命令。

当规则依赖于其他规则但同样的原则适用时,它会变得更加复杂。

于 2013-08-05T13:40:37.280 回答
0

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

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

于 2013-08-05T13:13:59.927 回答