我最近有理由使用通常的Debug和Release配置来处理一些Visual Studio C ++项目,还有'Release All'和'Debug All',这是我以前从未见过的。
事实证明,项目的作者只有一个ALL.cpp,其中#includes所有其他.cpp文件。 *所有配置只构建一个ALL.cpp文件。它当然被排除在常规配置之外,并且常规配置不构建ALL.cpp
我只是想知道这是否是一种常见做法?它带来了什么好处? (我的第一反应是闻起来很糟糕。)
您可能会遇到哪些陷阱?我能想到的是,如果你的.cpps中有匿名命名空间,它们不再是那个cpp的“私有”,但现在也可以在其他cpp中看到了吗?
所有项目都构建了DLL,因此在匿名命名空间中存储数据不是一个好主意,对吧?但功能还可以吗?
干杯。
答案 0 :(得分:56)
有些人(和google-able)称之为“Unity Build”。它疯狂地链接并且合理地快速编译。它非常适合您不需要迭代的构建,例如来自中央服务器的版本构建,但它不一定用于增量构建。
这是一个维持的PITA。
编辑:这是第一个获取更多信息的Google链接:http://buffered.io/posts/the-magic-of-unity-builds/
使它快速的事情是编译器只需要读入一次,编译,然后链接,而不是为每个.cpp文件执行此操作。
布鲁斯道森在他的博客上有更好的写作:http://randomascii.wordpress.com/2014/03/22/make-vc-compiles-fast-through-parallel-compilation/
答案 1 :(得分:47)
Unity构建改进的构建速度有三个主要原因。第一个原因是所有共享头文件只需要解析一次。许多C ++项目都有大量的头文件,大多数或所有CPP文件都包含这些头文件,这些文件的冗余解析是编译的主要成本,特别是如果你有很多短源文件。预编译的头文件可以帮助您节省这笔费用,但通常会有很多未预编译的头文件。
统一构建提高构建速度的下一个主要原因是编译器调用次数较少。调用编译器会有一些启动成本。
最后,冗余头解析的减少意味着内联函数的冗余代码生成减少,因此目标文件的总大小更小,这使链接更快。
Unity构建也可以提供更好的代码。
由于磁盘I / O减少,Unity构建 NOT 更快。我用xperf描述了许多构建,我知道我在说什么。如果您有足够的内存,那么操作系统磁盘缓存将避免冗余I / O - 后续读取标头将来自操作系统磁盘缓存。如果你没有足够的内存,那么统一构建甚至会使编译器的内存占用超过可用内存并被分页,从而使构建时间变得更糟。
磁盘I / O很昂贵,这就是为什么所有操作系统都积极地缓存数据以避免冗余磁盘I / O.
答案 2 :(得分:6)
我想知道ALL.cpp是否试图将整个项目放在一个编译单元中,以提高编译器优化程序大小的能力?
通常,某些优化仅在不同的编译单元中执行,例如删除重复的代码和内联。
那就是说,我似乎记得最近的编译器(微软,英特尔,但我不认为这包括GCC)可以跨多个编译单元进行这种优化,所以我怀疑这个'技巧'是不必要的。
那就是说,看看确实存在任何差异会很奇怪。
答案 3 :(得分:3)
我同意布鲁斯的意见;根据我的经验,我曾尝试为我的.dll项目实施Unity Build,其中包含大量包含大量的.cpps;为了降低VS2010的整体编译时间(已经耗尽了增量构建选项)但是我没有减少编译时间,而是内存不足而且Build甚至无法完成编译。
然而要补充;我确实发现在Visual Studio中启用多处理器编译选项非常有助于减少编译时间;我不确定其他平台编译器是否可以使用这样的选项。
答案 4 :(得分:0)
除了布鲁斯道森的excellent answer之外,以下链接为团结构建的利弊提供了更多见解 - https://github.com/onqtam/ucm#unity-builds
答案 5 :(得分:0)
我们有一个针对MacOS和Windows的多平台项目。我们有许多大型模板和许多标头。我们使用预编译标头将Visual Studio 2017 msvc的构建时间缩短了一半。对于MacOS,我们尝试了几天以减少构建时间,但预编译的标头仅将构建时间减少到85%。突破是使用单个.cpp文件。我们只需使用脚本创建此ALL.cpp。我们的ALL.cpp包含项目所有.cpp文件的包含列表。我们使用XCode 9.0将构建时间减少到30%。唯一的缺点是我们必须为.cpp-Files中的所有私有未修饰的编译单元命名空间命名。否则,本地名称将发生冲突。