23

我目前正在将一个大型 RAD Studio 2010 项目迁移到 XE4。作为其中的一部分,我正在重新创建许多项目文件。我想借此机会确保我们对预编译头文件使用了最好的机制,因为似乎有几种方法可以做到这一点。

现在我们只编译 32 位,但将来会使用 64 位编译器。

以下是我们目前在 2010 年所做的事情,以及为什么我不确定在 XE4 中该做什么:

在 RAD 工作室 2010 中

我们有一个文件PchApp.h,其中包含<vcl.h>和其他一些常用的头文件,主要是项目中各种常用核心类的头文件。此标头包含在每个 CPP 文件的顶部,后跟#pragma hdrstop,如下所示:

// Top of .cpp file
#include "PchApp.h"
#pragma hdrstop

// Normal includes here
#include "other.h"
#include "other2.h"
// etc

然后我们在项目选项的 Precompiled Headers 部分有以下设置:

当前 RS2010 预编译头设置

编译速度不是特别快(大约 350,000 行代码需要 12 分钟。)我不确定:

  • “注入预编译的头文件”:这应该注入 PchApp.h 吗?
  • “缓存预编译头文件(必须与 -H 或 -H“xxx”一起使用)”:-H 选项是“PCH 文件名”,所以我们使用它,但预编译头文件的重点肯定是它是“缓存”或每次编译预构建一次。这有什么额外的区别?
  • 我们是否应该在 .cpp 文件中包含两行来包含 PchApp.h 和 pragma hdrstop ?有没有办法只在项目选项中执行此操作,而不是在每个文件中重复这两行?他们有必要吗?

换句话说,我不确定这些设置是否正确或最佳,但通过阅读文档,我同样不确定什么会更好。我知道我对所有选项的理解不够透彻 - 这个问题的一个原因:)

在 RAD Studio XE4 中

XE4 32 位编译器的选项对话框是相同的,但有两件事让我感到困惑和/或让我不确定当前的 2010 方法是最好的。

1.默认行为

在创建新的 VCL Forms 项目时,IDE 会创建一个默认命名为 Project1PCH1.h 的头文件,该头文件旨在作为项目的预编译头文件。 此标头包括<vcl.h><tchar.h>,并且在项目管理器中显示为一个节点。它不包含在默认的 Form1.cpp 中,但#include <vcl.h>紧随其后的#pragma hdrstop是 Form1.cpp 的最顶部,然后是其他标题。

使用此标头的新项目的默认 XE4 设置对话框是: XE4 默认预编译头设置

我(天真地?)假设默认值实际上是最佳/最佳设置。有些事情让我感到困惑:

  • 该项目的预编译头文件Project1PCH1.h在任何地方的预编译头文件设置中都没有提及。
  • 标头未缓存
  • 未指定 PCH 文件名(应该是Project1PCH1.h?)
  • .cpp 文件也不包括在内Project1PCH1.h

事实上,我不知道编译器或 IDE 是如何真正知道它应该使用Project1PCH1.h或应该使用它的 .cpp 文件的,因为我找不到任何方式来引用它。

这对我来说是最令人困惑的事情,也是提出这个问题并消除我对 PCHe 的所有困惑的动力。我曾计划复制/使用 IDE 的默认设置,但在我了解他们在做什么之前我不想这样做。

2. PCH 向导

自 2010 年以来,IDE 已包含一个预编译的标头向导。我一直无法让它工作 - 我现在再次运行它以获得它的结果并解释我对“不起作用”的记忆,但它似乎需要几个小时,所以我会更新这个问题之后。

编辑:它运行,虽然它需要几个小时,并产生了一个列表(对我来说,知道源库)奇怪的标题。我对几年前尝试过的回忆是它根本没有运行 - 一个明显的改进。

由于它存在,它可能是在为升级 2010 项目而形成的新创建的项目文件中使用预编译头文件进行设置的最佳方式。我怎样才能最好地做到这一点?包括 PchApp.h 在内的所有 .cpp 文件都会混淆它吗?

问题

