C and C++ compilation system

C++ precompiled headers

It is often desirable to avoid recompiling a set of header files, especially when they introduce many lines of code and the primary source files that #include them are relatively small. The C++ compiler provides a mechanism for, in effect, taking a snapshot of the state of the compilation at a particular point and writing it to a disk file before completing the compilation; then, when recompiling the same source file or compiling another file with the same set of header files, it can recognize the ``snapshot point,'' verify that the corresponding precompiled header (``PCH'') file is reusable, and read it back in. Under the right circumstances, this can produce a dramatic improvement in compilation time; the trade-off is that PCH files can take a lot of disk space.

Automatic precompiled header processing

When -Rauto appears on the CC command line, automatic precompiled header processing is enabled. This means the front end will automatically look for a qualifying precompiled header file to read in and/or will create one for use on a subsequent compilation.

The PCH file will contain a snapshot of all the code preceding the ``header stop'' point. The header stop point is typically the first token in the primary source file that does not belong to a preprocessing directive, but it can also be specified directly by #pragma hdrstop (see below) if that comes first. For example:

   #include "xxx.h"
   #include "yyy.h"
   int i;
The header stop point is int (the first non-preprocessor token) and the PCH file will contain a snapshot reflecting the inclusion of xxx.h and yyy.h. If the first non-preprocessor token or the #pragma hdrstop appears within a #if block, the header stop point is the outermost enclosing #if. To illustrate, here's a more complicated example:
   #include "xxx.h"
   #ifndef YYY_H
   #define YYY_H 1
   #include "yyy.h"
   #if TEST
   int i;
Here, the first token that does not belong to a preprocessing directive is again int, but the header stop point is the start of the #if block containing it. The PCH file will reflect the inclusion of xxx.h and conditionally the definition of YYY_H and inclusion of yyy.h; it will not contain the state produced by #if TEST.

A PCH file will be produced only if the header stop point and the code preceding it (mainly, the header files themselves) meet certain requirements:

When a precompiled header file is produced, it contains, in addition to the snapshot of the compiler state, some information that can be checked to determine under what circumstances it can be reused. This includes: This information comprises the PCH ``prefix.'' The prefix information of a given source file can be compared to the prefix information of a PCH file to determine whether the latter is applicable to the current compilation.

As an illustration, consider two source files:

   // a.C
   #include "xxx.h"
   ...                 // Start of code

// b.C #include "xxx.h" ... // Start of code

When a.C is compiled with CC -Rauto, a precompiled header file named a.pch is created. Then, when b.C is compiled (or when a.C is recompiled), the prefix section of a.pch is read in for comparison with the current source file. If the command line options are identical, if xxx.h has not been modified, and so forth, then, instead of opening xxx.h and processing it line by line, the front end reads in the rest of a.pch and thereby establishes the state for the rest of the compilation.

It may be that more than one PCH file is applicable to a given compilation. If so, the largest (i.e., the one representing the most preprocessing directives from the primary source file) is used. For instance, consider a primary source file that begins with

   #include "xxx.h"
   #include "yyy.h"
   #include "zzz.h"
If there is one PCH file for xxx.h and a second for xxx.h and yyy.h, the latter will be selected (assuming both are applicable to the current compilation). Moreover, after the PCH file for the first two headers is read in and the third is compiled, a new PCH file for all three headers may be created.

When a precompiled header file is created, it takes the name of the primary source file, with the suffix replaced by .pch. Unless -Rdir is specified (see below), it is created in the directory of the primary source file.

When the -v option to CC is used, a message such as

   "test.C": creating precompiled header file "test.pch"
is issued if a precompiled header file is created or used.

In automatic mode (i.e., when -Rauto is used) the front end will deem a precompiled header file obsolete and delete it under the following circumstances:

This handles some common cases; other PCH file clean-up must be dealt with by other means (e.g., by the user).

Manual precompiled header processing

The CC command-line option -Rcreate=filename specifies that a precompiled header file of the specified name should be created. The CC command-line option -Ruse=filename specifies that the indicated precompiled header file should be used for this compilation; if it is invalid (i.e., if its prefix does not match the prefix for the current primary source file), a warning will be issued and the PCH file will not be used.

When either of these options is used in conjunction with -Rdir=directory-name, the indicated file name (which may be a path name) is tacked on to the directory name, unless the file name is an absolute path name.

The manual-mode PCH options may not be used in conjunction in automatic mode. In other words, these options are not compatible with -Rauto. Nevertheless, most of the description of automatic PCH processing applies to one or the other of these modes --- header stop points are determined the same way, PCH file applicability is determined the same way, and so forth.

Other ways to control precompiled headers

There are several ways in which the user can control and/or tune how precompiled headers are created and used.

Performance issues

The relative overhead incurred in writing out and reading back in a precompiled header file is quite small for reasonably large header files.

In general, it doesn't cost much to write a precompiled header file out even if it does not end up being used, and if it is used it almost always produces a significant speedup in compilation. The problem is that the precompiled header files can be quite large (from a minimum of about 250K bytes to several megabytes or more), and so one probably doesn't want many of them sitting around.

Thus, despite the faster recompilations, precompiled header processing is not likely to be justified for an arbitrary set of files with nonuniform initial sequences of preprocessing directives. Rather, the greatest benefit occurs when a number of source files can share the same PCH file. The more sharing, the less disk space is consumed. With sharing, the disadvantage of large precompiled header files can be minimized, without giving up the advantage of a significant speedup in compilation times.

Consequently, to take full advantage of header file precompilation, users should expect to reorder the #include sections of their source files and/or to group #include directives within a commonly used header file.

A common idiom is this:

   #include "common_head.h"
   #pragma hdrstop
   #include ...
where common_head.h pulls in, directly and indirectly, the header files used throughout all the source files that make up the program. The #pragma hdrstop is inserted to get better sharing with fewer PCH files. Another idiom, is to partition related header files into groups:
   #include "common_head.h"
   #include "group1.h"
   #pragma hdrstop
   #include ...
If disk space were at a premium, one could decide to make one header file that pulls in all the header files used --- then, a single PCH file could be used in building the whole program.

Different environments and different projects will have different needs, but in general, users should be aware that making the best use of the precompiled header support will require some experimentation and probably some minor changes to source code.

Next topic: How to use library functions
Previous topic: Header Files

© 2005 The SCO Group, Inc. All rights reserved.
SCO OpenServer Release 6.0.0 -- 02 June 2005