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

时间:2013-08-05 13:07:01

标签: c++ compiler-construction

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


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

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


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

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

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

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

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

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

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

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

答案 2 :(得分:0)

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

中间文件会更大(可能每个kb)。