792 lines
37 KiB
Markdown
792 lines
37 KiB
Markdown
|
cotire manual
|
||
|
=============
|
||
|
|
||
|
Cotire (compile time reducer) is a CMake module that speeds up the build process of CMake based
|
||
|
build systems by fully automating techniques as [precompiled header][pch] usage and
|
||
|
[single compilation unit][scu] builds for C and C++.
|
||
|
|
||
|
motivation
|
||
|
----------
|
||
|
|
||
|
Cotire was born out of a dissatisfaction with the existing CMake solutions for adding
|
||
|
[precompiled header][1260] support and unity build support to CMake based build systems.
|
||
|
The design of cotire tries to adhere to the following principles:
|
||
|
|
||
|
#### as automatic as possible
|
||
|
|
||
|
[Precompiled header][pch] and [unity builds][scu] are good ideas in principle, but in reality
|
||
|
they do not work if the burden of maintaining the required additional source files (a
|
||
|
[prefix header][pfh] and a unity source file) is put on the developer. A modern build system
|
||
|
like CMake provides enough context information to have the build system generate and update
|
||
|
these files automatically.
|
||
|
|
||
|
#### non-intrusive
|
||
|
|
||
|
The configuration of precompiled headers usage and single computation unit builds belongs to the
|
||
|
build system and not in the source code. Nobody wants to litter one's source files with `hdrstop`
|
||
|
pragmas or be forced to add an include directive to every file. Source code should build properly
|
||
|
when a precompiled header isn't used and should build faster when a precompiled header is used.
|
||
|
|
||
|
#### minimal interface
|
||
|
|
||
|
Maintaining a build system over time is enough work and the CMake language may often get in your
|
||
|
way. Thus the solution should only add few public CMake functions. It should be easy to integrate
|
||
|
it into an existing CMake based build system and it should be just as easy to remove it again.
|
||
|
|
||
|
#### lazy file creation
|
||
|
|
||
|
The additional source files needed for precompiled header support and unity build support should
|
||
|
only be created when they are required for the compilation of a target. Thus the solution should
|
||
|
not create these files upon configuring the project, but should set up custom build commands for
|
||
|
the creation of these files that only kick in when the files are required to exist by the build
|
||
|
process.
|
||
|
|
||
|
#### cross-platform
|
||
|
|
||
|
C/C++ Compilers and IDEs on different platforms vary widely in how the implement precompiled
|
||
|
header support. The solution should hide these implementation details and present a uniform
|
||
|
interface to the developer on all supported platforms.
|
||
|
|
||
|
cotire basic usage
|
||
|
------------------
|
||
|
|
||
|
Cotire consists of a single CMake module file, which can be easily added to an existing CMake
|
||
|
project.
|
||
|
|
||
|
The file `CMake/cotire.cmake` needs to be copied to the module directory of a CMake project. In the
|
||
|
top-level `CMakeList.txt` file, the module directory needs to be added to the CMake module search
|
||
|
path:
|
||
|
|
||
|
set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake")
|
||
|
|
||
|
To use cotire in a CMake project, one adds the following include directive to the beginning of the
|
||
|
top-level `CMakeList.txt`:
|
||
|
|
||
|
include(cotire)
|
||
|
|
||
|
To speed the build process of a CMake library or executable target, the `cotire` function is
|
||
|
applied to a CMake target. From the example project that ships with cotire:
|
||
|
|
||
|
add_executable(example main.cpp example.cpp log.cpp log.h example.h)
|
||
|
...
|
||
|
cotire(example)
|
||
|
|
||
|
Cotire looks at the properties of the target provided by CMake (e.g., target type, source files,
|
||
|
compile flags, preprocessor defines, include directories, ...) and modifies the target's build
|
||
|
process in the following way:
|
||
|
|
||
|
1. cotire adds a custom build rule to produce a unity source file from the target's sources.
|
||
|
2. cotire adds a custom build rule to produce a prefix header file by tracking the header files
|
||
|
included by the target's sources.
|
||
|
3. cotire adds a custom build rule to produce a precompiled header from the prefix header.
|
||
|
4. cotire modifies the target's compile flags to make use of the generated precompiled header.
|
||
|
5. cotire adds a couple of new targets.
|
||
|
|
||
|
For makefile based build systems, running `make help` in the terminal reveals the new targets:
|
||
|
|
||
|
$ make help
|
||
|
...
|
||
|
... all_pch
|
||
|
... all_unity
|
||
|
... clean_cotire
|
||
|
... example
|
||
|
... example_pch
|
||
|
... example_unity
|
||
|
|
||
|
The `example_pch` target triggers the compilation of the precompiled header and as a side effect
|
||
|
the generation of the unity source and the prefix header. The target `clean_cotire` cleans up all
|
||
|
files generated by cotire. The `example_unity` target produces the same output as the original
|
||
|
`example` target, but does so by performing a unity build. The `all_pch` and `all_unity` serve as
|
||
|
pool targets for all cotired project targets.
|
||
|
|
||
|
By default, the `example_unity` target inherits all build settings from the original target
|
||
|
`example` including linked libraries and target dependencies.
|
||
|
|
||
|
cotire generated files
|
||
|
----------------------
|
||
|
|
||
|
For a target that has been cotired, three files will be generated as part of the build process:
|
||
|
|
||
|
### the unity source
|
||
|
|
||
|
The unity source file is generated from the target by querying the target's `SOURCES` property.
|
||
|
It consists of preprocessor include directives for each of the target source files. The files
|
||
|
are included in the same order that is used in the CMake `add_executable` or `add_library` call.
|
||
|
Header files are omitted.
|
||
|
|
||
|
This is a unity source generated for the example project under OS X:
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
#include "/Users/sakra/Documents/cotire/src/main.cpp"
|
||
|
#include "/Users/sakra/Documents/cotire/src/example.cpp"
|
||
|
#include "/Users/sakra/Documents/cotire/src/log.cpp"
|
||
|
#endif
|
||
|
|
||
|
The unity source file uses absolute paths to include the target's source file. The file is not
|
||
|
intended to be portable across different build folders or machines. It is an intermediate file
|
||
|
tied to the build folder that is automatically recreated by the build system if it is missing.
|
||
|
|
||
|
For multi-core machines cotire can be configured to generate multiple unity file segments that
|
||
|
can be built in parallel by the chosen CMake generator (see below).
|
||
|
|
||
|
### the prefix header
|
||
|
|
||
|
The prefix header is produced from the unity source file by running the unity file through the
|
||
|
preprocessor and keeping track of each header file used (this is done by using option `-H` with
|
||
|
GCC / Clang and `/showIncludes` with Visual Studio C++). The path of each used header file is
|
||
|
compared against an exclude directory list and an include directory list to decide if the header
|
||
|
file should be added to the prefix header.
|
||
|
|
||
|
By default the include directory list is empty and the exclude directory list is initialized to
|
||
|
`"${CMAKE_SOURCE_DIR};${CMAKE_BINARY_DIR}"`. This default setting guarantees that project headers
|
||
|
which are likely to be changed frequently are not added to the prefix header.
|
||
|
|
||
|
Upon generation of the prefix header cotire makes sure that target compile options, include path
|
||
|
settings and preprocessor defines (e.g., `NDEBUG`) that affect the outcome of the preprocessor
|
||
|
are correctly set up.
|
||
|
|
||
|
Generating the prefix header from the unity source is much faster than running each individual
|
||
|
target source file through the preprocessor, because the coalesced unity source will make the
|
||
|
preprocessor process most header files only once.
|
||
|
|
||
|
This is a prefix header produced for the example project with Visual Studio 2013 under Windows 7:
|
||
|
|
||
|
#pragma warning(push, 0)
|
||
|
#ifdef __cplusplus
|
||
|
#include "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\string"
|
||
|
#include "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\algorithm"
|
||
|
#include "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\iostream"
|
||
|
#endif
|
||
|
#pragma warning(pop)
|
||
|
|
||
|
Generating the prefix file under Ubuntu 12.04 with GCC 4.6 yields the following result:
|
||
|
|
||
|
#pragma GCC system_header
|
||
|
#ifdef __cplusplus
|
||
|
#include "/usr/include/c++/4.6/string"
|
||
|
#include "/usr/include/c++/4.6/algorithm"
|
||
|
#include "/usr/include/c++/4.6/iterator"
|
||
|
#include "/usr/include/c++/4.6/iostream"
|
||
|
#endif
|
||
|
|
||
|
Using Xcode 5.1 under OS X 10.9, this is the resulting prefix header:
|
||
|
|
||
|
#pragma clang system_header
|
||
|
#ifdef __cplusplus
|
||
|
#include "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/string"
|
||
|
#include "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/iostream"
|
||
|
#endif
|
||
|
|
||
|
Besides include directives, cotire also adds compiler specific pragmas to the generated prefix
|
||
|
header to suppress compiler warnings upon inclusion.
|
||
|
|
||
|
Cotire attempts to produce a minimal list of header files by omitting header files indirectly
|
||
|
included by a header that is already part of the prefix header. Header files with nonstandard
|
||
|
file extensions like `.inl`, `.inc` of `.ipp` are omitted by default.
|
||
|
|
||
|
The generated prefix file includes the selected header files by their absolute paths. This speeds
|
||
|
up the precompiling of the prefix header because the compiler does not have to search for header
|
||
|
files in include directories again.
|
||
|
|
||
|
The prefix header is tailored to the CMake target that it is generated for. It is tied to the
|
||
|
compiler environment of the local machine and is not portable across different compilers or
|
||
|
machines. It is automatically recreated by the build system if it goes missing.
|
||
|
|
||
|
The generated prefix header can be applied to a different target added in the same source directory
|
||
|
(see below).
|
||
|
|
||
|
Optionally, cotire will also create a prefix source file that consists of a single include directive
|
||
|
for the prefix header. This file is needed for pre-compiling the prefix header with Clang or GCC
|
||
|
to make both compilers handle the `system_header` pragma correctly.
|
||
|
|
||
|
### the precompiled header
|
||
|
|
||
|
The precompiled header is produced from the generated prefix header by using the proprietary
|
||
|
precompiling mechanism depending on the compiler used. For GCC and Clang cotire sets up a custom
|
||
|
build rule and generates the precompiled header as described in the documentation for
|
||
|
[GCC][gcc_pch] and [Clang][clang_pch]. Cotire then modifies the `COMPILE_FLAGS` property of the
|
||
|
target to force the inclusion of the prefix header.
|
||
|
|
||
|
Visual Studio C++ and Intel C++ use a [different approach][msvc_pch] to pre-compiling. Both
|
||
|
compilers require a host source file to generate the precompiled header as a side effect of
|
||
|
producing an object file. Cotire modifies the `COMPILE_FLAGS` of the first target source file to
|
||
|
[generate][msvc_pch_create] the precompiled header and then modifies the `COMPILE_FLAGS` of the
|
||
|
remaining target source files to [include][msvc_pch_use] the generated precompiled header.
|
||
|
|
||
|
For Xcode projects generated with CMake, cotire completely hands off the pre-compilation of
|
||
|
the prefix header and the inclusion of the precompiled header to the IDE. Cotire attaches a
|
||
|
pre-build action to the target which generates the unity source file and the prefix header.
|
||
|
Cotire then modifies Xcode attributes of the generated Xcode project to have Xcode precompile the
|
||
|
the generated prefix header with the Xcode build steps `ProcessPCH` for C sources and
|
||
|
`ProcessPCH++` for C++ sources.
|
||
|
|
||
|
For precompiled headers creation flags must match use flags exactly. Cotire uses the same flags,
|
||
|
include directories and preprocessor defines that are used for the compilation of source files
|
||
|
for the generation of the precompiled header. Thus the resulting precompiled header binary is only
|
||
|
usable for the target and cannot be re-used for a different CMake target.
|
||
|
|
||
|
cotire advanced usage
|
||
|
---------------------
|
||
|
|
||
|
### applying cotire to multiple targets at the same time
|
||
|
|
||
|
The `cotire` function can be applied to multiple targets added in the same source directory in one
|
||
|
call:
|
||
|
|
||
|
add_library(libA STATIC ...)
|
||
|
add_library(libB SHARED ...)
|
||
|
add_executable(example ...)
|
||
|
...
|
||
|
cotire(example libA libB)
|
||
|
|
||
|
### mixed-language targets
|
||
|
|
||
|
Cotire is able to speed up the build process of mixed language targets, consisting of both C and
|
||
|
C++ sources. It generates a separate set of unity source files, prefix headers and precompiled
|
||
|
headers for both languages and modifies the `COMPILE_FLAGS` of each target source file to include
|
||
|
the correct precompiled header depending on the compilation language of the source file.
|
||
|
|
||
|
### obtaining the names of the generated files and targets
|
||
|
|
||
|
For a cotired target the target properties `COTIRE_<LANG>_UNITY_SOURCE`,
|
||
|
`COTIRE_<LANG>_PREFIX_HEADER`, `COTIRE_<LANG>_PRECOMPILED_HEADER` will be set to the paths of the
|
||
|
generated files (`<LANG>` can be set to `CXX` or `C`). The target property
|
||
|
`COTIRE_UNITY_TARGET_NAME` will be set to the name of the generated unity target:
|
||
|
|
||
|
cotire(example)
|
||
|
...
|
||
|
get_target_property(_unitySource example COTIRE_CXX_UNITY_SOURCE)
|
||
|
get_target_property(_prefixHeader example COTIRE_CXX_PREFIX_HEADER)
|
||
|
get_target_property(_precompiledHeader example COTIRE_CXX_PRECOMPILED_HEADER)
|
||
|
get_target_property(_unityTargetName example COTIRE_UNITY_TARGET_NAME)
|
||
|
|
||
|
If a source file's `COMPILE_FLAGS` are modified by cotire, it sets the source file property
|
||
|
`COTIRE_TARGET` to the name of the target, that the source file's build command has been
|
||
|
altered for:
|
||
|
|
||
|
cotire(example)
|
||
|
...
|
||
|
get_source_file_property(_cotireTargetName "example.cpp" COTIRE_TARGET)
|
||
|
if (_cotireTargetName)
|
||
|
message(STATUS "example.cpp has been cotired for target ${_cotireTargetName}")
|
||
|
endif()
|
||
|
|
||
|
### changing the name of the generated unity build target
|
||
|
|
||
|
By default cotire uses the name of the the original target with the suffix `_unity` appended
|
||
|
for the name of the generated unity build target. To create the unity build target under a
|
||
|
different name, set the `COTIRE_UNITY_TARGET_NAME` property:
|
||
|
|
||
|
add_executable(example_template main.cpp example.cpp log.cpp log.h example.h)
|
||
|
set_target_properties(example_template PROPERTIES COTIRE_UNITY_TARGET_NAME "example")
|
||
|
...
|
||
|
cotire(example_template)
|
||
|
|
||
|
Invoking the `example` target will then run the unity build.
|
||
|
|
||
|
### restricting cotire to certain build configurations
|
||
|
|
||
|
To restrict the cotire related modifications to the build process to certain build configurations,
|
||
|
the `CONFIGURATIONS` parameter can be added to the `cotire` call.
|
||
|
|
||
|
cotire(example CONFIGURATIONS Release MinSizeRel)
|
||
|
|
||
|
For single build type builds the selected configuration will be checked at configure time, for
|
||
|
multi-configuration builds the check will be done at build time.
|
||
|
|
||
|
It is recommended to have at least one build configuration that does not make use of cotire to
|
||
|
ensure that the project builds properly without cotire.
|
||
|
|
||
|
### disabling precompiled headers and unity builds
|
||
|
|
||
|
If the target's build process should not be modified to make use of the generated precompiled
|
||
|
header, the target property `COTIRE_ENABLE_PRECOMPILED_HEADER` can be set to `FALSE`:
|
||
|
|
||
|
set_target_properties(example PROPERTIES COTIRE_ENABLE_PRECOMPILED_HEADER FALSE)
|
||
|
cotire(example)
|
||
|
|
||
|
If a unity build target should not be added by cotire, the target property
|
||
|
`COTIRE_ADD_UNITY_BUILD` can be set to `FALSE`:
|
||
|
|
||
|
set_target_properties(example PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
|
||
|
cotire(example)
|
||
|
|
||
|
The property `COTIRE_ADD_UNITY_BUILD` only affects the addition of the unity build target. Custom
|
||
|
build rules for the generation of the unity source file will always be set up, because the
|
||
|
unity source file is needed for the generation of the prefix header.
|
||
|
|
||
|
Both properties default to `TRUE`. If both are set to `FALSE`, cotire will only set up custom build
|
||
|
rules for the generation of the unity source and the prefix header.
|
||
|
|
||
|
The properties `COTIRE_ENABLE_PRECOMPILED_HEADER` and `COTIRE_ADD_UNITY_BUILD` can also be set on
|
||
|
directories. A target inherits the property value from its enclosing directory.
|
||
|
|
||
|
### disabling precompiled headers for small targets
|
||
|
|
||
|
The cache variable `COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES` can be set to the minimum number of
|
||
|
source files required to enable the use of a precompiled header. It defaults to 2. To override the
|
||
|
default, run `cmake` with the following options:
|
||
|
|
||
|
$ cmake -D COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES=5 <path-to-source>
|
||
|
|
||
|
### using a manually maintained prefix header instead of the automatically generated one
|
||
|
|
||
|
cotire can be configured to use an existing manually maintained prefix header (e.g., Visual Studio
|
||
|
projects often use a prefix header named `stdafx.h`) instead of the automatically generated one.
|
||
|
Set the target property `COTIRE_CXX_PREFIX_HEADER_INIT` to the path of the existing prefix header
|
||
|
file. The path is interpreted relative to the target source directory:
|
||
|
|
||
|
set_target_properties(example PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "stdafx.h")
|
||
|
cotire(example)
|
||
|
|
||
|
If the prefix header `stdafx.h` needs an accompanying source file (e.g., `stdafx.cpp`) in order
|
||
|
to be precompiled properly, that source file needs to be the first one on the list of source
|
||
|
files in the target's `add_executable` or `add_library` call.
|
||
|
|
||
|
The property `COTIRE_CXX_PREFIX_HEADER_INIT` can also be set to a list of header files which will
|
||
|
then make up the contents of the generated prefix header.
|
||
|
|
||
|
A manually maintained prefix header will always be applied to the corresponding target,
|
||
|
even if the target contains too few sources to enable the use of a precompiled header.
|
||
|
|
||
|
### using a generated prefix header for multiple targets
|
||
|
|
||
|
A prefix header that is generated for a cotired target can be applied to a different target
|
||
|
added in the same source directory:
|
||
|
|
||
|
cotire(example)
|
||
|
get_target_property(_prefixHeader example COTIRE_CXX_PREFIX_HEADER)
|
||
|
...
|
||
|
set_target_properties(other_target PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${_prefixHeader}")
|
||
|
cotire(other_target)
|
||
|
|
||
|
The compilation of either target will trigger the generation of the prefix header.
|
||
|
|
||
|
### configuring the generation of the prefix header
|
||
|
|
||
|
There are multiple target properties which affect the generation of the prefix header:
|
||
|
|
||
|
* `COTIRE_PREFIX_HEADER_IGNORE_PATH` can be set to a semicolon separated list of directories. If a
|
||
|
header file is found in one of these directories or sub-directories, it will be excluded from the
|
||
|
generated prefix header.
|
||
|
|
||
|
* `COTIRE_PREFIX_HEADER_INCLUDE_PATH` can be set to a semicolon separated list of directories. If
|
||
|
a header file is included from one of these directories or sub-directories, it will be included
|
||
|
in the generated prefix header.
|
||
|
|
||
|
If a header file is matched by both `COTIRE_PREFIX_HEADER_IGNORE_PATH` and
|
||
|
`COTIRE_PREFIX_HEADER_INCLUDE_PATH`, the option which yields the closer relative path match wins.
|
||
|
For example, if third-party libraries are part of the source tree in a directory called `Libs`,
|
||
|
the following setting will make cotire select header files from the third-party directory, but
|
||
|
ignore other project related headers in `CMAKE_SOURCE_DIR`:
|
||
|
|
||
|
set_target_properties(example PROPERTIES
|
||
|
COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR}"
|
||
|
COTIRE_PREFIX_HEADER_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/Libs")
|
||
|
|
||
|
The properties `COTIRE_PREFIX_HEADER_IGNORE_PATH` and `COTIRE_PREFIX_HEADER_INCLUDE_PATH` can
|
||
|
also be set on directories.
|
||
|
|
||
|
The following cache variables also affect the selection of prefix headers:
|
||
|
|
||
|
* Directory paths in `COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH` will be added to the list of
|
||
|
ignored directories when the prefix header file is created.
|
||
|
|
||
|
* `COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS` can be used to ignore header files by file
|
||
|
extension. It defaults to the CMake list `inc;inl;ipp`.
|
||
|
|
||
|
During development, changes to the project source files may affect the list of header files that
|
||
|
should be selected for inclusion in the prefix header (e.g., a standard include may be added or
|
||
|
removed from a target source file). Cotire does not automatically recreate the prefix header,
|
||
|
when a target source file is changed, because this would always trigger a re-compilation of the
|
||
|
precompiled header and would result in a rebuild of the whole target. To make the prefix header
|
||
|
creation dependent on changes to certain target source files, the source file property
|
||
|
`COTIRE_DEPENDENCY` can be set to `TRUE` for those files:
|
||
|
|
||
|
set_property (SOURCE "example.cpp" PROPERTY COTIRE_DEPENDENCY "TRUE")
|
||
|
|
||
|
### fixing linkage issues
|
||
|
|
||
|
When a C++ program uses `extern "C"` on a system header file, cotire will not be able to detect
|
||
|
that the include file needs C linkage and will include the file with C++ linkage in the generated
|
||
|
prefix header instead. For example, the C interface to BLAS `cblas.h` usually has to be included
|
||
|
as `extern "C"` in a C++ program:
|
||
|
|
||
|
extern "C" {
|
||
|
#include <cblas.h>
|
||
|
}
|
||
|
|
||
|
The presence of `extern "C"` includes will prevent cotired targets from being linked successfully
|
||
|
because of unresolved function references using the wrong linkage. To work around the problem,
|
||
|
the property `COTIRE_PREFIX_HEADER_IGNORE_PATH` can also include the full path of header files
|
||
|
besides directories. Here is an example:
|
||
|
|
||
|
set_property(DIRECTORY
|
||
|
PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH
|
||
|
"${ATLAS_INCLUDE_DIR}/cblas.h"
|
||
|
"${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}")
|
||
|
|
||
|
That way `cblas.h` will not be included in the generated prefix header and will not cause problems
|
||
|
upon linking.
|
||
|
|
||
|
### using a manually maintained unity source instead of the automatically generated one
|
||
|
|
||
|
Cotire can be configured to use an existing manually maintained unity source file instead of the
|
||
|
automatically generated one. Set the target property `COTIRE_CXX_UNITY_SOURCE_INIT` to the path
|
||
|
of the existing unity source file. Its path is interpreted relative to the target source directory:
|
||
|
|
||
|
set_target_properties(example PROPERTIES COTIRE_CXX_UNITY_SOURCE_INIT "example-all.cpp")
|
||
|
cotire(example)
|
||
|
|
||
|
The property can also be set to a list of source files which will then make up the contents of
|
||
|
the generated unity source file.
|
||
|
|
||
|
### configuring the generation of the unity source
|
||
|
|
||
|
By default cotire adds all target source files to the generated unity source. In most cases a
|
||
|
unity build will not work out of the box, because unity builds [break][EoUB] the use of some C
|
||
|
and C++ language features. Unity build problems can be tackled in the following way:
|
||
|
|
||
|
* Change the order of the source files in the `add_executable` or `add_library` calls.
|
||
|
Problematic source files should be moved towards the end.
|
||
|
|
||
|
* Set the source file property `COTIRE_EXCLUDED` on problematic source files. The source file
|
||
|
will not be included in the unity source file and will be compiled separately when the unity build
|
||
|
is performed.
|
||
|
|
||
|
* `COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS` can be used to exclude source files by file extension
|
||
|
from inclusion in the generated unity source. It defaults to the CMake list `m;mm`.
|
||
|
|
||
|
* If the unity source file is too large and the compilation process runs into a compiler limit,
|
||
|
the target property `COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES` can be set. If the target
|
||
|
contains more than that number of source files, cotire will create multiple unity source files
|
||
|
for it. Each unity source file is compiled separately when the unity build is performed.
|
||
|
The property is initialized by value of the cache variable
|
||
|
`COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES`.
|
||
|
|
||
|
* Another way to break up a large unity source file is to set the source file property
|
||
|
`COTIRE_START_NEW_UNITY_SOURCE` to `TRUE` on selected target source files. If cotire encounters
|
||
|
this property, it will complete the current unity file and start a new one. The new unity source
|
||
|
file will include the source file as the first one. This property essentially works as a separator
|
||
|
for unity source files.
|
||
|
|
||
|
### optimizing the build process for multiple processor cores
|
||
|
|
||
|
To make use of all the machine's CPU cores for the unity compilation of a target, the target
|
||
|
property `COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES` can be set to the string `-j`. Cotire
|
||
|
will then create as many unity file segments as there are CPU cores on the machine. Because
|
||
|
the unity file segments do not depend on each other, a multi-core aware build process can compile
|
||
|
the file segments in parallel.
|
||
|
|
||
|
To explicitly specify the number of cores, append the number after `-j`, e.g. `-j 4` or `-j4`.
|
||
|
|
||
|
For CMake generators that are multi-core aware by default (i.e., Visual Studio, JOM, Ninja), cotire
|
||
|
will automatically initialize the property to `-j`. For makefile based generators, this has to be
|
||
|
done explicitly by setting the cache variable `COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES`, i.e.:
|
||
|
|
||
|
$ cmake -D COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES=-j4 <path-to-source>
|
||
|
$ make -j 4
|
||
|
|
||
|
### fixing macro definition clashes
|
||
|
|
||
|
Many unity build problems stem from macro definitions leaking into other target source files,
|
||
|
where they may conflict with other definitions of the same name. Cotire adds the properties
|
||
|
`COTIRE_UNITY_SOURCE_PRE_UNDEFS` and `COTIRE_UNITY_SOURCE_POST_UNDEFS` to fix macro definition
|
||
|
clashes.
|
||
|
|
||
|
As an example, if these properties are set on a source file of the example project:
|
||
|
|
||
|
set_source_files_properties (example.cpp PROPERTIES
|
||
|
COTIRE_UNITY_SOURCE_PRE_UNDEFS "max;min"
|
||
|
COTIRE_UNITY_SOURCE_POST_UNDEFS "DEBUG_TYPE")
|
||
|
|
||
|
This will make cotire add undefs to the generated unity source file.
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
#include "/Users/sakra/Documents/cotire/src/main.cpp"
|
||
|
#undef min
|
||
|
#undef max
|
||
|
#include "/Users/sakra/Documents/cotire/src/example.cpp"
|
||
|
#undef DEBUG_TYPE
|
||
|
#include "/Users/sakra/Documents/cotire/src/log.cpp"
|
||
|
#endif
|
||
|
|
||
|
The properties `COTIRE_UNITY_SOURCE_PRE_UNDEFS` and `COTIRE_UNITY_SOURCE_POST_UNDEFS` can also be
|
||
|
set on targets. Cotire will add `#undef` directives for each source file in the unity source then.
|
||
|
|
||
|
### enabling verbose builds
|
||
|
|
||
|
The cache variable `COTIRE_VERBOSE` can be set to `TRUE` to see all compile commands used when
|
||
|
generating the cotire related files. Cotire will also print the contents of the generated unity
|
||
|
source and the prefix header for verbose builds. `COTIRE_VERBOSE` defaults to `FALSE`.
|
||
|
When using a Makefile generator `COTIRE_VERBOSE` defaults to the value of the makefile variable
|
||
|
`VERBOSE` (i.e., `make VERBOSE=1`).
|
||
|
|
||
|
### conditionally loading cotire
|
||
|
|
||
|
To make a `CMakeLists.txt` robust against a missing `cotire.cmake` module, the following strategy
|
||
|
can be applied to using cotire:
|
||
|
|
||
|
include(cotire OPTIONAL)
|
||
|
...
|
||
|
add_executable(example main.cpp example.cpp log.cpp log.h example.h)
|
||
|
...
|
||
|
if (COMMAND cotire)
|
||
|
cotire(example)
|
||
|
endif()
|
||
|
|
||
|
The `include(cotire OPTIONAL)` will prevent CMake from raising an error if cotire cannot be
|
||
|
found. The actual calls to cotire need to be guarded by `if (COMMAND cotire)` blocks.
|
||
|
|
||
|
### using cotire with compiler wrappers
|
||
|
|
||
|
Cotire is compatible with CMake compiler wrappers. For example, the use of [ccache][ccch] may be
|
||
|
enabled in the following way upon configuring the project:
|
||
|
|
||
|
$ export CC="/usr/local/bin/ccache /usr/bin/gcc"
|
||
|
$ export CXX="/usr/local/bin/ccache /usr/bin/g++"
|
||
|
$ export CCACHE_SLOPPINESS=pch_defines,time_macros
|
||
|
$ cmake ..
|
||
|
|
||
|
Alternatively, for CMake 3.4 or later compiler wrappers can be enabled by pointing the CMake
|
||
|
variable `CMAKE_CXX_COMPILER_LAUNCHER` to the compiler wrapper executable upon configuring:
|
||
|
|
||
|
$ cmake -D CMAKE_CXX_COMPILER_LAUNCHER=/usr/local/bin/ccache <path-to-source>
|
||
|
|
||
|
Note that with ccache in order for precompiled headers to work properly, it is necessary to set
|
||
|
the environment variable `CCACHE_SLOPPINESS` to `pch_defines,time_macros`. Otherwise the build
|
||
|
process may abort with the following error message:
|
||
|
|
||
|
fatal error: file 'example_CXX_prefix.hxx' has been modified since the precompiled header
|
||
|
'example_CXX_prefix.hxx.gch' was built
|
||
|
|
||
|
Also see the [ccache manual][ccch_pch].
|
||
|
|
||
|
### applying cotire to object library targets
|
||
|
|
||
|
CMake 2.8.8 introduced a new type of library target called [object library][objlib]. An object
|
||
|
library is a convenience target that compiles multiple source files but does not create a linked
|
||
|
target library for them, e.g.:
|
||
|
|
||
|
add_library(myLib OBJECT lib1.cpp lib2.cpp lib3.cpp)
|
||
|
add_executable(exeA $<TARGET_OBJECTS:myLib> mainA.cpp)
|
||
|
add_executable(exeB $<TARGET_OBJECTS:myLib> mainB.cpp)
|
||
|
|
||
|
The `cotire` function can be applied to an object library target in a familiar fashion:
|
||
|
|
||
|
add_library(myLib OBJECT lib1.cpp lib2.cpp lib3.cpp)
|
||
|
cotire(myLib)
|
||
|
# use unity object library for executables
|
||
|
add_executable(exeA $<TARGET_OBJECTS:myLib_unity> mainA.cpp)
|
||
|
add_executable(exeB $<TARGET_OBJECTS:myLib_unity> mainB.cpp)
|
||
|
|
||
|
Because object library targets do not support `PRE_BUILD` actions, precompiled header usage cannot
|
||
|
be enabled for them for Xcode projects generated with CMake. Unity builds work as expected, though.
|
||
|
|
||
|
### automatically setting up linked libraries in the unity target
|
||
|
|
||
|
The setting of the target property `COTIRE_UNITY_LINK_LIBRARIES_INIT` controls the linking
|
||
|
strategy for the generated unit target.
|
||
|
|
||
|
If this property is empty or set to `NONE`, the generated unity target's link libraries have to be
|
||
|
set up manually with subsequent `target_link_libraries` calls:
|
||
|
|
||
|
set_target_properties(example PROPERTIES COTIRE_UNITY_LINK_LIBRARIES_INIT "NONE")
|
||
|
...
|
||
|
cotire(example)
|
||
|
target_link_libraries(MyExecutable_unity ${MyExecutableLibraries})
|
||
|
|
||
|
If this property is set to `COPY`, the unity target's link libraries will be copied from the
|
||
|
original target.
|
||
|
|
||
|
If this property is set to `COPY_UNITY`, the unity target's link libraries will be copied from the
|
||
|
original target but instead of copying a linked target verbatim, the target's corresponding unity
|
||
|
target will be preferred, provided one exists. This also applies to object libraries, which have
|
||
|
been added to the original target with a `TARGET_OBJECTS` generator expression.
|
||
|
|
||
|
As of cotire 1.7.0, the default linking strategy for unit targets is `COPY_UNITY`.
|
||
|
|
||
|
The property `COTIRE_UNITY_LINK_LIBRARIES_INIT` can also be set on directories. A target inherits
|
||
|
the property value from its enclosing directory. To make all targets in the project use the
|
||
|
`COPY` strategy, the directory property can be set in the outermost `CMakeList.txt` file:
|
||
|
|
||
|
include(cotire)
|
||
|
...
|
||
|
set_property(DIRECTORY PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT "COPY")
|
||
|
|
||
|
### using cotire with Qt
|
||
|
|
||
|
Cotire is compatible with both Qt projects that use CMake as build system, provided Qt targets
|
||
|
do not use CMake automatic moc, uid or rcc scanning.
|
||
|
|
||
|
### installing files generated by unity targets
|
||
|
|
||
|
Cotire cannot set up a `install_unity` target that mimics the `install` target automatically,
|
||
|
because CMake does not provide the necessary information about the existing install rules
|
||
|
programmatically.
|
||
|
|
||
|
When using a Makefile generator, you can use the following workaround (thanks to peterhuene):
|
||
|
|
||
|
$ make all_unity
|
||
|
$ make install/fast
|
||
|
|
||
|
The `install/fast` does not trigger a build, but will use the binaries built by the `all_unity`
|
||
|
target.
|
||
|
|
||
|
For other generators, set up an `install_unity` target manually. First set up install rules for
|
||
|
all unity targets, that mimic the install rules for the original targets:
|
||
|
|
||
|
install(TARGETS example_unity RUNTIME DESTINATION "bin" OPTIONAL COMPONENT "unity")
|
||
|
|
||
|
This installs the `example` executable built by the unity target to the `bin` folder. The install
|
||
|
rules for unity targets must use a custom install component. Then add a global `install_unity`
|
||
|
target that performs the installation of all unity targets:
|
||
|
|
||
|
add_custom_target(install_unity
|
||
|
COMMAND ${CMAKE_COMMAND} -DCOMPONENT=unity -P cmake_install.cmake
|
||
|
COMMENT "Install the unity-built project..."
|
||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||
|
add_dependencies(unity_install example_unity)
|
||
|
|
||
|
The global `install_unity` target must depend on all unity targets that should be installed.
|
||
|
|
||
|
### customized inclusion of system headers
|
||
|
|
||
|
If a system header ends up in a precompiled header, it is not possible to customize the inclusion
|
||
|
of that header in a source file through preprocessor defines.
|
||
|
|
||
|
For example, under Windows one may want to include `Windows.h` with `NOMINMAX` defined to prevent
|
||
|
the definition of the `min` and `max` macros:
|
||
|
|
||
|
#define NOMINMAX
|
||
|
#include <Windows.h>
|
||
|
|
||
|
The dependency of `Windows.h` on the preprocessor define `NOMINMAX` will not be picked up by cotire
|
||
|
automatically upon adding `Windows.h` to the prefix header. To work around the problem, make the
|
||
|
dependency explicit by using `add_definitions` in the corresponding `CMakeLists.txt`:
|
||
|
|
||
|
if (WIN32)
|
||
|
# prevent definition of min and max macros through inclusion of Windows.h
|
||
|
add_definitions("-DNOMINMAX")
|
||
|
endif()
|
||
|
|
||
|
That way, the preprocessor define `NOMINMAX` will be picked up by cotire and applied to the
|
||
|
pre-compilation of the prefix header.
|
||
|
|
||
|
### organize includes added to the prefix header
|
||
|
|
||
|
Sometimes the order of the includes in the automatically generated prefix header may result in
|
||
|
compilation errors due to subtile header dependencies.
|
||
|
|
||
|
To work around the problem, the target property `COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH`
|
||
|
can be set to a list of directories. Header files whose path matches one of these directories will
|
||
|
be inserted at the beginning of generated prefix header. Header files are sorted according to
|
||
|
the order of the directories in the property. Headers not matching one of these directories are
|
||
|
left untouched.
|
||
|
|
||
|
The property `COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH` can also be set on directories. A target
|
||
|
inherits the property value from its enclosing directory.
|
||
|
|
||
|
common pitfalls
|
||
|
---------------
|
||
|
|
||
|
### include the `cotire.cmake` module correctly
|
||
|
|
||
|
If CMake issues the message `Unknown CMake command "cotire"`, double check that the cotire module
|
||
|
has been included correctly in your project. See the manual section "cotire basic usage".
|
||
|
|
||
|
### do not modify a target's build related properties after applying cotire
|
||
|
|
||
|
Cotire only considers build related settings of a target at the time of the `cotire` function call.
|
||
|
If target properties that control the build are changed after the call to the `cotire` function,
|
||
|
the build rules set up by cotire for the precompiled header and unity build may not work correctly.
|
||
|
|
||
|
Don't do this:
|
||
|
|
||
|
add_executable(example main.cpp example.cpp log.cpp log.h example.h)
|
||
|
cotire(example)
|
||
|
...
|
||
|
set_target_properties(example PROPERTIES POSITION_INDEPENDENT_CODE ON) # affects build
|
||
|
|
||
|
|
||
|
### always apply cotire in the same source directory where a target has been added
|
||
|
|
||
|
CMake targets are globally visible. Nevertheless, it is important that the `cotire` function is
|
||
|
called for a target in the exact same directory that creates the target with `add_library` or
|
||
|
`add_executable`.
|
||
|
|
||
|
Don't do this:
|
||
|
|
||
|
add_subdirectory(src)
|
||
|
...
|
||
|
cotire(mytarget) # mytarget added in src directory
|
||
|
|
||
|
Cotire may fail to inspect the target's source files correctly, if the target has been added in a
|
||
|
different directory and you may get odd messages about missing source files.
|
||
|
|
||
|
known issues
|
||
|
------------
|
||
|
|
||
|
### generator expressions
|
||
|
|
||
|
cotire uses the CMake command `file(GENERATE ...` to expand generator expressions used in various
|
||
|
compilation settings. This command does not handle certain CMake generator expressions like
|
||
|
`$<CXX_COMPILER_ID:...>` correctly.
|
||
|
|
||
|
### Ninja compatibility
|
||
|
|
||
|
Under Ninja indirect prefix header dependencies are ignored by the generated build system. Cotire
|
||
|
uses the `IMPLICIT_DEPENDS` option of `add_custom_command` to make the precompiled header depend
|
||
|
on header files indirectly included by the prefix header. The `IMPLICIT_DEPENDS` option is not
|
||
|
supported by CMake's Ninja generator. See [CMake issue][ninja_issue].
|
||
|
|
||
|
### using source files for multiple targets
|
||
|
|
||
|
When the same set of source files is used for different targets (e.g., for producing a static
|
||
|
and a shared library variant from the same sources), using a precompiled header may not work.
|
||
|
Under certain circumstances, cotire cannot enable the precompiled header usage by changing the
|
||
|
`COMPILE_FLAGS` property of the whole target, but must set the `COMPILE_FLAGS` properties of
|
||
|
individual target source files instead. This will break the usage of the source file for multiple
|
||
|
targets.
|
||
|
|
||
|
### multi-architecture builds under Mac OS X
|
||
|
|
||
|
Neither GCC nor Clang support the use of precompiled headers when performing a Mac OS X
|
||
|
multi-architecture build (e.g., using option `-DCMAKE_OSX_ARCHITECTURES=i386;x86_64`).
|
||
|
|
||
|
### Objective-C
|
||
|
|
||
|
CMake targets that contain Objective-C or Objective-C++ source files cannot be cotired. Source
|
||
|
files ending with .m and .mm are excluded by default through the initial default setting of
|
||
|
`COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS`.
|
||
|
|
||
|
### Intel C++
|
||
|
|
||
|
Intel C++ support has only been tested with [Intel C++ Composer XE 2013 for Linux][icc_linux] and
|
||
|
may not work with other platforms or versions.
|
||
|
|
||
|
The Intel compiler may issue incorrect warnings #672 (the command line options do not match those
|
||
|
used when precompiled header was created) or #673 (the initial sequence of preprocessing directives
|
||
|
is not compatible with those of precompiled header file) upon compilation of cotired targets.
|
||
|
|
||
|
### IncrediBuild
|
||
|
|
||
|
Cotire is not compatible with [Xoreax IncrediBuild][XGE].
|
||
|
|
||
|
[1260]:https://cmake.org/Bug/view.php?id=1260
|
||
|
[ccch]:https://ccache.samba.org/
|
||
|
[ccch_pch]:https://ccache.samba.org/manual.html#_precompiled_headers
|
||
|
[clang_pch]:https://clang.llvm.org/docs/UsersManual.html#precompiled-headers
|
||
|
[gcc_pch]:https://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html
|
||
|
[msvc_pch]:https://msdn.microsoft.com/en-us/library/szfdksca(v=vs.90).aspx
|
||
|
[msvc_pch_create]:https://msdn.microsoft.com/en-us/library/7zc28563(v=vs.90).aspx
|
||
|
[msvc_pch_use]:https://msdn.microsoft.com/en-us/library/z0atkd6c(v=vs.90).aspx
|
||
|
[ninja_issue]:https://cmake.org/Bug/view.php?id=13234
|
||
|
[EoUB]:http://altdevblog.com/2011/08/14/the-evils-of-unity-builds/
|
||
|
[pch]:https://en.wikipedia.org/wiki/Precompiled_header
|
||
|
[scu]:https://en.wikipedia.org/wiki/Single_Compilation_Unit
|
||
|
[objlib]:https://cmake.org/cmake/help/latest/command/add_library.html#object-libraries
|
||
|
[pfh]:https://en.wikipedia.org/wiki/Prefix_header
|
||
|
[icc_linux]:https://software.intel.com/en-us/c-compilers/ipsxe-support
|
||
|
[XGE]:https://www.incredibuild.com/
|