GCC和预编译头

Mih*_*dor 5 c++ dependencies gcc precompiled-headers

在阅读了这篇精彩的文章(预编译标题的关注和喂养)之后,我对这些文章在现实生活中如何实际起作用存在疑问.更具体地说,我怎么知道在以下场景中我需要触发预编译头的重建:

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

是否应该使用预编译的头文件强制执行某种限制性编码样式,例如将.cpp文件中包含的头文件数限制为一个并且永远不会将#define内容限制在.cpp文件中?

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

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

Bas*_*tch 12

目前GCC(即4.7)和它以前版本的作品很好地与预编译头,只有当你有一个共同的头到你的应用程序,并且当单头(其中包括把所有的系统的,和图书馆具体的,需要由应用程序)是你的应用程序的每个来源#include-d(作为你的来源的第一个非评论词汇).

所以,你应该有一个单一的 yourapp.h ,并有每一个源文件(即每编译单元)yourapp 开始#include "yourapp.h"使用相同的预处理方案(即-D-I-U)在命令行上.该youapp.h头文件通常#include-ing许多其他国家,例如,系统报头(或GTK或Qt的那些)等<stdlib.h><sys/poll.h>或[在C++] <algorithm><gtk/gtk.h><QtGui>

回想一下,这-H是一个有用的选项,可以gcc告诉您包含的内容.

源文件可能有一些额外的#include #include "yourapp.h"若有通缉.

在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提案.

(附加补遗,2015年12月)这仍然适用于GCC-5和未来的GCC-6.

  • 只有一个 `yourapp.h` 文件可以作为预处理头,并且仅当 `gcc` 遇到的第一个词素是 `#include "yourapp.h"` 时,才使用其 `yourapp.h.gch` 预处理形式 (2认同)