在 VC++ 项目中开始使用 PCH

Posted

技术标签:

【中文标题】在 VC++ 项目中开始使用 PCH【英文标题】:Getting started with PCH in a VC++ project 【发布时间】:2013-05-23 06:30:49 【问题描述】:

我正在 VS 2012 中开发一个 VC++ 项目,完整编译大约需要 8-10 分钟。我知道 PCH 可以将编译时间加快 10 倍。我目前在我的项目中禁用了 PCH,并且在需要的地方包含了头文件。我如何开始使用 PCH?我到处寻找“操作方法”指南,但我得到的只是文档。

我假设我必须这样做:

    为 PCH 配置我的项目,创建一个空白的 PCH 头文件 从每个.cpp文件中收集头文件并将其放入PCH头文件中 修改每个文件,删除所有头文件导入 重新编译,希望不会出错 ;)

我如何开始使用这个(特别是#1)?您是否修改了项目以使用 PCH,其中的绊脚石或常见问题/问题是什么? PCH 会导致任何问题,还是它与正常包含的编译时/运行时行为相同?是否有工具可以自动化该过程,还是我必须手动浏览 500 个 .cpp 文件并对其进行修改以使用 PCH?

最后但并非最不重要的一点是,PCH 的编译时间加速是多少?是2x-10x吗?还是会快 30%? (这并不能证明所涉及的时间是合理的)

【问题讨论】:

【参考方案1】:

将我的项目配置为使用 PCH 后,完整编译时间减少了一半,增量构建几乎立即发生。 PCH 是一种非常有效的加速编译时间的方法,我强烈推荐它。

Althouh dsharlet 提到了许多重要的点,他跳过了一些我最终必须弄清楚的关键步骤。因此,这里是配置项目以使用 PCH 的完整指南:

在 VC++ 项目中开始使用 PCH

    备份您的src 目录和任何其他包含源代码的目录...(如果出现任何问题,您将需要这个)

    在您的项目中创建 2 个文件,Globals.cppGlobals.h ..(选择任何名称但坚持使用)

    右键Globals.cpp打开属性,选择配置>所有配置

    转到 C/C++ |预编译的Header,并填写:

    预编译头文件:创建 (/Yc) 预编译头文件:Globals.h

    打开Globals.cpp并添加这一行,仅此而已#include "Globals.h"

    右键单击您的 VC++ 项目并打开 属性,选择配置 > 所有配置

    转到 C/C++ |预编译的Header,并填写:

    预编译头文件:使用 (/Yu) 预编译头文件:Globals.h

    打开项目中的所有.h.cpp 文件,并在最顶部添加:#include "Globals.h"

    打开Globals.h 并在其中添加以下内容:(非常重要的是您在顶部有#pragma once

     #pragma once
    
     #include <stdio.h>
     #include <stdlib.h>
     #include <stdarg.h>
     #include <stddef.h>
     #include <memory>
     #include <string.h>
     #include <limits.h>
     #include <float.h>
     #include <time.h>
     #include <ctype.h>
     #include <wchar.h>
     #include <wctype.h>
     #include <malloc.h>
     #include <locale.h>
     #include <math.h>
    
     // Windows SDK
     #define _WIN32_WINNT 0x0501     // _WIN32_WINNT_WINXP
     #include <SDKDDKVer.h>
    
     // Windows API
     #define WIN32_LEAN_AND_MEAN
     #include <windows.h>
    
    这些包括是 PCH 文件的典型候选对象 删除不使用的包含 浏览您的项目并收集更多不经常更改的头文件

    使用查找和替换,在 PCH 文件中搜索每个 #include,并将它们从项目中的所有 .h.cpp 文件中删除。

    李>

    进行完整编译并确保一切正常。以下是您将遇到的常见问题的一些解决方案:


PCH 文件包含自身:

您的 PCH 文件包含一个包含 PCH 头文件的头,创建了一种循环依赖。双击错误将您带到有问题的文件,只需删除显示#include "Globals.h"的行


未定义符号 X

虽然你所有的项目文件都可以包含PCH头文件,但是包含在里面PCH头文件的文件不能包含PCH头文件! (如上所述),因此您需要重新添加之前在文件中的所有导入。 (将文件与备份版本进行比较)


找不到符号 logf

有时全局 PCH 文件的行为不符合预期,并且会因无法解决的疯狂错误而中断编译。然后,您可以关闭单个源代码文件的 PCH。

    右键单击您的.cpp 文件并打开属性,选择配置> 所有配置

    转到 C/C++ |预编译的Header,并填写:

    预编译头文件:不使用预编译头文件

    删除.cpp 文件中的#include "Globals.h"

    添加文件最初的所有导入。 (将文件与备份版本进行比较)

【讨论】:

【参考方案2】:

以下是我如何使用 PCH 并取得不错的效果:

    转到项目属性,C/C++|PCH 将 Precompiled Header 选项设置为“使用”。将 Precompiled Header File 设置为您想要的。 转到您想成为 PCH 的 cpp 文件的属性,并将 Precompiled Header 选项设置为“创建”(项目属性设置中默认为“使用”)。 在项目中的所有 cpp 文件中包含 pch 头文件(基本上,那些为 Precompiled Header 选项设置了“使用”的文件)。我想您可以关闭项目中某些 cpp 文件的“使用”,而不是为 PCH 添加包含,但我从未尝试过...

此时,项目仍应像以前一样构建和运行,但编译时间可能没有任何真正的改进。现在,您需要将 一些 #include "...h" 移动到 PCH 头文件(并从项目的其他位置删除这些文件的包含)。您应该移至 PCH 标头的包含应该是包含在许多文件中,但很少更改的标头。示例:STL 标头、windows.h、项目中的核心功能标头等。

PCH 设置后,应该是透明的。它基本上只是帮助编译器缓存一些中间编译数据。换句话说,如果你在你的项目中关闭了 PCH,所有的东西仍然应该和打开 PCH 时一样构建(除了更慢!)

加速完全取决于将多少代码移入 PCH(有多少头文件中包含的代码从任意 cpp 文件移至 PCH 头文件)。我已经看到了多次改进,但没有精确地对其进行基准测试。 当我在一个大项目中使用 PCH 遇到麻烦时,我绝对觉得这样做是值得的。

【讨论】:

我应该将每个 .h 文件添加到其中吗?我的项目包含大约 250 个 .h 文件和 250 个 .cpp 文件,我应该添加所有内容以获得最大加速吗?还是每次我更改其中一个 .h 文件都会导致 PCH 失效,从而导致几乎相同的减速? "使用 'just stick everything in stdafx.h' 风格编写的代码很容易维护,因为更改任何头文件中的任何内容都可能导致整个代码库重新编译每个时间。这可以使简单的重构花费很长时间,因为每次更改和重新编译周期都比它应该花费的时间长得多。 ...***.com/questions/290034/… 只将不经常更改的文件添加到 PCH。否则,速度可能会比您设置 PCH 文件之前更糟,因为您正在使每个使用 PCH 的 cpp 文件无效,而不仅仅是包含已修改标头的 cpp 文件。 你的意思是“stdlib.h”、“float.h”、“math.h”、“memory”?? 是的。您也可以从您的项目中添加标题,而不是经常更改的标题。没有单一的规则可以决定,您必须根据具体情况自己找出答案。

以上是关于在 VC++ 项目中开始使用 PCH的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3 - 表 VC(使用 coredata)和细节 VC 的故事板设计 *从默认信息的细节 VC 开始*

VC++ try catch

VC++ try catch

VC++ try catch

UIKit框架(15)PCH头文件

c语言中各种文件,如ILK,PCH,PDB等分别指啥文件?有啥用?