diff options
-rw-r--r-- | Help/command/target_precompile_headers.rst | 21 | ||||
-rw-r--r-- | Source/cmTargetPrecompileHeadersCommand.cxx | 41 | ||||
-rw-r--r-- | Source/cmTargetPrecompileHeadersCommand.h | 9 | ||||
-rw-r--r-- | Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake | 2 | ||||
-rw-r--r-- | Tests/RunCMake/PrecompileHeaders/PchInterface-check.cmake | 13 | ||||
-rw-r--r-- | Tests/RunCMake/PrecompileHeaders/PchInterface.cmake | 5 | ||||
-rw-r--r-- | Tests/RunCMake/PrecompileHeaders/foo.c | 6 | ||||
-rw-r--r-- | Tests/RunCMake/PrecompileHeaders/foobar.c | 3 | ||||
-rw-r--r-- | Tests/RunCMake/PrecompileHeaders/include/foo2.h | 6 |
9 files changed, 89 insertions, 17 deletions
diff --git a/Help/command/target_precompile_headers.rst b/Help/command/target_precompile_headers.rst index 7d36b11..3a32f41 100644 --- a/Help/command/target_precompile_headers.rst +++ b/Help/command/target_precompile_headers.rst @@ -48,17 +48,32 @@ See the :manual:`cmake-generator-expressions(7)` manual for available expressions. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. +Usage +^^^^^ + .. code-block:: cmake target_precompile_headers(<target> PUBLIC - "project_header.h" + project_header.h PRIVATE + [["other_header.h"]] <unordered_map> ) -Header files will be double quoted if they are not specified with double -quotes or angle brackets. +The list of header files is used to generate a header file named +``cmake_pch.h|xx`` which is used to generate the precompiled header file +(``.pch``, ``.gch``, ``.pchi``) artifact. The ``cmake_pch.h|xx`` header +file will be force included (``-include`` for GCC, ``/FI`` for MSVC) to +all source files, so sources do not need to have ``#include "pch.h"``. + +Header file names specified with angle brackets (e.g. ``<unordered_map>``) or +explicit double quotes (escaped for the :manual:`cmake-language(7)`, +e.g. ``[["other_header.h"]]``) will be treated as is, and include directories +must be available for the compiler to find them. Other header file names +(e.g. ``project_header.h``) are interpreted as being relative to the current +source directory (e.g. :variable:`CMAKE_CURRENT_SOURCE_DIR`) and will be +included by absolute path. See Also ^^^^^^^^ diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx index 97f1bea..5751fff 100644 --- a/Source/cmTargetPrecompileHeadersCommand.cxx +++ b/Source/cmTargetPrecompileHeadersCommand.cxx @@ -2,17 +2,29 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetPrecompileHeadersCommand.h" +#include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmStringAlgorithms.h" +#include "cmSystemTools.h" #include "cmTarget.h" +#include <utility> + bool cmTargetPrecompileHeadersCommand::InitialPass( std::vector<std::string> const& args, cmExecutionStatus&) { return this->HandleArguments(args, "PRECOMPILE_HEADERS", PROCESS_REUSE_FROM); } +void cmTargetPrecompileHeadersCommand::HandleInterfaceContent( + cmTarget* tgt, const std::vector<std::string>& content, bool prepend, + bool system) +{ + cmTargetPropCommandBase::HandleInterfaceContent( + tgt, ConvertToAbsoluteContent(tgt, content, true), prepend, system); +} + void cmTargetPrecompileHeadersCommand::HandleMissingTarget( const std::string& name) { @@ -31,6 +43,33 @@ std::string cmTargetPrecompileHeadersCommand::Join( bool cmTargetPrecompileHeadersCommand::HandleDirectContent( cmTarget* tgt, const std::vector<std::string>& content, bool, bool) { - tgt->AppendProperty("PRECOMPILE_HEADERS", this->Join(content).c_str()); + tgt->AppendProperty( + "PRECOMPILE_HEADERS", + this->Join(ConvertToAbsoluteContent(tgt, content, false)).c_str()); return true; } + +std::vector<std::string> +cmTargetPrecompileHeadersCommand::ConvertToAbsoluteContent( + cmTarget* /*tgt*/, const std::vector<std::string>& content, + bool /*isInterfaceContent*/) +{ + std::vector<std::string> absoluteContent; + absoluteContent.reserve(content.size()); + for (std::string const& src : content) { + std::string absoluteSrc; + // Use '<foo.h>' and '"foo.h"' includes and absolute paths as-is. + // Interpret relative paths with respect to the source directory. + // If the path starts in a generator expression, assume it is absolute. + if (cmHasLiteralPrefix(src, "<") || cmHasLiteralPrefix(src, "\"") || + cmSystemTools::FileIsFullPath(src) || + cmGeneratorExpression::Find(src) == 0) { + absoluteSrc = src; + } else { + absoluteSrc = + cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', src); + } + absoluteContent.emplace_back(std::move(absoluteSrc)); + } + return absoluteContent; +} diff --git a/Source/cmTargetPrecompileHeadersCommand.h b/Source/cmTargetPrecompileHeadersCommand.h index 7e4558e..00dc928 100644 --- a/Source/cmTargetPrecompileHeadersCommand.h +++ b/Source/cmTargetPrecompileHeadersCommand.h @@ -28,6 +28,11 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; +protected: + void HandleInterfaceContent(cmTarget* tgt, + const std::vector<std::string>& content, + bool prepend, bool system) override; + private: void HandleMissingTarget(const std::string& name) override; @@ -36,6 +41,10 @@ private: bool prepend, bool system) override; std::string Join(const std::vector<std::string>& content) override; + + std::vector<std::string> ConvertToAbsoluteContent( + cmTarget* tgt, const std::vector<std::string>& content, + bool isInterfaceContent); }; #endif diff --git a/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake b/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake index ee47980..59ee14b 100644 --- a/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake +++ b/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake @@ -4,7 +4,7 @@ project(DisabledPch C) add_library(foo foo.c) target_include_directories(foo PUBLIC include) target_precompile_headers(foo PUBLIC - foo.h + include/foo.h <stdio.h> \"string.h\" ) diff --git a/Tests/RunCMake/PrecompileHeaders/PchInterface-check.cmake b/Tests/RunCMake/PrecompileHeaders/PchInterface-check.cmake index cbd6ede..caeb22b 100644 --- a/Tests/RunCMake/PrecompileHeaders/PchInterface-check.cmake +++ b/Tests/RunCMake/PrecompileHeaders/PchInterface-check.cmake @@ -18,19 +18,14 @@ endif() file(STRINGS ${foo_pch_header} foo_pch_header_strings) -if (NOT "#include \"foo.h\"" IN_LIST foo_pch_header_strings OR - NOT "#include <stdio.h>" IN_LIST foo_pch_header_strings OR - NOT "#include \"string.h\"" IN_LIST foo_pch_header_strings) - set(RunCMake_TEST_FAILED "Generated foo pch header ${foo_pch_header} has bad content") +if (NOT foo_pch_header_strings MATCHES ";#include \"[^\"]*PrecompileHeaders/include/foo.h\";#include \"foo2.h\";#include <stdio.h>;#include \"string.h\"(;|$)") + set(RunCMake_TEST_FAILED "Generated foo pch header\n ${foo_pch_header}\nhas bad content:\n ${foo_pch_header_strings}") return() endif() file(STRINGS ${foobar_pch_header} foobar_pch_header_strings) -if (NOT "#include \"foo.h\"" IN_LIST foobar_pch_header_strings OR - NOT "#include <stdio.h>" IN_LIST foobar_pch_header_strings OR - NOT "#include \"string.h\"" IN_LIST foobar_pch_header_strings OR - NOT "#include \"bar.h\"" IN_LIST foobar_pch_header_strings) - set(RunCMake_TEST_FAILED "Generated foobar pch header ${foobar_pch_header} has bad content") +if (NOT foobar_pch_header_strings MATCHES ";#include \"[^\"]*PrecompileHeaders/include/foo.h\";#include \"foo2.h\";#include <stdio.h>;#include \"string.h\";#include \"[^\"]*PrecompileHeaders/include/bar.h\"(;|$)") + set(RunCMake_TEST_FAILED "Generated foobar pch header\n ${foobar_pch_header}\nhas bad content:\n ${foobar_pch_header_strings}") return() endif() diff --git a/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake b/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake index 9041b09..a1e0792 100644 --- a/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake +++ b/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake @@ -4,14 +4,15 @@ project(PchInterface C) add_library(foo foo.c) target_include_directories(foo PUBLIC include) target_precompile_headers(foo PUBLIC - foo.h + include/foo.h + \"foo2.h\" <stdio.h> \"string.h\" ) add_library(bar INTERFACE) target_include_directories(bar INTERFACE include) -target_precompile_headers(bar INTERFACE bar.h) +target_precompile_headers(bar INTERFACE include/bar.h) add_executable(foobar foobar.c) target_link_libraries(foobar foo bar) diff --git a/Tests/RunCMake/PrecompileHeaders/foo.c b/Tests/RunCMake/PrecompileHeaders/foo.c index 974a248..85ea230 100644 --- a/Tests/RunCMake/PrecompileHeaders/foo.c +++ b/Tests/RunCMake/PrecompileHeaders/foo.c @@ -1,6 +1,12 @@ #include "foo.h" +#include "foo2.h" int foo() { return 0; } + +int foo2() +{ + return 0; +} diff --git a/Tests/RunCMake/PrecompileHeaders/foobar.c b/Tests/RunCMake/PrecompileHeaders/foobar.c index 6dbf8ce..7a135ea 100644 --- a/Tests/RunCMake/PrecompileHeaders/foobar.c +++ b/Tests/RunCMake/PrecompileHeaders/foobar.c @@ -1,7 +1,8 @@ #include "bar.h" #include "foo.h" +#include "foo2.h" int main() { - return foo() + bar(); + return foo() + foo2() + bar(); } diff --git a/Tests/RunCMake/PrecompileHeaders/include/foo2.h b/Tests/RunCMake/PrecompileHeaders/include/foo2.h new file mode 100644 index 0000000..4bf9c81 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/include/foo2.h @@ -0,0 +1,6 @@ +#ifndef foo2_h +#define foo2_h + +int foo2(void); + +#endif |