Module to precompile headers
This CMake module will set up a target for compiling a set of headers which can then be added to compilation modules to speed up compilation. A separate target is created because the function doesn't know all the sources of a target, and to reuse the precompiled header across several targets that share the same characteristics (such as unit tests).
This commit is contained in:
parent
3ca1d229d2
commit
e0e1a24edd
150
cmake/Modules/UsePrecompHeaders.cmake
Normal file
150
cmake/Modules/UsePrecompHeaders.cmake
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# - Use precompiled headers
|
||||||
|
#
|
||||||
|
# precompile_header takes these parameters
|
||||||
|
#
|
||||||
|
# language Language in which the header is written; C or CXX.
|
||||||
|
#
|
||||||
|
# type Type of target being build, SHARED_LIBRARY, STATIC_LIBRARY
|
||||||
|
# or EXECUTABLE.
|
||||||
|
#
|
||||||
|
# header Relative path within the source tree to the header
|
||||||
|
# that contains the list of includes to be precompiled.
|
||||||
|
# This header should not be added to the installation,
|
||||||
|
# as it will be specific for this project.
|
||||||
|
#
|
||||||
|
# target Name of target to be created. All targets that
|
||||||
|
# use the precompiled header should depend on this target
|
||||||
|
# so that it is built before them. A variable with this
|
||||||
|
# name will also be created which contains the file name.
|
||||||
|
#
|
||||||
|
# flags_name Name of variable to receive the flags that should be
|
||||||
|
# added to the command-line.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# get_target_property (type opmcore TYPE)
|
||||||
|
# precompile_header (CXX ${type}
|
||||||
|
# HEADER "opm/core/opm-core-pch.hpp"
|
||||||
|
# TARGET opmcore_CXX_pch
|
||||||
|
# FLAGS opmcore_PRECOMP_CXX_FLAGS
|
||||||
|
# )
|
||||||
|
# set_source_files_properties (${opmcore_CXX_SOURCES} PROPERTIES
|
||||||
|
# OBJECT_DEPENDS "${opmcore_CXX_pch}"
|
||||||
|
# COMPILE_FLAGS "${opmcore_PRECOMP_CXX_FLAGS}"
|
||||||
|
# )
|
||||||
|
|
||||||
|
# reconstruct the compiler command line; this does NOT include the
|
||||||
|
# DEFINE_SYMBOL that is added for shared libraries. type is the TYPE
|
||||||
|
# target property.
|
||||||
|
# see larsch's PrecompiledHeader.cmake: <https://gist.github.com/573926>
|
||||||
|
# and <https://github.com/loaden/qtcreator/blob/wip/cmake/cmake/PrecompiledHeader.cmake>
|
||||||
|
function (compiler_cmdline language type cmd_name args_name)
|
||||||
|
# get the compiler for this particular language
|
||||||
|
set (${cmd_name} "${CMAKE_${language}_COMPILER}" PARENT_SCOPE)
|
||||||
|
|
||||||
|
# in case someone has overridden the compiler (e.g. ccache)
|
||||||
|
set (_args "${CMAKE_${language}_COMPILER_ARG1}")
|
||||||
|
|
||||||
|
# macro definitions
|
||||||
|
get_directory_property (_defs DEFINITIONS)
|
||||||
|
list (APPEND _args "${_defs}")
|
||||||
|
|
||||||
|
# global flags (such as -std=c++11); notice that there are both
|
||||||
|
# release-dependent and non-release-dependent ones
|
||||||
|
string (TOUPPER "CMAKE_${language}_FLAGS" _flags)
|
||||||
|
list (APPEND _args "${${_flags}}")
|
||||||
|
string (TOUPPER "CMAKE_${language}_FLAGS_${CMAKE_BUILD_TYPE}" _flags)
|
||||||
|
list (APPEND _args "${${_flags}}")
|
||||||
|
|
||||||
|
# assume that we are always generating position-independent code
|
||||||
|
# when compiling for a shared library
|
||||||
|
if (type STREQUAL "SHARED_LIBRARY")
|
||||||
|
list (APPEND _args "${CMAKE_SHARED_LIBRARY_${language}_FLAGS}")
|
||||||
|
endif (type STREQUAL "SHARED_LIBRARY")
|
||||||
|
|
||||||
|
# directories included
|
||||||
|
get_directory_property (_dirs INCLUDE_DIRECTORIES)
|
||||||
|
foreach (_dir ${_dirs})
|
||||||
|
list (APPEND _args "-I${_dir}")
|
||||||
|
endforeach (_dir)
|
||||||
|
|
||||||
|
# make arguments a real list, and write to output variable
|
||||||
|
separate_arguments (_args)
|
||||||
|
set (${args_name} "${_args}" PARENT_SCOPE)
|
||||||
|
endfunction (compiler_cmdline language type cmd_name args_name)
|
||||||
|
|
||||||
|
# probe the GCC version
|
||||||
|
function (get_gcc_version language ver_name)
|
||||||
|
# exec_program is deprecated, but execute_process does't work :-(
|
||||||
|
exec_program (${CMAKE_${language}_COMPILER}
|
||||||
|
ARGS ${CMAKE_${language}_COMPILER_ARG1} -dumpversion
|
||||||
|
OUTPUT_VARIABLE _version
|
||||||
|
)
|
||||||
|
set (${ver_name} ${_version} PARENT_SCOPE)
|
||||||
|
endfunction (get_gcc_version ver_name)
|
||||||
|
|
||||||
|
function (precompile_header
|
||||||
|
language type hdr_kw header tgt_kw target flgs_kw flags_name)
|
||||||
|
|
||||||
|
# check "syntax"
|
||||||
|
if (NOT hdr_kw STREQUAL "HEADER")
|
||||||
|
message (FATAL "Third token to precompile_header shoulde be \"HEADER\"")
|
||||||
|
endif (NOT hdr_kw STREQUAL "HEADER")
|
||||||
|
if (NOT tgt_kw STREQUAL "TARGET")
|
||||||
|
message (FATAL "Fifth token to precompile_header should be \"TARGET\"")
|
||||||
|
endif (NOT tgt_kw STREQUAL "TARGET")
|
||||||
|
if (NOT flgs_kw STREQUAL "FLAGS")
|
||||||
|
message (FATAL "Seventh token to precompile_header should be \"FLAGS\"")
|
||||||
|
endif (NOT flgs_kw STREQUAL "FLAGS")
|
||||||
|
|
||||||
|
# only support precompiled headers if the compiler is gcc >= 3.4
|
||||||
|
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
get_gcc_version (${language} GCC_VERSION)
|
||||||
|
if (GCC_VERSION VERSION_EQUAL 3.4 OR GCC_VERSION VERSION_GREATER 3.4)
|
||||||
|
# command-line used to compile modules in this kind of target
|
||||||
|
compiler_cmdline (${language} ${type} _cmd _args)
|
||||||
|
|
||||||
|
# gcc will include any configurations which are in a directory
|
||||||
|
# with the same name as the header included
|
||||||
|
set (_pch_dir "CMakeFiles/pch")
|
||||||
|
set (_pch_file "${_pch_dir}/${header}.gch/${target}")
|
||||||
|
|
||||||
|
# make sure that output directory exists
|
||||||
|
get_filename_component (_outdir "${PROJECT_BINARY_DIR}/${_pch_file}" PATH)
|
||||||
|
file (MAKE_DIRECTORY ${_outdir})
|
||||||
|
|
||||||
|
# we need to generate the precompiled header in the output tree, but
|
||||||
|
# at the same time prevent the compiler to pick up the header from the
|
||||||
|
# source tree. getting the order of the include paths right is fragile
|
||||||
|
# in CMake. by copying the header, we can put the precompile dump
|
||||||
|
# right next to it and have the compiler pick it up there
|
||||||
|
add_custom_command (
|
||||||
|
OUTPUT "${_pch_dir}/${header}"
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
ARGS -E copy "${PROJECT_SOURCE_DIR}/${header}" "${_pch_dir}/${header}"
|
||||||
|
DEPENDS "${PROJECT_SOURCE_DIR}/${header}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# add a makefile rule to create the precompiled header
|
||||||
|
add_custom_command (
|
||||||
|
OUTPUT ${PROJECT_BINARY_DIR}/${_pch_file}
|
||||||
|
COMMAND ${_cmd}
|
||||||
|
ARGS ${_args} "-o" "${_pch_file}" "${_pch_dir}/${header}"
|
||||||
|
DEPENDS "${_pch_dir}/${header}"
|
||||||
|
COMMENT "Precompiling headers ${_pch_file}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# create a phony target that is always built, but which only checks
|
||||||
|
# if the header file is OK (i.e. the header only gets rebuilt if
|
||||||
|
# necessary)
|
||||||
|
add_custom_target (${target} ALL
|
||||||
|
DEPENDS ${PROJECT_BINARY_DIR}/${_pch_file}
|
||||||
|
)
|
||||||
|
|
||||||
|
# these flags need to be added to the target
|
||||||
|
set (${target} "${_pch_file}" PARENT_SCOPE)
|
||||||
|
set (${flags_name} "-Winvalid-pch -include ${_pch_dir}/${header}" PARENT_SCOPE)
|
||||||
|
endif (GCC_VERSION VERSION_EQUAL 3.4 OR GCC_VERSION VERSION_GREATER 3.4)
|
||||||
|
endif (CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
|
||||||
|
endfunction (precompile_header
|
||||||
|
language type header tgt_kw target flgs_kw flags_name)
|
Loading…
Reference in New Issue
Block a user