此编译器选项可激活预编译头文件功能。v 可以是 auto、autofirst、collect: pch_filename 或 use:pch_filename。通过将 -xpch(在B.2.128 -xpch=v中进行了详细介绍)和 -xpchstop(在B.2.129 -xpchstop=[file|<include>]中进行了详细介绍)选项与 #pragma hdrstop 指令(在2.11.8 hdrstop中进行了详细介绍)结合使用,可利用此功能。
使用 -xpch 选项可以创建预编译头文件并减少编译时间。预编译头文件的作用是减少源代码共享同一组 include 文件的应用程序的编译时间,这些 include 文件往往包含大量的源代码。预编译头文件的工作机理是,首先从一个源文件收集一组头文件信息,然后在重新编译该源文件或者编译其他有同样头文件顺序的源文件时就可以使用这些收集到的信息。编译器收集的信息存储在预编译头文件中。
另请参见:
可以让编译器自动生成预编译头文件。选择以下两种方法之一来实现此目的。一种方法是让编译器从在源文件找到的第一个 include 文件创建预编译头文件。另一种方法是让编译器从在源文件中找到的 include 文件集合中选择,选择范围从第一个 include 文件开始,直到已经定义好的确定哪个 include 文件是最后一个的点结束。使用以下标志之一可以确定编译器用于自动生成预编译头文件的方法:
表 B–36 -xpch 标志
标志 |
含义 |
---|---|
-xpch=auto |
预编译头文件的内容基于编译器在源文件中找到的最长的活前缀(有关如何识别活前缀的说明,请参见下文)。此标志生成的预编译头文件可能包含最多的头文件。 |
-xpch=autofirst |
此标志生成的预编译头文件仅包含在源文件中找到的第一个头文件。 |
如果决定手动创建预编译头文件,则必须首先使用 -xpch,并指定 collect 模式。指定 -xpch=collect 的编译命令只能指定一个源文件。在以下示例中,-xpch 选项根据源文件 a.c 创建名为 myheader.cpch 的预编译头文件:
cc -xpch=collect:myheader a.c
有效的预编译头文件通常具有后缀 .cpch。在指定 pch_filename 时,后缀可以由您自己增加或由编译器增加。例如,如果指定 cc -xpch=collect:foo a.c,则预编译的头文件名为 foo.cpch。
如果编译器无法使用 -xpch=auto 和 -xpch=autofirst 时的预编译头文件,则会生成新的预编译头文件。如果编译器无法使用 -xpch=use 时的预编译头文件,将发出一个警告,并且使用真实头文件来完成编译。
您还可以指示编译器使用特定的预编译头文件。要实现此目的,请指定 -xpch=use:pch_filename。您可以将 include 文件同一序列中任意数量的源文件指定为用于创建预编译头文件的源文件。例如,在 use 模式中的命令可类似于以下命令: cc -xpch=use:foo.cpch foo.c bar.c foobar.c.
如果以下条件都成立,则只能使用现有的预编译的头文件。如果以下任意条件不成立,则应重新创建预编译头文件:
用于访问预编译头文件的编译器与创建预编译头文件的编译器相同。由某一版本的编译器创建的预编译头文件不能被其他版本的编译器使用。
除 -xpch 选项之外,用 -xpch=use 指定的编译器选项必须与创建预编译头文件时指定的选项相匹配。
用 -xpch=use 指定的包含头文件的集合与创建预编译头文件时指定的头文件集合是相同的。
用 -xpch=use 指定的包含头文件的内容与创建预编译头文件时指定的包含头文件的内容是相同的。
当前目录(即发生编译并尝试使用给定预编译头文件的目录)与创建预编译头文件所在的目录相同。
在用 -xpch=collect 指定的文件中预处理指令(包括 #include)的初始序列,与在用 -xpch=use 指定的文件中预处理指令的序列相同。
要在多个源文件间共享预编译头文件,这些源文件必须共享一组共同的 include 文件(按其初始标记序列)。标记是指关键字、名称或标点符号。被 #if 指令排除的注释和代码不能被编译器识别为标记。该初始标记序列称为活前缀。也就是说,活前缀是源文件中通用于所有源文件的最靠前的部分。创建预编译头文件并进而确定源文件中哪些头文件是预编译的时,编译器使用此活前缀作为整个操作的依据。
编译器在当前编译期间找到的活前缀必须与用于创建预编译头文件的活前缀匹配。也就是说,必须在使用相同预编译头文件的所有源文件中对活前缀给出一致的解释。
源文件的活前缀只能包含注释和以下任意预处理程序指令:
#include #if/ifdef/ifndef/else/elif/endif #define/undef #ident (if identical, passed through as is) #pragma (if identical)
以上任何指令都可以引用宏。#else、#elif 和 #endif 指令必须在活前缀内匹配。注释被忽略。
指定 -xpch=auto 或 -xpch=autofirst 时,编译器自动确定活前缀的终点,定义如下:
第一个声明/定义
第一个 #line 指令
#pragma hdrstop 指令
在指定的 include 文件之后(如果您指定 -xpch=auto 和 -xpchstop)
第一个 include 文件(如果您指定 -xpch=autofirst)
预处理程序条件编译语句中的终点会生成一个警告,并禁止自动创建预编译头文件。另外,如果同时指定 #pragma hdrstop 和 -xpchstop 选项,编译器将使用两个停止点中较早的那一个来终止活前缀。
对于 -xpch=collect 或 -xpch=use,活前缀以 #pragma hdrstop 结尾。
在共享预编译头文件的每个文件的活前缀中,每个相应的 #define 和 #undef 指令都必须引用相同的符号(例如每个 #define 必须引用同一个值)。这些指令在每个活前缀中出现的顺序也必须相同。每个相应 pragma 也必须相同,并且必须按相同顺序出现在共享预编译头文件的所有文件中。
如何能够使头文件可以预编译?在不同的源文件中解释一致时,头文件可以预编译。具体来说,就是当它仅包含完全声明时。也就是说,任何一个文件中的声明都必须独自成为有效声明。不完全的类型声明,例如 struct S;,是有效声明。完全类型声明可以出现在某些其他文件中。请考虑这些头文件示例:
file a.h struct S { #include "x.h" /* not allowed */ }; file b.h struct T; // ok, complete declaration struct S { int i; [end of file, continued in another file] /* not allowed*/ |
并入预编译头文件的头文件一定不得违反以下约束。这里没有定义对违反上述约束的程序的编译结果。
头文件不得使用 __DATE__ 和 __TIME__。
头文件不得包含 #pragma hdrstop。
如果头文件还包含变量和函数定义,则也是可预编译的。
编译器自动创建预编译头文件时,会将该文件写入 SunWS_cache 目录中。此目录始终位于创建目标文件的位置。该文件的更新受锁保护,这样可在 dmake 下正常工作。
如果需要强制编译器重新生成自动生成的预编译头文件,可以使用 CCadmin 工具清除预编译头文件高速缓存目录。有关更多信息,请参见 CCadmin(1) 手册页。
不要在命令行上指定冲突的 -xpch 标志。例如,同时指定 -xpch=collect 和 -xpch=auto 或同时指定 -xpch=autofirst 和 -xpchstop=<include> 会产生错误。
如果指定 -xpch=autofirst,或指定不带 -xpchstop 的 -xpch=auto,则出现在第一个 include 文件之前或出现在使用用于 -xpch=auto 的 -xpchstop 指定的 include 文件之前的任何声明、定义或 #line 指令都会生成警告,并禁止自动生成预编译头文件。
-xpch=autofirst 或 -xpch=auto 时的第一个 include 文件之前的 #pragma hdrstop 会禁止自动生成预编译头文件。
指定 -xpch=collect 时,编译器会生成预编译头文件的依赖性信息。需要在 make 文件中创建适当的规则,以利用这些依赖性。考虑下面的 make 文件示例:
%.o : %.c shared.cpch $(CC) -xpch=use:shared -xpchstop=foo.h -c $< default : a.out foo.o + shared.cpch : foo.c $(CC) -xpch=collect:shared -xpchstop=foo.h foo.c -c a.out : foo.o bar.o foobar.o $(CC) foo.o bar.o foobar.o clean : rm -f *.o shared.cpch .make.state a.out |
这些 make 规则以及编译器生成的依赖性,会在与 -xpch=collect 一起使用的任何源文件或属于预编译头文件的一部分的任何头文件发生更改时,强制重新创建手动创建的预编译头文件。这样可防止使用过期的预编译头文件。
您无需在 make 文件中为 -xpch=auto 或 -xpch=autofirst 创建任何其他 make 规则。