我了解增量编译是什么:当编译器只编译您编辑的代码而不是全部时。但是,将代码分离为 .h 和 .c/.cc 文件以及 C++ 中的 makefile 如何帮助增量编译?
1 回答
头文件实际上与编译增量相反。对任何头文件的任何更改都会导致包含该头文件的所有源文件(甚至间接通过另一个头文件)被重新编译。但是标题使得跨多个翻译单元保持所有定义相同(如语言所要求的那样)变得非常容易,因此它们的使用实际上是必要的。这种反生产力是为什么“只包括你需要的东西”是要考虑的经验法则的原因。
有助于增量编译的只是每个翻译单元的定义更少。如果您将整个程序编写在单个源文件中,那么对程序任何小部分的任何微小更改都将导致需要重新编译整个程序。
如果您将每个函数都写在单独的源文件中,那么对这些函数中的任何一个进行修改都将导致只需要重新编译那个微小的源文件,然后将其与未修改的先前编译的目标文件链接在一起。编译单个函数通常比编译整个程序要快。虽然,如果更改是例如函数的参数,那么调用该函数的所有内容 - 即它的依赖项 - 也必须重新编译(因此,这将是更改位于头文件中的情况,并且所有依赖项必须包含标题)。
拥有多个源文件的另一个优点是它们可以独立编译,因此可以并行编译,考虑到当今的多核处理器,这非常棒,更不用说拥有无数行计算机系统的数据中心了。但是也有缺点:当有许多内联函数(尤其包括所有模板)时,从头开始的非增量编译通常更昂贵,需要为每个使用它们的单独源文件重新编译。
诸如 make 和 ninja 等构建系统是工具,它们的其他功能包括跟踪以前编译的源文件,并决定哪些源文件在修改后需要重新编译。该决定通常基于源文件(以及所有包含的文件)与其编译目标文件相比的修改时间。
这一切都适用于使用需要构建工具来过滤所需的重新编译并且其中没有任何增量逻辑的“愚蠢”非增量编译器(这是大多数编译器)。对于真正的增量编译器,可能不需要构建系统,甚至可能不需要翻译单元划分。