[cmake-developers] Support for Precompiled Headers

Daniel Pfeifer daniel at pfeifer-mail.de
Thu Jun 14 04:36:30 EDT 2012


Hi,

In a private mailing with Dave Abrahams and Brad King I wrote a
proposal of how I imagine PCH support should be implemented. Brad
asked me to send it to this list for further discussion.
Please note that even though I use present tense in the proposal,
nothing descibed below is implemented yet.
We have a similar implementation for PCH [1], but the interface
differs to this proposal.

[1] https://github.com/ryppl/ryppl/blob/develop/cmake/Modules/RypplPrecompileHeader.cmake

cheers, Daniel



CMakeLists.txt changes
----------------------
There are new target properties PRECOMPILE_HEADER and
PRECOMPILE_HEADER_<config>. These properties may be set to a list of
header files:

set_property(TARGET target APPEND PROPERTY PRECOMPILE_HEADER
 <boost/spirit/karma.hpp>
 "my/precompiled/header.h"
 )


changes to source files
-----------------------
None. All source files should be written as if there was no PCH
support. That means that each file should include all the headers it
requires. Nothing more, nothing less.

That especially means that source files should *NOT* include an
"all.h", "precompile.h", or "stdafx.h" file. Nothing breaks if they
do, but it may impact compile times if precompiled headers are not
supported.


file(s) to precompile
---------------------
Special header files that contain all the system headers may be
created and added to the PRECOMPILE_HEADER property. However, the
system headers may also be added directly to PRECOMPILE_HEADER.

If custom files are created, it is important to note that a special
PCH_SUPPORTED guard is *NOT* required.


What is done behind the scenes
------------------------------
CMake creates the actual header file that is going to be precompiled
during the config step inside the current binary directory. The
complete filename encodes the target name and the configuration (eg.
"${CMAKE_CURRENT_BINARY_DIR}/${target}_${config}_pch.hpp") and
contains one #include directive for each element in the
PRECOMPILE_HEADER/PRECOMPILE_HEADER_<config> list. If the element is
wrapped in angle brackets, it is included unmodified, otherwise the
*absolute path* is used in double quotes. The generated header file
for the above example may look like this:

/* generated by CMake 2.8.x */
#include <boost/spirit/karma.hpp>
#include "/home/daniel/workspace/foo/my/precompiled/header.h"


This header file is compiled before all object files of the target; ie
the object files depend on the compiled header.


MSVC specific
-------------
MSVC requires a source file to compile the header. This source file is
generated by CMake alongside the header file and may be called
<target>_pch.cpp, for example. It contains just one line: an #include
directive that includes the configured header file.

The precompiled header (pch_binary) is created by compiling the source
file (pch_source) with "/Yc\"${pch_header}\" /Fp\"${pch_binary}\"".

For the MSVC IDE, pch_binary might be "$(IntDir)/${target}.pch".

All other source files are compiled with "/Yu\"${pch_header}\"
/FI\"${pch_header}\" /Fp\"${pch_binary}\"".

/Yc = create pch
/Yu = use pch
/FI = force include
/Fp = name pch binary


GCC specific
------------
In GCC the pch_binary is created by compiling the header file directly
(no extra source file is required). The pch_binary must be
"${pch_header}.pch", there is no way to change that. Here, it pays off
again that we generate the actual pch_header in the binary directory.

The compile flags to compile the header are "-x c++-header" and the
output file must be set with "-o ${pch_binary}"

All the other source files are compiled with "-include ${pch_header}"
(force include), it may also be a good idea to pass "-Winvalid-pch".



More information about the cmake-developers mailing list