fbpx
维基百科

预编译头

预编译头(precompiled header)是程序设计时把头文件编译为中间格式(如目标文件),以节约在开发过程中编译器反复编译该头文件的开销。 C语言C++语言Objective C语言等都有类似的技术。

有的头文件包含了巨量的源代码(如著名的windows.h),或者使用模板编程时要生成巨大的头文件模板库(如Eigen math library英语List of numerical librariesBoost C++ libraries英语Boost C++ libraries)。为减少编译时间,某些编译器允许把头文件编译为某种中间形式称为预编译头(precompiled header),后续再编译源文件时就可以尽量直接使用这些预编译头。

简单示例

C++文件source.cpp包括header.hpp

//header.hpp ... 
//source.cpp #include "header.hpp" ... 

首次编译source.cpp时,编译器生成header.pch的预编译头。以后再编译该程序时,编译器会比较该头文件的时间戳,如果头文件没有改变,编译器直接使用预编译头。

Visual Studio

Microsoft Visual Studio采取一个头文件(默认命名为stdafx.h),其内容是整个软件项目中被各个编译单元所使用的源代码,并极少修改。每个编译单元的源代码从最开始之处直至#include "stdafx.h"的内容完全相同。其中一个编译单元(源文件默认命名为"stdafx.cpp")以#include "stdafx.h"为最后一行(不考虑程序注释),并用编译选项/Yc"stdafx.h"编译,这将生成预编译头(默认命名为"<项目名>.pch"),包含了到#include "stdafx.h"这一行为止的所有代码编译结果。

项目中的其他编译单元,使用/Yu"stdafx.h"编译,这将把从开头直至#include "stdafx.h"这一行的源代码跳过编译过程,直接用预编译头(默认命名为"<项目名>.pch")代替。

stdafx中的AFX代表Application Framework eXtensions。AFX是Microsoft Foundation Classes (MFC)的旧称。编程者也可以用其他名字的头文件代替stdafx.h。

Visual Studio编译器确定预编译头的文件名,依照下述次序:[1]

  1. 编译器选项/Fp中给出的参数;
  2. 源文件中预处理器指令#pragma hdrstop [( "filename" )]给出的预编译头的文件名。源文件从开始之处至该行#pragma hdrstop的内容,用于创建预编译头(若使用/Yc选项)或者被预编译头取代(若使用/Yu选项)。
  3. /Yu"头文件基名.h"中的文件的base name加上后缀.PCH;
  4. 当前源文件的的base name加上后缀.PCH。

GCC

GCC3.4版开始支持预编译头。当编译器输入文件为头文件时(例如sample.h),产生预编译头,其文件名称是原来的头文件追加".gch"后缀(如sample.h.gch)。当gcc编译源文件时,对于遇到的每个头文件,都在INCLUDE路径中的每个目录下,先搜寻追加".gch"后缀的预编译头,如果没有再搜索该头文件。如果找到预编译头且满足一些条件,则直接使用该预编译头;否则就把该头文件在源文件中展开并编译之。[2] 可以在编译源文件时使用-H选项,如果显示的预编译头的全路径这一行是以"!"开始,说明编译器成功使用了预编译头;如果这一行以"x"开始,说明编译器找到了这一预编译头但未能使用它。

gcc对C语言的头文件与C++的头文件产生的格式不同,不能混用。如果头文件的名字不是".h"或".hpp"后缀结尾(C++标准库的头文件基本如此),可以用编译选项-x c++-header让gcc把当前的输入文件当作C++头文件来处理。用编译选项-x c-header让gcc把当前的输入文件当作C头文件来处理。[3]

使用预编译头时必须满足下列条件:

  • 编译一个源文件,至多只能使用一个预编译头。
  • 编译源文件时,如果先于预编译头对应的头文件编译器就扫描到C/C++的词(token),则不能使用该预编译头。也就是说,在预编译头对应的头文件之前的源文件中,只能有预处理指令(preprocessor directive)。 不能在另一个头文件中引入使用预编译头。
  • 预编译头与源文件必须是相同语言。不能在编译C++源文件时使用C语言的预编译头。
  • 预编译头与源文件应当由同一个编译器编译。以保证二进制兼容。
  • 在预编译头之前定义的宏(macro)或者被引入源程序时与预编译头生产时完全一致,或者预编译头没有用到该宏。这包括了由编译选项-D定义的宏、#define定义的宏、以及某些编译选项如-O或-Wdeprecated隐式定义的宏。
  • 源文件用-g选项编译以获取调试信息时,其使用的预编译头也应该是用-g编译选项生成的。但是,用-g选项编译生成的预编译头,也可用在没有调试信息输出的源文件编译。
  • 生成与使用预编译头,必须使用相同的-m选项。该编译选项给出目标硬件平台的相关信息。
  • 生成与使用预编译头,必须使用相同的-fexceptions选项。
  • 生成与使用预编译头,必须使用以-f, -p, -O开头的相同的命令行选项。目前还不知道哪些编译选项可以安全地改变或者决不能改变,最安全的选择是生成与使用预编译头使用相同的编译选项。已知下述选项可以安全地改变:
 -fmessage-length= -fpreprocessed -fsched-interblock -fsched-spec -fsched-spec-load -fsched-spec-load-dangerous -fsched-verbose=number -fschedule-insns -fvisibility= -pedantic-errors 

