digitalmars.com                        
Last update Sun Mar 4 11:58:06 2018

Precompiled Headers

If your program uses a large header file or numerous small headers, the compiler spends considerable time compiling the same code over and over again. To save compile time, precompile a header file; the compiler can load a precompiled header faster than it can a text header file. The compiler includes a precompiled header only once in a file, regardless of how many #include statements for it appear.

How the compiler precompiles a header

A precompiled header consists of the header file's global symbol table and any macros defined by the header. A header intended for precompilation should, therefore, contain only declarations and no definitions.

For example, the following declarations are appropriate for use in precompiled headers:

extern int abc;
int foo(int x); 
inline void g(x) { foo(x); } // inline function definition 
#define MACRO(x) asdf(x) 
These will not work:
int def = 3; // a definition
void g(x) { foo(x); } // function definition 

Precompiled header options

These switches to dmc control precompiled headers. Corresponding IDDE options are in the Header Files subpage on the Build page of the IDDE's Project Settings dialog box.
Header Files
Switch Description
-H Use precompiled headers
-HC Do not cache precompiled headers in memory
-HDdirectory Read/write precompiled headers in directory
-HF[filename[.sym]] Write precompiled header to filename.sym
-HI Include header file
-HMaddress Set address for memory mapped files precompiled header files
-HO Include header files only once
-HS Search for include files only in -Ipath directories
-HX Use automatic precompiled headers
-Ipath Set search path for include files
To use a precompiled header: Create a directory specifically for the program that includes its source files and makefile. When compiling, this directory is the current directory, and the compiler automatically writes the precompiled headers there. A program should have its own directory because precompiled headers are highly specialized, and it is unlikely that a precompiled header for one program can work with another.

#include the precompiled header in the source as you normally would. For example, to use a precompiled version of stdio.h in a program, write:

#include <stdio.h> 
main()
{ 
  printf("hello world\n");
} 
The program's makefile must precompile the header file and include the precompiled header in the list of dependencies for all the source files that #include it. For example, this is the makefile for the hello world program:
stdio.sym : stdio.h makefile
	dmc -HF stdio.h 

hello.exe : hello.c stdio.sym
	dmc -H hello 
The first two lines are for the precompiled header. The name of the precompiled header is the same as the text header, except it ends in .sym instead of .h. The dmc -HF command precompiles the header file, creates a .sym file and places it in the current directory. The precompiled header depends not only on the text header file, but also on the program's makefile. This is because changes in the makefile, such as using a different memory model or target CPU, change how the compiler precompiles the header.

The last two lines above are for the program's source file. The executable file is dependent not only on its source file, but also on the precompiled header. The -H option tells the compiler that when it looks for a header file, it should first look in the current directory for .sym files.

Using a project precompiled header

If many source files #include the same files, you might want to create a project precompiled header that #includes several text header files.

For example, if the files in the project all #include stdio.h, string.h and myglobals.h, create a project header file project.h that contains just these lines:

#include <stdio.h>
#include <string.h> 
#include "myglobals.h" 
Precompile project.h with this command:
dmc -HF project.h 
Then compile them with the -H and -HI options:
dmc file1 file2 file3 -HIproject.h -H 

"Automatic" Precompiled Headers (-HX)

Using -HX improves compile times for most programs. Instances where this might not be the case include:

Using a fast disk with a precompiled header

To make a precompiled header file even faster, place it on the fastest disk drive in your system. To let the compiler know where the precompiled file is, make some changes in the makefile. First, precompile the header file with -HF to specify where to place it. Then, use -HD to set the path to read the precompiled header.

For example, if the fastest disk is drive e, the makefile for the hello world program would be:

TMP=e: 

$(TMP)stdio.sym : stdio.h makefile
	dmc -HF$(TMP) stdio stdio.h 

hello.exe : hello.c $(TMP)stdio.sym
	dmc -HD$(TMP) hello 
or, with automatic precompiled headers:
TMP=e: 

hello.exe : hello.c
	dmc -HD$(TMP) -HX hello 

Tips For Precompiled Headers

To make the best use of precompiled headers, follow these rules:
  1. Header files should contain complete definitions, i.e. starting a declaration in one file and finishing it in another should be avoided. Every header file should be self-contained.
  2. Design headers so they only need to be #include'd once. Then, wrap the header in:
    #ifndef _HEADER_H
    #define _HEADER_H 1
        ... declarations ...
    #endif // _HEADER_H
    
    so that if it is #include'd multiple times, it is parsed only once. In addition, add:
    #pragma once
    
    to it so the compiler doesn't need to rescan it.
  3. Design headers so they can be #include'd in any order. The best way to do this is to have each header #include the ones it depends on. By following rule (2), this will not have a compile time penalty.
  4. Avoid defining data in the headers.
  5. Avoid putting executable code, other than inline functions, in headers.
  6. Avoid #undef'ing macros and redefining them to something else.
  7. If the struct packing is set to something other than the default, set it back to the default before the end of the file.
  8. Do not write extern "C" constructs that start in one file and end in another.
  9. If the header file has changed since the last time you precompiled it, the compiler uses the older precompiled header file. Updating the precompiled header file should be done by the makefile.
  10. #include directives for precompiled header file(s) should be the first line(s) in a source file other than comments. If other code precedes the #include directive for a precompiled header, ensure that the code does not affect compilation of the header file.
Home | Runtime Library | IDDE Reference | STL | Search | Download | Forums