GCC和预编译头

时间:2012-09-15 13:53:14

标签: c++ gcc dependencies precompiled-headers

在阅读this nice article(预编译标题的护理和喂养)之后,我对这些在现实生活中如何实际起作用存在疑问。更具体地说,我怎么知道在以下场景中我需要触发预编译头的重建:

  • 我决定在我的.cpp文件中#define改变预处理器解释已经包含在我预编译头文件中的标头的方式
  • 我在我的一个.cpp文件中包含另一个标题,其中#define是一个特定的预处理器指令,用于改变预处理器解释已经包含在预编译标题中的标题的方式
  • 更糟糕的是,当某些标题#include其他标题
  • 时,上一个问题可以递归发生

预编译头文件的使用是否应强制执行某种限制性编码样式,例如将.cpp文件中包含的头文件数限制为一个而不是{.1}在.cpp文件中的内容?

虽然微软的编译器可能在使用预编译的头文件(通过应用某些特定于MS的voodoo)上做得不错,但据我所知,它提供了#define/Yc选项。应该做所有的管道,对于GCC来说,这个功能似乎需要Makefile中的大量手工工作和创造力,而我无法找到应该解决使用预编译头文件的所有陷阱的模板。

例如,如果我有一个构建多个库的项目,为了不在每次更改后重建所有库,我必须在Makefile中使用一些非常可爱的sed tricks来检测其中一个头当前库的/Yu d被修改(或#include修改了标题)。我担心甚至会想到预先构建的标头实际上意味着的复杂性,以便构建脚本在每次必要时重建它们。

1 个答案:

答案 0 :(得分:12)

当前GCC(即4.7)及其早期版本仅在您的应用程序具有单个公共标头时以及当该单个标头(包括在内)时与precompiled headers很好地协同工作应用程序的每个源都是#include - d(作为源的第一个非注释词条)。

所以你应该有一个单个 yourapp.h并且yourapp 的所有源文件(即每个编译单元)都以{{1}开始在命令行上使用相同的预处理选项(即#include "yourapp.h"-D-I)。该-U标头文件通常是youapp.h - 其他许多文件,例如系统标头(或GTK或Qt),如#include<stdlib.h>或[在C ++中] <sys/poll.h><algorithm><gtk/gtk.h>等。

回想一下,<QtGui>是让-H告诉您所包含内容的有用选项。

如果需要,您的源文件可能会在 gcc之后增加一些#include

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

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

有些人(特别是来自Google,尤其是Diego Novillo)正在研究PreParsed Header (pph) branch以改善这种情况,但目前的GCC主干还没有完成这项工作。

关于GCC行为的解释是,预处理头本质上是整个GCC堆的持久序列化检查点(与GCC内的memory management相关,通过Ggc和GTY以及#ifdef)。只有当gengtype处于初始空状态时,才能加载该检查点堆。只要gcc知道某些内容(实际上gcccc1),它就无法再加载任何预编译的头文件cc1plus,并且会恢复解析文本头文件{ {1}}。


addenda (2014年11月)

甚至GCC 4.9想要一个预编译的头。 Diego Novillo等人预解析的头部工作。已经被遗弃了。

C ++标准的未来版本(post C++14)可能会定义一个模块机制。参见例如n4047提案。

(附加附录,2015年12月)这仍适用于GCC-5和未来的GCC-6。