作为一名 C++ 开发者,如果您曾经构建过 C# 或 Java 项目,可能会惊讶于它们的构建过程比 C++ 快得多。对于某些 C++ 项目,一次构建可能只需几分钟;而对另一些项目,则可能长达数小时,这取决于项目的规模。即使编译阶段已经在所有可用核心上并行化,C++ 的构建仍可能比其他语言慢得多。下面是这篇有用的Stack Overflow 回答中解释的一些原因:
- 头文件:每个编译单元都需要 1:加载、2:编译成百上千个头文件。其中的每一个通常都要为每个编译单元重新编译,因为预处理器会保证头文件的编译结果可能因编译单元而异。(某个编译单元中定义的宏可能会改变头文件的内容。)这恐怕是最主要的原因:它要求为每个编译单元编译海量的代码;此外,每个头文件还必须被编译多次(每个包含它的编译单元一次)。
- 链接:编译完成后,所有目标文件必须链接在一起。这基本上是一个无法很好并行化的整体过程,必须处理您的整个项目。
- 解析:C++ 的语法极其难以解析,严重依赖上下文,而且很难消除歧义。这会耗费大量时间。
- 模板:在 C# 中,
List<T>是唯一被编译的类型,无论程序中有多少个 List 的实例化。而在 C++ 中,vector<int>是一个与vector<float>完全不同的类型,每一个都必须单独编译。
如果构建过程很慢,会发生什么?
如果一次构建需要 10 分钟,公司损失的就相当于 10 分钟乘以每天进行的构建次数。总成本还取决于开发者的数量:开发者越多,构建次数越多,生产力损失就越大。
IncrediBuild 投资回报率计算器可以估算:当一个团队有 X 名开发者、每次构建耗时 Y 分钟时,会损失多少时间。不过,这个计算器的估算是偏乐观的,因为它无法计算隐性成本。例如,如果一名开发者启动构建后必须等待 10 分钟,他可能会转去做别的事情,比如浏览网页,然后分心。结果,10 分钟的中断很容易变成 15 甚至 20 分钟。
快速的构建能帮助开发者专注于手头正在编写的代码。
如何优化 C++ 项目的构建过程?有几种技术可以帮助优化构建过程,其中一些列在这里
- Pimpl 惯用法
- 前向声明
- 头文件保护
- 减少相互依赖
- 当然,还有使用最广泛的技术之一:预编译头文件
然而,使用上述技术也有一些缺点:
- 很难确保这些解决方案真正得到落实;需要定期进行代码评审。
- 即使这些解决方案被正确应用,节省的时间也可能有限;对于非常大的项目,构建仍可能需要数小时。
- 仅仅为了解决构建时间问题而修改代码,通常不是好主意;代码的设计和实现应当独立于所使用的构建过程。
C++ 分布式构建系统来救场
分布式构建系统是一种将代码编译分发到网络上多台机器的程序。它应当始终产生与本地编译相同的结果。
市面上有几个不错的 C++ 分布式构建系统。就我个人而言,我只用过IncrediBuild。
IncrediBuild 是 IncrediBuild 公司开发的一套网格计算软件。IncrediBuild 旨在通过将计算密集型任务分发到网络上,帮助加速这些任务,其典型应用包括编译源代码、常规软件构建以及其他与软件开发相关的任务。任务可以分发到网络上的多台计算机,从而利用比发起计算机单机更多的资源来加速工作。

IncrediBuild 帮助我们大幅缩短了构建时间,让我们能把更多时间花在富有成效的工作上。
如果您的 C++ 构建过程耗时太长,不妨考虑使用分布式构建系统。探索可用的工具,选择最符合您需求的那一个。
