GCC和预编译头文件

6
阅读完这篇好文章(预编译头文件的使用与维护),我对它们在实际应用中如何工作有些疑问。更具体地说,以下情况下我如何知道需要触发预编译头文件的重建:
  • 我决定在其中一个.cpp文件中定义一些内容,以改变预处理器解释已经包含在预编译头文件中的某些头文件的方式
  • 我在其中一个.cpp文件中包含另一个头文件,该头文件定义了特定的预处理指令,以改变已经包含在预编译头文件中的头文件的解释方式
  • 更糟糕的是,前面的问题可能会递归发生,当某些头文件包含其他头文件时

预编译头文件的使用是否应强制执行某种限制性的编码风格,例如将.cpp文件中包含的头文件数量限制为一个,并且永远不要在.cpp文件中定义内容?

虽然据我所知,微软的编译器可能会通过应用一些MS特定的魔法来处理预编译头文件(因为它提供了/Yc/Yu选项来完成所有的管道工作),但对于GCC来说,似乎这个功能需要在Makefile中进行大量的手动工作和创造性工作,我无法找到一个模板来解决使用预编译头文件时遇到的所有问题。例如,如果我有一个构建多个库的项目,在每次更改后不重新构建所有库,则必须在Makefile中使用一些非常巧妙的sed技巧来检测当前库所包含的头文件是否已被修改(或者它包含了一个已修改的头文件)。我甚至不敢想象预先构建的头文件实际上会引起哪些复杂的问题,以便构建脚本在每次必要时都可以重建它们。
1个回答

15

当前的GCC(即4.7版本)和之前的版本仅在您的应用程序具有单个公共头文件并且该单个头文件(其中包括所有系统文件和库特定文件,这些文件由应用程序所需)被应用程序的每个源代码文件“#include”(作为源代码文件的第一个非注释词元)时,才可以很好地使用预编译头文件

因此,您应该有一个单一的yourapp.h文件,并让yourapp的每个源文件(即每个编译单元)都以相同的预处理选项(例如-D-I -U)以启动#include "yourapp.h"。那个youapp.h头文件通常会包含许多其他文件,例如系统文件(或GTK或Qt类似的)如<stdlib.h><sys/poll.h>或[在C ++中]<algorithm><gtk/gtk.h><QtGui>等。

请注意,-H是一个有用的选项,可以让gcc告诉您包含了哪些文件。

如果有需要,您的源代码文件可以在#include "yourapp.h"之后添加一些其他的#include

在GCC包含[单个]预编译头文件之后,您当然可以#define宏,#include一些非预编译头文件,使用#ifdef进行条件编译等。但是那样的预处理不会被“预编译”!

这可能不符合您的需求或习惯。

一些人(特别是来自Google,尤其是Diego Novillo)正在开发PreParsed Header (pph)分支以改善情况,但当前的GCC主干还没有实现此项工作。

GCC行为的解释是,预处理头文件本质上是GCC堆的持久化序列化检查点(与GCC内存管理相关,通过Ggc、GTY和gengtype)。只有当gcc处于其初始空状态时,才能加载该检查点堆。一旦gcc(实际上是cc1cc1plus)知道某些东西,它就无法再加载任何预编译的头文件*.h.gch,并将恢复到解析文本头文件*.h


添加附录 (2014年11月及以后)

即使是GCC 4.9也需要一个单独的预编译头文件。Diego Novillo等人的预解析头文件工作已经被放弃。

C++标准的未来版本(C++14之后)可能会定义一个模块机制。请参见n4047提案和C++20标准。

(额外添加的补充说明,2020年夏季)这对于GCC-10仍然有效,在那里有几个静态分析器选项。请参阅Clang静态分析器此草案报告。考虑使用Frama-C


是的,只需要一个头文件来包含所有内容可以消除大部分复杂性,但我在以前的工作场所看到了这种做法会让事情变得混乱的很好的例子。感谢您提供的详细而清晰的答案! - Mihai Todor
有趣。Borland引入了预编译头文件的概念,并且正是现在的PreParsed Headers试图做的事情。然后微软出现并宣布他们的方法更好,于是大家都跟着走了。 - Pete Becker
1
单个预编译头文件当然可以包含许多#include指令(而且通常应该这样做)。 - Basile Starynkevitch
@Mihai:什么是源代码作为预编译头文件的一部分? - Basile Starynkevitch
2
只有一个单独的 yourapp.h 文件可以作为预处理头文件,当 gcc 遇到的第一个词元是 #include "yourapp.h" 时,它的 yourapp.h.gch 预处理形式才会被使用。 - Basile Starynkevitch
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接