以此为背景,我有以下问题:

  • 现有设置。我正在创建一个新项目文件并添加数千个预先存在的 .cpp 文件,所有文件的顶部都带有“#include PchApp.h; #pragma hdrstop”。我应该复制现有的 RS2010 PCH 设置吗?我应该删除以上两行并用其他内容替换它们吗?
  • 使用 PCH 向导:根据您的经验,这是否可以创建最佳设置?它是否包含如果修改会导致项目的大部分区域被重建(可能不是编码的最佳选择)的文件?是否可以在现有项目上使用,或者像我们的“#include PchApp.h”这样的项目需要在使用之前删除吗?
  • CPP 文件/单位和正确的包括。使用预编译头文件的 .cpp 文件是否应该不包含预编译头文件本身,而只包含 .cpp 实际需要的头文件,即使 PCH 包含这些头文件?如果您有我们目前的情况,其中 PchApp.h 文件包含几个常见的头文件,而 .cpp 文件实际上并不包含这些文件本身,该怎么办?如果删除 PchApp.h 的包含并将其替换为特定 .cpp 文件所需的 PchApp.h 中的标头子集,它们应该高于还是低于 #pragma hdrstop?(以上,我认为。)如果您在上面包含其他未包含在预编译头文件中的内容怎么办 - 它会改变该特定单元的 PCH 使用情况,导致重建 PCH(性能问题?)等?
  • 默认设置:假设新项目的默认设置是最佳的,那么如何最好地将当前系统迁移到使用它?
  • 非默认设置:如果默认设置不是最优的,那是什么?我想,这是关键问题。
  • 32 位和 64 位:知道我们将很快迁移到 64 位,我们应该怎么做才能让预编译的头文件同时在 32 位和 64 位上工作?所有 PCH 知识都应该在项目选项中而不是 .cpp 文件中,所以 32 位和 64 位编译的设置不同?

我正在寻求一个清晰、详细、解释性、指导性的答案,一个清楚地解释最佳实践、设置选项、要包含在 .cpp 文件、标题和/或项目文件中的项目等等 - 换句话说,一些到现在(毕竟以上!)清理我的理解相当混乱。将来其他 C++Builder 用户可以将其用作 PCH 参考的高质量答案将非常好。我打算在可能的几天内增加赏金。

4

2 回答 2

1

这就是我所做的(虽然我不确定这是否是一个好主意,但它似乎有效)

  1. 确保 Project1PCH1.h 存在(其中 Project1 是项目的名称)
  2. 使其包含#pragma hdrstop和 2 个尾随换行符(当我没有尾随换行符时出现奇怪的错误,可能是编译器错误)
  3. 在“所有配置”中放入“注入预编译头文件”,然后命名为“Project1PCH1.h”
  4. 不要在其他文件中做#include "PchApp.h"任何事情。#pragma hdrstop
  5. 检查一切是否正确构建(即文件具有正确的包含本身的优点,而不依赖于注入的 PCH)
  6. 将一些包含到 Project1PCH1.h 中。我使用向导来提出一些建议,但是您还必须应用一些人工逻辑才能获得良好的构建。

当它在 32 位模式下正常工作时,一切都编译得很快;如果您正在编译您的项目并且一个特定的 .cpp 文件比其他文件花费的时间要长得多,那么您可以判断您是否做得不对。该向导根据包含给定标头的文件数量提出建议,但这有点虚假;如果它不是 PCH 的一部分,您需要在其中包含任何会显着增加编译时间的系统头文件(或 boost 头文件等)。

我不想在其中包含我自己的项目标头,只是系统和标准标头。根据您的项目 IDK,这可能对您有所不同。

PCH 不适用于.c文件,因此如果您的文件中有任何这些文件,则需要使 Project1PCH1.h 具有#ifdef __cplusplus警卫。

另外:即使 bcc64 不支持 PCH(但它确实注入了文件),如果您确实设置了正确的 PCH,它似乎确实使编译速度更快,我不确定为什么。


我还不明白的事情:

  • 为什么新建项目向导会自动生成 Project1PCH1.h 但实际上并未在项目属性的“注入预编译头文件”字段中进行设置?
  • 有时构建失败说它无法打开 Project1PCH1.h 但如果我进行一些更改并重新保存它通常似乎可以解决这个问题。
于 2014-06-15T22:35:21.987 回答
1
  1. Existing settings. In my experience I have changed these settings usually, because if you have hundreds of files - it's just does not seem to be optimal. In xCode i.e. it's the default configuration. There should be no compilation performance difference.
  2. Using the PCH wizard Honestly I have never used it in real project, and it haven't impressed me, so just forgot about that and used manual settings.
  3. CPP files / units and the correct includes. Different IDEs have different default settings for that. What I have usually used is:
    • Inject precompiled headers automatically (no manual #include in .cpp)
    • First include appropriate header matching .cpp if one exists (myfile.cpp - then include myfile.h)
    • After that include all the specific headers that do specific job (specific lib headers, etc.)
    • In "myfile.h" include ONLY stuff that is a must. Avoid any stuff you can avoid.
    • Everything you include specifically for a particular .cpp file should be below #pragma hdrstop. Everything you want to be precompiled should be above.
  4. Default setup I don't think it's optimal. As for me it's much easier to migrate just changing a couple of options in the settings.
  5. Non-default setup As I have mentioned above - as for me the optimal set up is with automatic injection of precompiled header. More details in item 3.
  6. 32 and 64-bit haven't experienced any problems with that. It should generate own precompiled headers for every particular configuration.
于 2013-08-14T17:16:20.907 回答