您如何减少 VC++ 项目(原生 C++)的编译时间和链接时间?
请指定每个建议是否适用于调试、发布或两者。
这对您来说可能听起来很明显,但我们尝试尽可能多地使用前向声明,即使它需要写出类型所在的长命名空间名称:
// Forward declaration stuff
namespace plotter { namespace logic { class Plotter; } }
// Real stuff
namespace plotter {
namespace samples {
class Window {
logic::Plotter * mPlotter;
// ...
};
}
}
它也大大减少了在其他编译器上编译的时间。实际上它适用于所有配置:)
使用Handle/Body 模式(有时也称为“pimpl”、“adapter”、“decorator”、“bridge”或“wrapper”)。通过将类的实现隔离到 .cpp 文件中,它们只需要编译一次。大多数更改不需要更改头文件,因此这意味着您可以进行相当广泛的更改,而只需要重新编译一个文件。这也鼓励重构和编写注释和单元测试,因为编译时间减少了。此外,您会自动分离接口和实现的关注点,从而简化代码的接口。
如果您的构建过程中的大多数 .cpp 文件必须包含大型复杂标头,并且这些标头不经常更改,则可以预编译它们。在具有典型配置的 Visual C++ 项目中,只需将它们包含在 stdafx.h 中即可。这个特性有它的批评者,但充分利用模板的库往往在头文件中有很多东西,在这种情况下,预编译的头文件是加速构建的最简单方法。
这些解决方案适用于调试和发布,并且专注于已经庞大且繁琐的代码库。
前向声明是一种常见的解决方案。
分布式构建,例如使用 Incredibuild 是一个胜利。
将代码从标头向下推送到源文件中是可行的。小类、常量、枚举等可能会从头文件开始,因为它可以在多个编译单元中使用,但实际上它们只在一个编译单元中使用,并且可以移动到 cpp 文件中。
我尚未阅读但使用过的解决方案是拆分大标题。如果您有一些非常大的标题,请查看它们。它们可能包含相关信息,也可能依赖于许多其他标头。获取不依赖于其他文件的元素...简单的结构、常量、枚举和前向声明,并将它们the_world.h
从the_world_defs.h
. 您现在可能会发现很多源文件现在只能包含the_world_defs.h
并避免包含所有这些开销。
Visual Studio 还有一个“显示包含”选项,可以让您了解哪些源文件包含许多头文件以及哪些头文件最常包含。
对于非常常见的包含,请考虑将它们放在预编译的标头中。
我使用Unity Builds(位于此处的屏幕截图)。
我们使用Xoreax 的 Incredibuild在多台机器上并行运行编译。
编译速度问题很有趣,Stroustrup 在他的FAQ中有这个问题。
还有一篇来自 Ned Batchelder 的有趣文章:http: //nedbatchelder.com/blog/200401/speeding_c_links.html(关于 Windows 上的 C++)。
我们的开发机器都是四核的,我们使用Visual Studio 2008 支持并行编译。我不确定是否所有版本的 VS 都可以做到这一点。
我们有一个包含大约 168 个单独项目的解决方案文件,在我们的四核机器上编译这种方式大约需要 25 分钟,而在我们为暑期学生提供的单核笔记本电脑上大约需要 90 分钟。不完全可比的机器,但你明白了:)
在 Visual C++ 中,有一种方法称为 Unity,它通过减少对象模块的数量来显着改善链接时间。
这涉及连接 C++ 代码,通常按库分组。这当然使编辑代码变得更加困难,除非你很好地使用它们,否则你会遇到命名空间冲突。它使您无法使用“使用命名空间 foo”;
我们公司的几个团队有精心设计的系统来获取普通的 C++ 文件并在编译时将它们连接起来作为构建步骤。链接时间的减少可能是巨大的。
另一种有用的技术是blobbing。我认为这与 Matt Shaw 所描述的相似。
简单地说,您只需创建一个包含其他 cpp 文件的 cpp 文件。您可能有两种不同的项目配置,一种是普通的,一种是 blob。当然,blobbing 对您的代码施加了一些约束,例如,未命名的命名空间中的类名可能会发生冲突。
当您更改一个 cpp 文件时,避免在 blob 中重新编译整个代码的一种技术(正如 David Rodríguez 所提到的)是让您的“工作” blob 是从最近修改的文件和其他普通 blob 中创建的。
我们大部分时间都在工作中使用blobbing,它减少了项目构建时间,尤其是链接时间。
编译时间:
如果您有 IncrediBuild,编译时间将不是问题。如果您没有 IncrediBuild,请尝试“统一构建”方法。它将多个 cpp 文件合并到一个 cpp 文件中,从而减少了整个编译时间。
链接时间:
“统一构建”方法也有助于减少链接时间,但作用不大。但是,您可以检查是否启用了“整体全局优化”和“LTCG”,虽然这些标志使程序变快,但它们确实使链接变慢。
尝试关闭“全局优化”并将 LTCG 设置为“默认”,链接时间可能会减少 5/6。
(LTCG 代表链接时间码生成)