Skip to content

Instantly share code, notes, and snippets.

@kfsone
Created January 24, 2023 01:44
Show Gist options
  • Save kfsone/cc31d7e2b20d7aec2e004e7c97f8296b to your computer and use it in GitHub Desktop.
Save kfsone/cc31d7e2b20d7aec2e004e7c97f8296b to your computer and use it in GitHub Desktop.
Add PCH helper
include_guard (GLOBAL)
# -----------------------------------------------------------------------------
# ADD_PRECOMPILED_HEADERS tells CMake to try and use the given header files as
# a list of pre-compiled headers for a given target (where supported), with
# language awareness. Default language is C++.
#
# It fully qualifies each of the headers with the BASE_DIR and it translates
# them into a list of generator expressions for the source language.
#
# Header files that end with "_inl.h" (inline implementations) will be ignored.
#
# include (AddPrecompiledHeaders.cmake)
# ADD_PRECOMPILED_HEADERS (
# TARGET <name of existing target>
# [LANGUAGE [CXX [ | C | OBJC | OBJCXX]]]
# [BASE_DIR] # Default path for the listed headers,
# # assumes CMAKE_CURRENT_LIST_DIR if not specified
# HEADERS
# <list of filenames or paths)
# )
#
# Example:
#
# cmake_minimum_required (VERSION 3.16)
# project (MyProj LANGUAGES C CXX OBJC)
# add_library (
# MyLib
# mylib.cpp
# mylib.h
# common.cpp
# common.h
# private.cpp
# private.h
# )
# include (AddPrecompiledHeaders.cmake)
# ADD_PRECOMPILED_HEADERS (TARGET MyLib HEADERS mylib.h common.h private.h)
#
# add_executable (
# MyExe
# main.cpp
# common.h
# )
# ADD_PRECOMPILED_HEADERS (TARGET MyExe HEADERS common.h)
# target_link_libraries (
# MyExe
# PUBLIC MyLib
# )
function (ADD_PRECOMPILED_HEADERS)
cmake_parse_arguments (
"tgt" # Prefix
"" # Options
"TARGET;LANGUAGE;BASE_DIR" # One-valued keywords
"HEADERS" # Multi-valued keywords
${ARGN} # Arguments
)
# The list of languages we accept
set (languages C CXX OBJC OBJCXX)
# Argument validation
if (tgt_UNPARSED_ARGUMENTS)
message (SEND_ERROR "${tgt_TARGET}: Invalid arguments to ADD_PRECOMPILED_HEADERS: ${tgt_UNPARSED_ARGUMENTS}")
endif ()
if (NOT tgt_HEADERS)
message (DEBUG "${tgt_TARGET}: HEADERS empty, not adding pch.")
endif ()
if (NOT tgt_LANGUAGE)
set (tgt_LANGUAGE "CXX")
endif ()
if (NOT tgt_LANGUAGE IN_LIST languages)
message (SEND_ERROR "${tgt_TARGET}: Unrecognized language: ${tgt_LANGUAGE}")
endif ()
if (NOT tgt_BASE_DIR)
set (tgt_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
endif ()
if (NOT IS_DIRECTORY "${tgt_BASE_DIR}")
message (SEND_ERROR "${tgt_TARGET}: Invalid 'BASE_DIR': ${tgt_BASE_DIR}")
endif ()
# Translate the local-relative list of header filenames into a list of fully
# qualified list of paths in ${headers}, as required by target_precompiled_headers.
set (headers "")
foreach (filename ${tgt_HEADERS})
# Exclude inline implementation headers.
if (NOT filename MATCHES ".*_inl.h")
get_filename_component (header ${filename} ABSOLUTE BASE_DIR ${tgt_BASE_DIR})
if (NOT EXISTS ${header})
message (SEND_ERROR "${tgt_TARGET}: ${filename} does not exist.")
endif ()
list (APPEND headers ${header})
endif ()
endforeach ()
# Did we find anything meaningful?
if (headers)
message (VERBOSE "${tgt_TARGET}: Adding C++ precompiled headers: ${tgt_HEADERS}")
target_precompile_headers (${tgt_TARGET} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${headers}>)
endif ()
endfunction ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment