编译器如何知道何时不重新编译
How do compilers know when not to recompile?
编译器如何知道何时不需要重新编译某些代码部分,尤其是在大型项目中?
例如,假设在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)。
- 使用 MINGW gcc 编译时,不会为 std::string 调用重载的新运算符
- 如何编译:Mac上的Synergy(2017年的新工具链)
- 如何编译和运行一个新的 C++ Actor 框架项目?
- C++编译新的警告过滤器
- 每次都构建(make)lib,只有在lib较新时才重新编译项目
- 如何创建指向派生类的新指针,该派生类在C++编译时未知
- 如何在不退出和失去断点的情况下重新加载重新编译的二进制文件
- 在编译时将整数和分数部分宏组合成一个新的宏或双精度
- C++运算符新重载、编译错误
- 在新OSX上编译旧碳应用
- 为什么G 5.4不能编译此编译时质数代码
- 代码块在尝试编译或创建新文件时出现"An assertion failed!"错误
- 在新的Visual Studio项目中包含任何Eigen 3.3.1文件将无法编译
- RCpp:如何在不重新启动R的情况下重新加载重新编译的C++代码
- 新安装的MinGW问题与编译和可执行文件
- 为什么要编译?(编译是否忽略未包含的 h 文件?
- 高级C和C++编译:无法编译书中提到的示例程序
- 在不同的编译单元中使用不同的编译标志编译相同的头
- 在cygwin中编译新的mingw二进制文件
- 使用boost库编译预编译头文件需要很长时间