25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

37 KiB

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 usage and single compilation unit builds for C and C++.

motivation

Cotire was born out of a dissatisfaction with the existing CMake solutions for adding precompiled header 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 and unity builds 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 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 and Clang. 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 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 the precompiled header and then modifies the COMPILE_FLAGS of the remaining target source files to include 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 3. 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 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 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.

applying cotire to object library targets

CMake 2.8.8 introduced a new type of library target called object library. 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”.

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

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.

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 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.