将所有.cpp 文件包含到一个编译单元中?

最近,我有理由使用一些 Visual Studio C + + 项目的常见调试和发布配置,但也有“发布所有”和“调试所有”,这是我以前从未见过的。

原来项目的作者只有一个 ALL.cpp,其中 # 包含所有其他内容。Cpp 文件。All 配置只构建这个 ALL.cpp 文件。当然,它被排除在常规配置之外,常规配置不构建 ALL.cpp

我只是想知道这是不是一种常见的做法?它带来了什么好处?(我的第一反应是它闻起来很臭。)

您可能会遇到哪些类型的陷阱?我可以想到的一个问题是,如果您的。Cpps,它们不再是该 cpp 的“私有”,但现在可以在其他 cpps 中看到?

所有项目都构建 DLL,因此在匿名名称空间中包含数据不是一个好主意,对吗?但是功能可以吗?

29488 次浏览

它被一些人(和谷歌可以)称为“统一建设”。它链接非常快,编译也相当快。对于不需要迭代的构建来说,它非常棒,就像从中央服务器发布构建一样,但它不一定适用于增量构建。

而且还要维护 PITA。

编辑: 这里是更多信息的第一个谷歌链接: http://buffered.io/posts/the-magic-of-unity-builds/

让它变得更快的是编译器只需要读入所有内容一次,编译出来,然后链接,而不是对每个内容都这样做。Cpp 文件。

布鲁斯 · 道森(Bruce Dawson)在他的博客 http://randomascii.wordpress.com/2014/03/22/make-vc-compiles-fast-through-parallel-compilation/上有一篇更好的文章

我想知道 ALL.cpp 是否试图将整个项目放在一个单独的编译单元中,以提高编译器优化程序大小的能力?

通常,一些优化只在不同的编译单元中执行,例如删除重复代码和内联。

也就是说,我似乎记得最近的编译器(微软的,英特尔的,但我不认为这包括海湾合作委员会)可以跨多个编译单元进行这种优化,所以我怀疑这个“技巧”是不必要的。

尽管如此,人们还是很好奇,是否真的存在任何差异。

统一建设提高了建设速度的三个主要原因。第一个原因是所有共享头文件只需要解析一次。许多 C + + 项目都有许多头文件,这些头文件包含在大多数或所有 CPP 文件中,对这些头文件的冗余解析是编译的主要成本,特别是如果您有许多简短的源文件。预编译头文件可以帮助降低成本,但通常有很多头文件没有预编译。

统一构建提高构建速度的下一个主要原因是调用编译器的次数较少。调用编译器会有一些启动成本。

最后,减少冗余头解析意味着减少内联函数的冗余代码生成,因此目标文件的总大小更小,这使得链接更快。

统一构建还可以提供更好的代码生成。

Unity 构建比 没有更快,因为减少了磁盘 I/O。我已经介绍了许多使用 xperf 的构建,我知道我在说什么。如果您有足够的内存,那么 OS 磁盘缓存将避免冗余 I/O-头的后续读取将来自 OS 磁盘缓存。如果您没有足够的内存,那么统一构建甚至会导致编译器的内存占用超过可用内存并被换出,从而使构建时间变得更糟。

磁盘 I/O 是昂贵的,这就是为什么所有操作系统都积极缓存数据以避免冗余磁盘 I/O 的原因。

我同意 Bruce 的观点; 根据我的经验,我曾经尝试过为我的一个。拥有大量头部的 dll 项目包括很多。为了降低 VS2010的整体编译时间(已经用尽了增量构建选项) ,但是没有减少编译时间,我用完了内存,而且构建甚至无法完成编译。

但是要补充的是,我确实发现在 Visual Studio 中启用多处理器编译选项有助于减少编译时间; 我不确定这样的选项是否可以在其他平台编译器中使用。

除了 Bruce Dawson 的 答得好之外,下面的链接还带来了更多关于统一构建的优缺点的见解—— https://github.com/onqtam/ucm#unity-builds

我们有一个针对 MacOS 和 Windows 的多平台项目。我们有许多大型模板和许多头部包括。我们使用预编译头将 VisualStudio2017msvc 的构建时间减半。对于 MacOS,我们尝试了几天来减少构建时间,但是预编译的头文件只将构建时间减少到85% 。使用单一。Cpp-File 是突破口。我们只需用一个脚本创建这个 ALL.cpp。我们的 ALL.cpp 包含所有。Cpp-我们项目的文件。我们使用 XCode 9.0将构建时间减少到30% 。中的所有私有未命名编译单元命名空间的名称。Cpp-档案。否则,本地名称将发生冲突。