C++ #include 所有 .cpp 文件到一个编译单元?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/543697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:52:39  来源:igfitidea点击:

#include all .cpp files into a single compilation unit?

c++visual-studiobuild-processbuild

提问by Steve Folly

I recently had cause to work with some Visual Studio C++ projects with the usual Debug and Release configurations, but also 'Release All' and 'Debug All', which I had never seen before.

我最近有理由使用一些带有通常调试和发布配置的 Visual Studio C++ 项目,还有我以前从未见过的“全部发布”和“全部调试”。

It turns out the author of the projects has a single ALL.cpp which #includes all other .cpp files. The *All configurations just build this one ALL.cpp file. It is of course excluded from the regular configurations, and regular configurations don't build ALL.cpp

事实证明,项目的作者有一个 ALL.cpp,其中 #includes 所有其他 .cpp 文件。*All 配置只是构建这个 ALL.cpp 文件。它当然被排除在常规配置之外,常规配置不构建ALL.cpp

I just wondered if this was a common practice? What benefits does it bring? (My first reaction was that it smelled bad.)

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

What kinds of pitfalls are you likely to encounter with this? One I can think of is if you have anonymous namespaces in your .cpps, they're no longer 'private' to that cpp but now visible in other cpps as well?

您可能会遇到哪些陷阱?我能想到的一个问题是,如果您的 .cpps 中有匿名命名空间,它们不再是该 cpp 的“私有”名称,但现在在其他 cpp 中也可见?

All the projects build DLLs, so having data in anonymous namespaces wouldn't be a good idea, right? But functions would be OK?

所有的项目都构建 DLL,所以在匿名命名空间中保存数据不是一个好主意,对吧?但是功能就可以了吗?

Cheers.

干杯。

采纳答案by MSN

It's referred to by some (and google-able) as a "Unity Build". It links insanely fast and compiles reasonably quickly as well. It's great for builds you don't need to iterate on, like a release build from a central server, but it isn't necessarily for incremental building.

它被一些(和 google-able)称为“Unity Build”。它的链接速度非常快,编译速度也相当快。它非常适合您不需要迭代的构建,例如来自中央服务器的发布构建,但不一定适用于增量构建。

And it's a PITA to maintain.

这是一个需要维护的 PITA。

EDIT: here's the first google link for more info: http://buffered.io/posts/the-magic-of-unity-builds/

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

The thing that makes it fast is that the compiler only needs to read in everything once, compile out, then link, rather than doing that for every .cpp file.

使它快速的原因是编译器只需要读入一次,编译出来,然后链接,而不是对每个 .cpp 文件都这样做。

Bruce Dawson has a much better write up about this on his blog: http://randomascii.wordpress.com/2014/03/22/make-vc-compiles-fast-through-parallel-compilation/

布鲁斯·道森 (Bruce Dawson) 在他的博客上对此进行了更好的描述:http: //randomascii.wordpress.com/2014/03/22/make-vc-compiles-fast-through-parallel-compilation/

回答by Bruce Dawson

Unity builds improved build speeds for three main reasons. The first reason is that all of the shared header files only need to be parsed once. Many C++ projects have a lot of header files that are included by most or all CPP files and the redundant parsing of these is the main cost of compilation, especially if you have many short source files. Precompiled header files can help with this cost, but usually there are a lot of header files which are not precompiled.

Unity 构建改进的构建速度主要有以下三个原因。第一个原因是所有共享头文件只需要解析一次。许多 C++ 项目有很多头文件,大多数或所有 CPP 文件都包含这些头文件,而这些的冗余解析是编译的主要成本,尤其是当您有许多短源文件时。预编译头文件可以帮助解决这个成本,但通常有很多未预编译的头文件。

The next main reason that unity builds improve build speeds is because the compiler is invoked fewer times. There is some startup cost with invoking the compiler.

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

Finally, the reduction in redundant header parsing means a reduction in redundant code-gen for inlined functions, so the total size of object files is smaller, which makes linking faster.

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

Unity builds can also give better code-gen.

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

Unity builds are NOTfaster because of reduced disk I/O. I have profiled many builds with xperf and I know what I'm talking about. If you have sufficient memory then the OS disk cache will avoid the redundant I/O - subsequent reads of a header will come from the OS disk cache. If you don't have enough memory then unity builds could even make build times worse by causing the compiler's memory footprint to exceed available memory and get paged out.

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

Disk I/O is expensive, which is why all operating systems aggressively cache data in order to avoid redundant disk I/O.

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

回答by Arafangion

I wonder if that ALL.cpp is attempting to put the entire project within a single compilation unit, to improve the ability for the compiler to optimize the program for size?

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

Normally some optimizations are only performed within distinct compilation units, such as removal of duplicate code and inlining.

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

That said, I seem to remember that recent compilers (Microsoft's, Intel's, but I don't think this includes GCC) can do this optimization across multiple compilation units, so I suspect that this 'trick' is unneccessary.

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

That said, it would be curious to see if there is indeed any difference.

也就是说,很好奇是否确实存在任何差异。

回答by spforay

I agree with Bruce; from my experience I had tried implementing the Unity Build for one of my .dll projects which had a ton of header includes and lots of .cpps; to bring down the overall Compilation time on the VS2010(had already exhausted the Incremental Build options) but rather than cutting down the Compilation time, I ran out of memory and the Build not even able to finish the Compilation.

我同意布鲁斯的观点;根据我的经验,我曾尝试为我的一个 .dll 项目实施 Unity Build,该项目包含大量标头和大量 .cpp;为了减少 VS2010 上的整体编译时间(已经用完了增量构建选项),但没有减少编译时间,我用完了内存,构建甚至无法完成编译。

However to add; I did find enabling the Multi-Processor Compilation option in Visual Studio quite helps in cutting down the Compilation time; I am not sure if such an option is available across other platform compilers.

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

回答by onqtam

In addition to Bruce Dawson's excellent answerthe following link brings more insights onto the pros and cons of unity builds - https://github.com/onqtam/ucm#unity-builds

除了 Bruce Dawson 的出色回答之外,以下链接还提供了有关统一构建优缺点的更多见解 - https://github.com/onqtam/ucm#unity-builds

回答by Stephanie

We have a multi platform project for MacOS and Windows. We have lots of large templates and many headers to include. We halfed build time with Visual Studio 2017 msvc using precompiled headers. For MacOS we tried several days to reduce build time but precompiled headers only reduced build time to 85%. Using a single .cpp-File was the breakthrough. We simply create this ALL.cpp with a script. Our ALL.cpp contains a list of includes of all .cpp-Files of our project. We reduce build time to 30% with XCode 9.0. The only drawback was we had to give names to all private unamed compilation unit namespaces in .cpp-Files. Otherwise the local names will clash.

我们有一个适用于 MacOS 和 Windows 的多平台项目。我们有许多大型模板和许多标题要包含在内。我们使用预编译头文件使用 Visual Studio 2017 msvc 将构建时间减半。对于 MacOS,我们尝试了几天来减少构建时间,但预编译头文件仅将构建时间缩短到 85%。使用单个 .cpp 文件是一个突破。我们只需使用脚本创建这个 ALL.cpp。我们的 ALL.cpp 包含我们项目的所有 .cpp 文件的包含列表。我们使用 XCode 9.0 将构建时间减少到 30%。唯一的缺点是我们必须为 .cpp-Files 中的所有私有未命名编译单元命名空间命名。否则本地名称会发生​​冲突。