GCC和预编译头 [英] GCC and Precompiled Headers

查看:287
本文介绍了GCC和预编译头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读这篇漂亮的文章(关怀与喂养编译标题),我对这些在现实生活中如何实际工作有些疑问。更具体来说,我如何知道在以下情况下需要触发重新编译预编译的头文件:




  • 我决定一个.cpp文件中的某个东西改变了预处理程序解释已经包含在我的预先编译的头文件中的一些标题的方式。

  • 我在其中一个.cpp文件中包含另一个标题,其中<。c $ c> #define 具体的预处理器指令改变了预处理器解析头的方式包含在预编译的标题中

  • 更糟的是,以前的问题可能会递归发生,当某些标题 #include 其他标题



如果预编译头的使用强制执行某种限制性编码风格,如将.cpp文件中包含的头文件数限制为一个,而不是 #define 在.cpp文件中的东西?



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



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

解决方案

当前的GCC(即4.7)及其以前的版本可以很好地与预编译标题,只有当您的应用程序具有单个公共标题时,并且当单个标题(其中包括所有系统的标题,以及特定的库)应用程序)是您应用程序的每个来源 #include -d(作为您的源的第一个非注释词典)。



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



回想一下, -H 是一个有用的选项获取 gcc 告诉您包含的内容。



您的源文件可能还有一些额外的 #include after #includeyourapp.h如果需要的话。 / p>

GCC已经包含了[单个]预编译头文件,您当然可以 #define 宏, #include 一些非预编译头,使用 #ifdef 等进行条件编译,但该预处理不会是pre编译!



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



有些人(特别是来自Google,特别是Diego Novillo)正在 PreParsed标题(pph)分支,以改善情况,但目前的海湾合作机构干线尚未完成。



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






addenda (2014年11月)



即使 GCC 4.9 也需要一个预编译的标题。 Diego Novillo等人预先解析的标题已被放弃



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



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


After reading this nice article (The Care and Feeding of Pre-Compiled Headers), I have some doubts regarding how these can actually work in real life. More specifically, how can I know that I need to trigger the rebuild of the pre-compiled header in the following scenarios:

  • I decide to #define something in one of my .cpp files that alters the way the pre-processor interprets some headers that are already included in my pre-compiled header
  • I include another header in one of my .cpp files which #defines a specific pre-processor directive that alters the way the pre-processor interprets a header already included in the precompiled header
  • Even worse, the previous issue can happen recursively, when certain headers #include other headers

Should the usage of pre-compiled headers enforce a certain restrictive coding style like limiting the number of headers included in .cpp files to one and never #defineing stuff in a .cpp file?

While Microsoft's compiler probably does a decent job with pre-compiled headers (by applying some MS-specific voodoo) because, as far as I know, it provides the /Yc and /Yu options that are supposed to do all the plumbing, for GCC it seems that this functionality requires a lot of manual work and creativity in the Makefile and I wasn't able to find a template that is supposed to address all the pitfalls of using pre-compiled headers.

For example, if I have a project which builds several libraries, in order not to rebuild all of them after each change, I have to use some really cute sed tricks in the Makefile to detect if one of the headers #included by the current library was modified (or it #includes a modified header). I fear to even think of the complications that pre-built headers would actually imply in order for the build script to rebuild them each time it is necessary.

解决方案

Current GCC (i.e. 4.7) and previous versions of it works nicely with precompiled headers only when you have a single common header to your application, and when that single header (which includes in turn all the system ones, and the library specific ones, required by the application) is #include-d (as the first non-comment lexeme of your sources) by every source of your application.

So you should have a single yourapp.h and have every source file (i.e. every compilation unit) of yourapp starting with #include "yourapp.h" with the same preprocessing options (i.e. -D or -I or -U) on the command line. That youapp.h header file is usually #include-ing many others, e.g. system headers (or GTK or Qt ones) like <stdlib.h> or <sys/poll.h> or [in C++] <algorithm> or <gtk/gtk.h> or <QtGui> etc.

Recall that -H is a useful option to get gcc tell you what is included.

Your source files might have some additional #include after #include "yourapp.h" if so wanted.

After a [single] precompiled header has been included by GCC, you may of course #define macros, #include some non-precompiled header, do conditional compilation with #ifdef, etc. But that preprocessing won't be "pre-compiled"!

This may not fit your needs or habits.

Some people (notably from Google, notably Diego Novillo) are working on the PreParsed Header (pph) branch to improve the situation, but the current GCC trunk has not got that work yet.

The explanation about that behavior of GCC is that a preprocessed header is essentially a persistent serialized checkpoint of the entire GCC heap (related to memory management inside GCC thru Ggc and GTY and gengtype). That checkpointed heap can be loaded only when gcc is in its initial empty state. As soon as something is known to gcc (actually cc1 or cc1plus) it cannot load any more any precompiled header file *.h.gch and will revert to parsing the textual header file *.h.


addenda (november 2014)

Even GCC 4.9 wants a single precompiled header. The pre-parsed header effort by Diego Novillo et al. has been abandoned.

Future versions (post C++14) of the C++ standard might define a module mechanism. See e.g. n4047 proposal.

(additional addenda, december 2015) This still holds for GCC-5 and the future GCC-6.

这篇关于GCC和预编译头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