Using precompiled headers in C

Precompiled Headers

Beginning with version 5.5, the Sun C compiler has provided a facility for manually precompiling header files. Beginning with version 5.6, this feature was expanded to include automatic creation and use of precompiled headers, making this already helpful feature even more easy to use. Here's some additional information about precompiled headers which should help clarify what this feature really is and show how it can best be utilized. With a bit of experimentation, the benefits of this feature should more than compensate for the time invested in initial setup.

Precompiled header (PCH) files can reduce compilation time by eliminating recompilation of one or more header files for each source file recompiled. A PCH file is, in essence, a snapshot of a compilation at a particular point in time.  With this information, the compiler can place itself back into the same state of compilation as when the PCH file was first created.  In many cases, it is much quicker to do this using a single PCH file than it is to recompile using all the headers from which the PCH file was originally created.

Note that using a precompiled headers isn't always beneficial. There is overhead involved in both creating and using a precompiled header.  To gain significantly by using precompiled headers, there must be something inherent in the included file(s) that when "precompiled" allows compilation to proceed faster. For example, programs typically contain includes of system header files and other user include files that further expand into other includes. These includes often contain such things as type and variable declarations, conditionally compiled code, additional includes, and macro definitions. Some of these include files may even be included multiple times, such that the compiler ends up scanning an entire file only to find that it contains nothing but redundant includes or macro definitions. A precompiled header file can, under these conditions, markedly reduce recompilation time. This is possible because:
  • only one file is opened to read the header file contents ("source") derived from many other include files;
  • types and variables are recognized without the need for recompilation;
  • macros are already expanded.
Note that an underlying assumption behind using precompiled headers is that the normal header files used to create the precompiled header rarely, if ever, are modified.

Sun PCH files are created either manually or automatically. In general,  to benefit from manual PCH, there should be some knowledge of the existing code base and a willingness to analyze it for opportunities to improve the efficacy of PCH. To maximize the benefit of manual PCH, then, the first step is to analyze the source files and make any necessary changes. Here is a list of source file and header file attributes that can affect the potential gain from manual PCH:
  • Look for commonality in header file inclusion. Does it exist already? Can it be used as is to create an effective PCH file?
        For example, given the following source fragments:

        a.c                         b.c                            c.c

        #include "a.h"     #include "a.h"          #include "a.h"
        #include "b.h"     #include "b.h"          #include "b.h"
                 .                #include "c.h"          #include "d.h"
                 .                      .                         #include "c.h"
                 .                      .                                  .
                 .                      .                                  .

        it is clear that include files "a.h" and "b.h" are common to all three
        examples and can be used to create a PCH file. This PCH file can in
        turn be used in subsequent recompilations of any of the above
        three sources to speed up the compile time.
  • Look for commonality that can be achieved by reordering existing includes.
        Given the source files "b.c" and "c.c" above, and the assumption
        that we know that we can safely move the include of "c.h" prior to
        the include of "d.h", the file "c.c" could be edited and the positions
        of the includes of "d.h" and "c.h" reversed.  A PCH file containing
        the contents of "a.h", "b.h", and "c.h" (and any other include files
        included) could then be created and used for any subsequent
        recompilations of "b.c" and "c.c"
  • Remove illegal elements from the viable source prefix, if possible, such as definitions (see the C User's Guide for more examples of what invalidates a viable source prefix).
  • Move pre-processor directives, if possible, such that they won't potentially cause conflicts with other source files.
        For example,


        #include "a.h"
        #define FOO 1
        #include "b.h"

        If the define of FOO is unnecessary prior to the include of "b.h", it
        could be moved past the last include so that there will be no
        possibility that it may clash with the viable source prefix of another
        source file.

Automatic PCH, while simpler to use, isn't necessarily the PCH mode of choice. While it does provide an intuitively easier approach to using precompiled headers, beyond that it still requires a program to have the same basic elements as noted above for manual PCH in order to truly be effective:
  • commonality of header file inclusion, both in number and order, among a large number of source files;
  • relatively large number of includes, either in the source or nested within other includes;
  • numerous declarations and macro definitions;
  • stability of header files involved in the PCH file
If these conditions are not true, then automatic PCH will likely not provide any improvement in compilation time and may, in fact, perform worse than judicious use of manual PCH.  The true benefit of automatic PCH is in its ease of use. If a particular program's sources files are already amenable to using precompiled headers, or have been properly modified to be so, allowing the compiler to take care of the details associated with PCH file creation and use can simplify the overall process.

One last feature of automatic PCH which can prove to be very useful is the variant specified simply as -xpch=autofirst. This tells the compiler to attempt to create a precompiled header automatically using only the contents of the first header file (which can, of course, include an arbitrary number of other header files). This simple form of automatic precompiled headers can, under the right circumstances, provide a dramatic reduction in compile time. The main requirement for "autofirst" to be effective is that the first header file included should be relatively large with respect to the main source file and/or it should include other large header files.


Post a Comment:
  • HTML Syntax: NOT allowed



« June 2016