我有一个包含许多 Visual C++ 项目的解决方案,所有项目都使用 PCH,但有些项目打开了特定的编译器开关以满足项目特定的需求。
大多数这些项目在各自的 stdafx.h 中共享相同的标头集(STL、boost 等)。 我想知道是否可以在项目之间共享 PCH,这样我就可以拥有一个解决方案中的大多数项目都可以使用的通用 PCH,而不是编译每个项目的每个 PCH。
似乎可以在项目设置中将 PCH 的位置指定为共享位置,因此我预感这可行。 我还假设使用共享 PCH 的所有项目中的所有源文件都必须具有相同的编译器设置,否则编译器会抱怨 PCH 与正在编译的源文件之间不一致。
有人试过这个吗? 有效吗?
一个相关的问题:这样的分片 PCH 是否应该过度包容,或者会影响整体构建时间? 例如,共享 PCH 可以包括许多广泛使用的 STL 标头,但某些项目可能只需要
和
。 当优化器必须丢弃 PCH 拖入项目中的所有未使用的内容时,使用共享 PCH 节省的时间是否必须在构建过程的稍后时间点得到补偿?
I have a solution with many Visual C++ projects, all using PCH, but some have particular compiler switches turned on for project-specific needs.
Most of these projects share the same set of headers in their respective stdafx.h (STL, boost, etc). I'm wondering if it's possible to share PCH between projects, so that instead of compiling every PCH per-project I could maybe have one common PCH that most projects in the solution could just use.
It seems possible to specify the location of the PCH as a shared location in the project settings, so I have a hunch this could work. I'm also assuming that all source files in all projects that use a shared PCH would have to have the same compiler settings, or else the compiler would complain about inconsistencies between the PCH and the source file being compiled.
Has anyone tried this? Does it work?
A related question: should such a shard PCH be overly inclusive, or would that hurt overall build time? For example, a shared PCH could include many STL headers that are widely used, but some projecst might only need <string>
and <vector>
. Would the time saved by using a shared PCH have to be paid back at a later point in the build process when the optimizer would have to discard all the unused stuff dragged into the project by the PCH?
发布评论
评论(6)
萨毛萨的回答对我有用。
我还看到了这个链接 有效(在底部附近查找雷金纳德的答案)。
这个使用
copy
,而 Reginald 使用xcopy
(我更喜欢xcopy
)。 不管怎样,谢谢——这大大加快了我的构建速度。Samaursa's answer worked for me.
I also saw this link that works (look for Reginald's answer near the bottom).
This one uses
copy
while Reginald's usesxcopy
(I preferxcopy
). Either way, thanks--this sped up my builds considerably.对我来说,这听起来像是“收益递减”的情况。 假设直接包含公共头文件会浪费每个 .cpp 文件 1 秒,并且每个目标(DLL/EXE)有 10 个 .cpp 文件。 通过为每个目标使用 .pch,每个目标可以节省 10 秒。 如果您的整个项目有 10 个目标,则整个构建可节省 1.5 分钟,这很好。
但是,通过将整个项目减少到一个 .pch,您只能再节省 9 秒。 这值得么? 额外的工作(设置起来可能会更加繁琐,因为这是 VS 向导不支持的非标准配置)只产生了十分之一的节省。
This sounds like a case of "diminishing returns" to me. Suppose including the common headers directly wastes 1 second per .cpp file, and each target (DLL/EXE) has 10 .cpp files. By using a .pch per target, you save 10 seconds per target. If your whole project has 10 targets, you save 1.5 minutes on the whole build, which is good.
But by reducing it to one .pch for the whole project, you'd only save a further 9 seconds. Is it worth it? The extra effort (which may be a lot more fiddly to set up, being a non-standard configuration unsupported by VS wizards) produces only a 10th of the saving.
在 2012 年,您可以使用 PDB 并从仅将 pch 和依赖于 pch lib 的主项目构建到同一目录中的 lib 项目构建 pch(不复制),不幸的是,这不适用于 2013+除了通过冗长的工作循环。
On 2012, you can use a PDB and just build the pch from a lib project that only builds the pch and the main project that depends on the pch lib into the same directory (no copying), unfortunately this doesn't work with 2013+ except via a long winded work-a-round.
是的,这是可能的,我可以向您保证,节省的时间是巨大的。 编译 PCH 时,必须从创建 PCH 文件的项目中复制
.pdb
和.idb
文件。 就我而言,我有一个简单的两个文件项目,用于创建 PCH 文件。 标头将是您的 PCH 标头,并且源将被告知在项目设置下创建 PCH - 这与您在任何项目中通常执行的操作类似。 正如您所提到的,每个配置都必须具有相同的编译设置,否则会出现差异并且编译器会抱怨。每次重建或每次重新编译 PCH 时复制上述文件将会很痛苦,因此我们将自动化它。 要自动复制,请执行预构建事件,将上述文件复制到适当的目录。 例如,如果您正在编译 PCH 的
Debug
和Release
版本,请将文件从 PCH 项目的Debug
复制到依赖项目的调试
。 所以复制命令看起来像这样请注意末尾的
/-Y
。 第一次构建后,每个后续构建都会增量编译,因此如果再次替换文件,Visual Studio 将抱怨符号损坏。 如果它们确实损坏,您始终可以执行重建,这将再次复制文件(这次不会跳过它们,因为它们不再存在 - 清理会删除文件)。我希望这有帮助。 我花了相当长的时间才能够做到这一点,但这是值得的。 我有几个项目依赖于一个大框架,并且 PCH 只需要编译一次。 现在,所有依赖项目的编译速度都非常快。
Yes it is possible and I can assure you, the time savings are significant. When you compile your PCH, you have to copy the
.pdb
and.idb
files from the project that is creating the PCH file. In my case, I have a simple two file project that is creating a PCH file. The header will be your PCH header and the source will be told to create the PCH under project settings - this is similar to what you would do normally in any project. As you mentioned, you have to have the same compile settings for each configuration otherwise a discrepancy will arise and the compiler will complain.Copying the above mentioned files every time there is a rebuild or every time the PCH is recompiled is going to be a pain, so we will automate it. To automate copying, perform a pre-build event where the above mentioned files are copied over to the appropriate directory. For example, if you are compiling
Debug
andRelease
builds of your PCH, copy the files fromDebug
of your PCH project over to your dependent project'sDebug
. So a copy command would look like thisNote the
/-Y
at the end. After the first build, each subsequent build is incrementally compiled, therefore if you replace the files again, Visual Studio will complain about corrupted symbols. If they do get corrupted, you can always perform a rebuild, which will copy the files again (this time it won't skip them as they no longer exist - the cleanup deletes the files).I hope this helps. It took me quite some time to be able to do this, but it was worth it. I have several projects that depend on one big framework, and the PCH needs to be compiled only once. All the dependent projects now compile very quickly.
虽然这是一个老问题,但我想给出一个适用于 Visual Studio 2017 并且不涉及任何复制的新答案。 唯一的缺点:编辑并继续不再起作用。
基本上,您必须为预编译头创建一个新项目,并让所有其他项目依赖于它。 这是我所做的:
一步一步:
在您的解决方案中创建一个新项目,其中包括标头(从此处称为 pch.h)和一个包含 pch.h 的单行 cpp 文件。 该项目应该创建一个静态库。 设置新项目以创建预编译头。 输出文件需要可供所有项目访问。 对我来说,这与 IntDir 相关,但对于默认设置,它可能与 $(SolutionDir) 相关。 pch 项目必须只定义所有其他项目也有的定义。
让所有其他项目都依赖于这个新项目。 否则构建顺序可能是错误的。
设置所有其他项目以使用 pch.h。 看一下,输出文件参数与 pch 项目中的参数如何相同。 其他包含目录还需要指向 pch.h 目录。 您可以选择强制将 pch 文件包含在每个 cpp 中(或者手动将其包含在每个 cpp 文件的第一行中)。
我希望我没有忘记任何事情。 对于我的解决方案(130k loc,160 个项目),这导致编译时间为 ~2:30 分钟,而不是 ~3:30 分钟。
While this is an old question I want to give a new answer which works in Visual Studio 2017 and does not involve any copying. Only disadvantage: Edit and continue doesn't work anymore.
Basically you have to create a new project for the precompiled header and have all other project depend on it. Here is what I did:
Step by step:
Create a new project withnin your solution which includes the header (called pch.h from hereon) and a one line cpp file which includes pch.h. The project should create a static lib. Setup the new project to create a precompiled header. The output file needs to be accessible by all projects. for me this relative to IntDir, but for default settings it could be relative to $(SolutionDir). The pch project must only have defines all others projects have too.
Have all other projects depend on this new project. Otherwise the build order might be wrong.
Setup all other projects to use the pch.h. See, how the output file parameters are the same as in the pch project. Additional include directories also need to point to the pch.h directory. Optionally you can force include the pch file in every cpp (or you include it manually in the first line of every cpp file).
I hope I didn't forget anything. For my solution (130k loc, 160 projects) this lead to a compile time of ~2:30mins instead of ~3:30mins.
这似乎是不可能的,因为每个源文件都必须针对编译 PCH 的同一个 PDB 进行编译。 该死的。
It seems it's not possible because each source file has to be compiled against the same PDB against which the PCH was compiled. darn it.