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

C++ 编译器如何知道何时不重新编译?,c++,compiler-construction,C++,Compiler Construction,编译器如何知道何时不需要重新编译代码的某些部分,尤其是在大型项目中 例如,在C++中,我们有两个C++文件和两个头文件。头文件相互依赖。(它们使用彼此文件中指定的类。) 编译器是否总是需要解析两个头文件,(也许是C++实现方法文件)来获得类信息,以便生成两个C++文件中的任何一个? 我一直认为,当您在命令提示符下运行编译器时,它会在输出对象文件后立即关闭,因此不可能缓存抽象语法树或中间代码。大多数C++编译器知道某个文件何时不需要输出到对象文件,因此跳过了吗? < p>所有编译的编译器都编译

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


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

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



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

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

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

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


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

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

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

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

但是,如果依赖源文件比目标文件新,则我们知道源文件是在编译发生后编辑的,并且另一次编译已就绪<因此,code>make将执行规则的build命令


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

这通常是构建系统的工作(例如make),而不是编译器的工作。这是make的工作,例如make在makefile的帮助下通常是make进行检查,告诉make哪些文件依赖于哪些其他文件是相当复杂的…@xanatos它可能是make,也可能是其他工具;我认为,通用名称是构建系统。好的构建系统与编译器协作,编译器“告诉”它们每次包含哪些头。(他们合作得有多好取决于,但我已经让VC++编译器告诉GNU make依赖关系。)我从来没有听说过编译器或构建系统这样做。通常的构建系统依赖于编译器输出来确定依赖关系,依赖于文件上的时间戳来确定哪些文件需要重新编译。分布式构建比本地构建要难一些,如果只是因为时钟同步的话。