上述条件如果不被满足,编译器将自动使用头文件而不是对应的预编译头。

C++Builder

在项目默认配置中,C++Builder编译器无保留地生成在#pragma hdrstop之前所有头文件的预编译头。如果可能的话,预编译头会被项目的所有模块共享。例如,当使用Visual Component Library时,通常首先会包含vcl.h头文件,该头文件含有大多数经常被用到的VCL头文件。因此,预编译头被全项目共享可以显著减少生成时间。

另外,C++Builder能设置为使用一个特定的头文件作为预编译头,和Visual C++提供的机制类似。

C++Builder 2009引入了“Precompiled Header Wizard(预编译头向导)”来为被包含的头文件提取所有源码,然后自动为特定的文件分类(例如排除那些不是项目成员或者没有Include防范的头文件)、生成并测试预编译头。

外部链接

  • The Care and Feeding of Pre-Compiled Headers (页面存档备份,存于互联网档案馆
  • Fractal eXtreme: Precompiled headers (页面存档备份,存于互联网档案馆

参考文献

  1. ^ MSDN Help Document: hdrstop. [2015-06-07]. (原始内容于2018-09-24). 
  2. ^ . [2015-06-07]. (原始内容存档于2015-09-18). 
  3. ^ . [2015-06-07]. (原始内容存档于2015-09-18). 

预编译头, 沒有或很少條目链入本條目, 2015年6月18日, 請根据格式指引, 在其他相關條目加入本條目的內部連結, 來建構維基百科內部網絡, precompiled, header, 是程序设计时把头文件编译为中间格式, 如目标文件, 以节约在开发过程中编译器反复编译该头文件的开销, c语言, 语言, objective, c语言等都有类似的技术, 有的头文件包含了巨量的源代码, 如著名的windows, 或者使用模板编程时要生成巨大的头文件模板库, 如eigen, math, library, 英语, lis. 沒有或很少條目链入本條目 2015年6月18日 請根据格式指引 在其他相關條目加入本條目的內部連結 來建構維基百科內部網絡 预编译头 precompiled header 是程序设计时把头文件编译为中间格式 如目标文件 以节约在开发过程中编译器反复编译该头文件的开销 C语言 C 语言 Objective C语言等都有类似的技术 有的头文件包含了巨量的源代码 如著名的windows h 或者使用模板编程时要生成巨大的头文件模板库 如Eigen math library 英语 List of numerical libraries 与Boost C libraries 英语 Boost C libraries 为减少编译时间 某些编译器允许把头文件编译为某种中间形式称为预编译头 precompiled header 后续再编译源文件时就可以尽量直接使用这些预编译头 目录 1 简单示例 2 Visual Studio 3 GCC 4 C Builder 5 外部链接 6 参考文献简单示例 编辑C 文件source cpp包括header hpp header hpp source cpp include header hpp 首次编译source cpp时 编译器生成header pch的预编译头 以后再编译该程序时 编译器会比较该头文件的时间戳 如果头文件没有改变 编译器直接使用预编译头 Visual Studio 编辑Microsoft Visual Studio采取一个头文件 默认命名为stdafx h 其内容是整个软件项目中被各个编译单元所使用的源代码 并极少修改 每个编译单元的源代码从最开始之处直至 include stdafx h 的内容完全相同 其中一个编译单元 源文件默认命名为 stdafx cpp 以 include stdafx h 为最后一行 不考虑程序注释 并用编译选项 Yc stdafx h 编译 这将生成预编译头 默认命名为 lt 项目名 gt pch 包含了到 include stdafx h 这一行为止的所有代码编译结果 项目中的其他编译单元 使用 Yu stdafx h 编译 这将把从开头直至 include stdafx h 这一行的源代码跳过编译过程 直接用预编译头 默认命名为 lt 项目名 gt pch 代替 stdafx中的AFX代表Application Framework eXtensions AFX是Microsoft Foundation Classes MFC 的旧称 编程者也可以用其他名字的头文件代替stdafx h Visual Studio编译器确定预编译头的文件名 依照下述次序 1 编译器选项 Fp中给出的参数 源文件中预处理器指令 pragma hdrstop filename 给出的预编译头的文件名 源文件从开始之处至该行 pragma hdrstop的内容 用于创建预编译头 若使用 Yc选项 或者被预编译头取代 若使用 Yu选项 Yu 头文件基名 h 中的文件的base name加上后缀 PCH 当前源文件的的base name加上后缀 PCH GCC 编辑GCC3 4版开始支持预编译头 当编译器输入文件为头文件时 例如sample h 产生预编译头 其文件名称是原来的头文件追加 gch 后缀 如sample h gch 当gcc编译源文件时 对于遇到的每个头文件 都在INCLUDE路径中的每个目录下 先搜寻追加 gch 后缀的预编译头 如果没有再搜索该头文件 如果找到预编译头且满足一些条件 则直接使用该预编译头 否则就把该头文件在源文件中展开并编译之 2 可以在编译源文件时使用 H选项 如果显示的预编译头的全路径这一行是以 开始 说明编译器成功使用了预编译头 如果这一行以 x 开始 说明编译器找到了这一预编译头但未能使用它 gcc对C语言的头文件与C 的头文件产生的格式不同 不能混用 如果头文件的名字不是 h 或 hpp 后缀结尾 C 标准库的头文件基本如此 可以用编译选项 x c header让gcc把当前的输入文件当作C 头文件来处理 用编译选项 x c header让gcc把当前的输入文件当作C头文件来处理 3 使用预编译头时必须满足下列条件 编译一个源文件 至多只能使用一个预编译头 编译源文件时 如果先于预编译头对应的头文件编译器就扫描到C C 的词 token 则不能使用该预编译头 也就是说 在预编译头对应的头文件之前的源文件中 只能有预处理指令 preprocessor directive 不能在另一个头文件中引入使用预编译头 预编译头与源文件必须是相同语言 不能在编译C 源文件时使用C语言的预编译头 预编译头与源文件应当由同一个编译器编译 以保证二进制兼容 在预编译头之前定义的宏 macro 或者被引入源程序时与预编译头生产时完全一致 或者预编译头没有用到该宏 这包括了由编译选项 D定义的宏 define定义的宏 以及某些编译选项如 O或 Wdeprecated隐式定义的宏 源文件用 g选项编译以获取调试信息时 其使用的预编译头也应该是用 g编译选项生成的 但是 用 g选项编译生成的预编译头 也可用在没有调试信息输出的源文件编译 生成与使用预编译头 必须使用相同的 m选项 该编译选项给出目标硬件平台的相关信息 生成与使用预编译头 必须使用相同的 fexceptions选项 生成与使用预编译头 必须使用以 f p O开头的相同的命令行选项 目前还不知道哪些编译选项可以安全地改变或者决不能改变 最安全的选择是生成与使用预编译头使用相同的编译选项 已知下述选项可以安全地改变 fmessage length fpreprocessed fsched interblock fsched spec fsched spec load fsched spec load dangerous fsched verbose number fschedule insns fvisibility pedantic errors 上述条件如果不被满足 编译器将自动使用头文件而不是对应的预编译头 C Builder 编辑在项目默认配置中 C Builder编译器无保留地生成在 pragma hdrstop之前所有头文件的预编译头 如果可能的话 预编译头会被项目的所有模块共享 例如 当使用Visual Component Library时 通常首先会包含vcl h头文件 该头文件含有大多数经常被用到的VCL头文件 因此 预编译头被全项目共享可以显著减少生成时间 另外 C Builder能设置为使用一个特定的头文件作为预编译头 和Visual C 提供的机制类似 C Builder 2009引入了 Precompiled Header Wizard 预编译头向导 来为被包含的头文件提取所有源码 然后自动为特定的文件分类 例如排除那些不是项目成员或者没有Include防范的头文件 生成并测试预编译头 外部链接 编辑The Care and Feeding of Pre Compiled Headers 页面存档备份 存于互联网档案馆 Precompiled Headers with GCC Fractal eXtreme Precompiled headers 页面存档备份 存于互联网档案馆 参考文献 编辑 MSDN Help Document hdrstop 2015 06 07 原始内容存档于2018 09 24 GCC online documentation 3 20 Using Precompiled Headers 2015 06 07 原始内容存档于2015 09 18 GCC online documentation 3 2 Options Controlling the Kind of Output 2015 06 07 原始内容存档于2015 09 18 取自 https zh wikipedia org w index php title 预编译头 amp oldid 75340636, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。