From 0467a2f91b632e9eb69805b7f0a2034ed4c8f39e Mon Sep 17 00:00:00 2001 From: Daniel Pfeifer Date: Thu, 12 Mar 2015 22:44:38 +0100 Subject: PCH: add PRECOMPILE_HEADERS to special properties --- Source/cmExportBuildFileGenerator.cxx | 3 +++ Source/cmGeneratorExpressionDAGChecker.h | 3 ++- Source/cmGeneratorTarget.cxx | 43 +++++++++++++++++++++++++++++ Source/cmGeneratorTarget.h | 7 +++++ Source/cmTarget.cxx | 46 ++++++++++++++++++++++++++++++++ Source/cmTarget.h | 5 ++++ 6 files changed, 106 insertions(+), 1 deletion(-) diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 8a1a305..9f0396b 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -91,6 +91,9 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gte, cmGeneratorExpression::BuildInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gte, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gte, cmGeneratorExpression::BuildInterface, properties, missingTargets); diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index 6d7d6ef..b72a40f 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -29,7 +29,8 @@ class cmGeneratorTarget; SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES) \ SELECT(F, EvaluatingLinkOptions, LINK_OPTIONS) \ SELECT(F, EvaluatingLinkDirectories, LINK_DIRECTORIES) \ - SELECT(F, EvaluatingLinkDepends, LINK_DEPENDS) + SELECT(F, EvaluatingLinkDepends, LINK_DEPENDS) \ + SELECT(F, EvaluatingPrecompileHeaders, PRECOMPILE_HEADERS) #define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \ CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 3048c5f..9e20b66 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -278,6 +278,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) , DebugCompileDefinitionsDone(false) , DebugLinkOptionsDone(false) , DebugLinkDirectoriesDone(false) + , DebugPrecompileHeadersDone(false) , DebugSourcesDone(false) , LinkImplementationLanguageIsContextDependent(true) , UtilityItemsDone(false) @@ -312,6 +313,10 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) t->GetLinkDirectoriesBacktraces(), this->LinkDirectoriesEntries); + CreatePropertyGeneratorExpressions(t->GetPrecompileHeadersEntries(), + t->GetPrecompileHeadersBacktraces(), + this->PrecompileHeadersEntries); + CreatePropertyGeneratorExpressions(t->GetSourceEntries(), t->GetSourceBacktraces(), this->SourceEntries, true); @@ -327,6 +332,7 @@ cmGeneratorTarget::~cmGeneratorTarget() cmDeleteAll(this->CompileDefinitionsEntries); cmDeleteAll(this->LinkOptionsEntries); cmDeleteAll(this->LinkDirectoriesEntries); + cmDeleteAll(this->PrecompileHeadersEntries); cmDeleteAll(this->SourceEntries); cmDeleteAll(this->LinkInformation); } @@ -3312,6 +3318,43 @@ std::vector> cmGeneratorTarget::GetCompileDefinitions( return list; } +std::vector> cmGeneratorTarget::GetPrecompileHeaders( + const std::string& config, const std::string& language) const +{ + std::unordered_set uniqueOptions; + + cmGeneratorExpressionDAGChecker dagChecker(this, "PRECOMPILE_HEADERS", + nullptr, nullptr); + + std::vector debugProperties; + const char* debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) { + cmExpandList(debugProp, debugProperties); + } + + bool debugDefines = !this->DebugPrecompileHeadersDone && + std::find(debugProperties.begin(), debugProperties.end(), + "PRECOMPILE_HEADERS") != debugProperties.end(); + + if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { + this->DebugPrecompileHeadersDone = true; + } + + std::vector entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->PrecompileHeadersEntries); + + AddInterfaceEntries(this, config, "INTERFACE_PRECOMPILE_HEADERS", language, + &dagChecker, entries); + + std::vector> list; + processOptions(this, entries, list, uniqueOptions, debugDefines, + "precompile headers", OptionsParse::None); + + return list; +} + void cmGeneratorTarget::GetLinkOptions(std::vector& result, const std::string& config, const std::string& language) const diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 3874738..9d422ee 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -455,6 +455,9 @@ public: std::vector> GetLinkDepends( std::string const& config, std::string const& language) const; + std::vector> GetPrecompileHeaders( + const std::string& config, const std::string& language) const; + bool IsSystemIncludeDirectory(const std::string& dir, const std::string& config, const std::string& language) const; @@ -867,8 +870,11 @@ private: std::vector CompileDefinitionsEntries; std::vector LinkOptionsEntries; std::vector LinkDirectoriesEntries; + std::vector PrecompileHeadersEntries; std::vector SourceEntries; mutable std::set LinkImplicitNullProperties; + mutable std::map PchHeaders; + mutable std::map PchSources; void ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, @@ -922,6 +928,7 @@ private: mutable bool DebugCompileDefinitionsDone; mutable bool DebugLinkOptionsDone; mutable bool DebugLinkDirectoriesDone; + mutable bool DebugPrecompileHeadersDone; mutable bool DebugSourcesDone; mutable bool LinkImplementationLanguageIsContextDependent; mutable bool UtilityItemsDone; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index df37d32..d2bcf3f 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -190,6 +190,8 @@ public: std::vector CompileFeaturesBacktraces; std::vector CompileDefinitionsEntries; std::vector CompileDefinitionsBacktraces; + std::vector PrecompileHeadersEntries; + std::vector PrecompileHeadersBacktraces; std::vector SourceEntries; std::vector SourceBacktraces; std::vector LinkOptionsEntries; @@ -348,6 +350,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("FOLDER"); initProp("Swift_MODULE_DIRECTORY"); initProp("VS_JUST_MY_CODE_DEBUGGING"); + initProp("DISABLE_PRECOMPILE_HEADERS"); #ifdef __APPLE__ if (this->GetGlobalGenerator()->IsXcode()) { initProp("XCODE_GENERATE_SCHEME"); @@ -1017,6 +1020,16 @@ cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const return cmMakeRange(impl->CompileDefinitionsBacktraces); } +cmStringRange cmTarget::GetPrecompileHeadersEntries() const +{ + return cmMakeRange(impl->PrecompileHeadersEntries); +} + +cmBacktraceRange cmTarget::GetPrecompileHeadersBacktraces() const +{ + return cmMakeRange(impl->PrecompileHeadersBacktraces); +} + cmStringRange cmTarget::GetSourceEntries() const { return cmMakeRange(impl->SourceEntries); @@ -1068,6 +1081,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) MAKE_STATIC_PROP(COMPILE_DEFINITIONS); MAKE_STATIC_PROP(COMPILE_FEATURES); MAKE_STATIC_PROP(COMPILE_OPTIONS); + MAKE_STATIC_PROP(PRECOMPILE_HEADERS); MAKE_STATIC_PROP(CUDA_PTX_COMPILATION); MAKE_STATIC_PROP(EXPORT_NAME); MAKE_STATIC_PROP(IMPORTED_GLOBAL); @@ -1166,6 +1180,14 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->LinkDirectoriesBacktraces.push_back(lfbt); } + } else if (prop == propPRECOMPILE_HEADERS) { + impl->PrecompileHeadersEntries.clear(); + impl->PrecompileHeadersBacktraces.clear(); + if (value) { + impl->PrecompileHeadersEntries.emplace_back(value); + cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); + impl->PrecompileHeadersBacktraces.push_back(lfbt); + } } else if (prop == propLINK_LIBRARIES) { impl->LinkImplementationPropertyEntries.clear(); impl->LinkImplementationPropertyBacktraces.clear(); @@ -1282,6 +1304,12 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); impl->LinkDirectoriesBacktraces.push_back(lfbt); } + } else if (prop == "PRECOMPILE_HEADERS") { + if (value && *value) { + impl->PrecompileHeadersEntries.emplace_back(value); + cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); + impl->PrecompileHeadersBacktraces.push_back(lfbt); + } } else if (prop == "LINK_LIBRARIES") { if (value && *value) { cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); @@ -1393,6 +1421,13 @@ void cmTarget::InsertLinkDirectory(std::string const& entry, impl->LinkDirectoriesBacktraces.insert(btPosition, bt); } +void cmTarget::InsertPrecompileHeader(std::string const& entry, + cmListFileBacktrace const& bt) +{ + impl->PrecompileHeadersEntries.push_back(entry); + impl->PrecompileHeadersBacktraces.push_back(bt); +} + static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop, const char* value, cmMakefile* context, @@ -1513,6 +1548,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const MAKE_STATIC_PROP(COMPILE_DEFINITIONS); MAKE_STATIC_PROP(LINK_OPTIONS); MAKE_STATIC_PROP(LINK_DIRECTORIES); + MAKE_STATIC_PROP(PRECOMPILE_HEADERS); MAKE_STATIC_PROP(IMPORTED); MAKE_STATIC_PROP(IMPORTED_GLOBAL); MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES); @@ -1528,6 +1564,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const propCOMPILE_FEATURES, propCOMPILE_OPTIONS, propCOMPILE_DEFINITIONS, + propPRECOMPILE_HEADERS, propLINK_OPTIONS, propLINK_DIRECTORIES, propIMPORTED, @@ -1616,6 +1653,15 @@ const char* cmTarget::GetProperty(const std::string& prop) const output = cmJoin(impl->Utilities, ";"); return output.c_str(); } + if (prop == propPRECOMPILE_HEADERS) { + if (impl->PrecompileHeadersEntries.empty()) { + return nullptr; + } + + static std::string output; + output = cmJoin(impl->PrecompileHeadersEntries, ";"); + return output.c_str(); + } if (prop == propIMPORTED) { return this->IsImported() ? "TRUE" : "FALSE"; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 2b75879..783c278 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -216,6 +216,8 @@ public: cmListFileBacktrace const& bt, bool before = false); void InsertLinkDirectory(std::string const& entry, cmListFileBacktrace const& bt, bool before = false); + void InsertPrecompileHeader(std::string const& entry, + cmListFileBacktrace const& bt); void AppendBuildInterfaceIncludes(); @@ -237,6 +239,9 @@ public: cmStringRange GetCompileDefinitionsEntries() const; cmBacktraceRange GetCompileDefinitionsBacktraces() const; + cmStringRange GetPrecompileHeadersEntries() const; + cmBacktraceRange GetPrecompileHeadersBacktraces() const; + cmStringRange GetSourceEntries() const; cmBacktraceRange GetSourceBacktraces() const; -- cgit v0.12 From 9b6797e71d28d4ee201cb0f8ed5efa39784a2af3 Mon Sep 17 00:00:00 2001 From: Daniel Pfeifer Date: Thu, 12 Mar 2015 17:44:36 +0100 Subject: PCH: add target_precompile_headers command --- Source/CMakeLists.txt | 2 ++ Source/cmCommands.cxx | 4 +++ Source/cmTargetPrecompileHeadersCommand.cxx | 36 +++++++++++++++++++++++++ Source/cmTargetPrecompileHeadersCommand.h | 41 +++++++++++++++++++++++++++++ bootstrap | 1 + 5 files changed, 84 insertions(+) create mode 100644 Source/cmTargetPrecompileHeadersCommand.cxx create mode 100644 Source/cmTargetPrecompileHeadersCommand.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 7cd07a8..10dfeef 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -656,6 +656,8 @@ set(SRCS cmTargetLinkDirectoriesCommand.h cmTargetLinkLibrariesCommand.cxx cmTargetLinkLibrariesCommand.h + cmTargetPrecompileHeadersCommand.cxx + cmTargetPrecompileHeadersCommand.h cmTargetPropCommandBase.cxx cmTargetPropCommandBase.h cmTargetSourcesCommand.cxx diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index ead16d2..41aabbb 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -78,6 +78,7 @@ #include "cmTargetCompileOptionsCommand.h" #include "cmTargetIncludeDirectoriesCommand.h" #include "cmTargetLinkLibrariesCommand.h" +#include "cmTargetPrecompileHeadersCommand.h" #include "cmTargetSourcesCommand.h" #include "cmTryCompileCommand.h" #include "cmTryRunCommand.h" @@ -277,6 +278,9 @@ void GetProjectCommands(cmState* state) state->AddBuiltinCommand("try_compile", cm::make_unique()); state->AddBuiltinCommand("try_run", cm::make_unique()); + state->AddBuiltinCommand( + "target_precompile_headers", + cm::make_unique()); #if !defined(CMAKE_BOOTSTRAP) state->AddBuiltinCommand("add_compile_definitions", diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx new file mode 100644 index 0000000..30cf1be --- /dev/null +++ b/Source/cmTargetPrecompileHeadersCommand.cxx @@ -0,0 +1,36 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmTargetPrecompileHeadersCommand.h" + +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmStringAlgorithms.h" +#include "cmTarget.h" + +bool cmTargetPrecompileHeadersCommand::InitialPass( + std::vector const& args, cmExecutionStatus&) +{ + return this->HandleArguments(args, "PRECOMPILE_HEADERS"); +} + +void cmTargetPrecompileHeadersCommand::HandleMissingTarget( + const std::string& name) +{ + const std::string e = + cmStrCat("Cannot specify precompile headers for target \"", name, + "\" which is not built by this project."); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); +} + +std::string cmTargetPrecompileHeadersCommand::Join( + const std::vector& content) +{ + return cmJoin(content, ";"); +} + +bool cmTargetPrecompileHeadersCommand::HandleDirectContent( + cmTarget* tgt, const std::vector& content, bool, bool) +{ + tgt->AppendProperty("PRECOMPILE_HEADERS", this->Join(content).c_str()); + return true; +} diff --git a/Source/cmTargetPrecompileHeadersCommand.h b/Source/cmTargetPrecompileHeadersCommand.h new file mode 100644 index 0000000..1ddf2af --- /dev/null +++ b/Source/cmTargetPrecompileHeadersCommand.h @@ -0,0 +1,41 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmTargetPrecompileHeadersCommand_h +#define cmTargetPrecompileHeadersCommand_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include + +#include "cm_memory.hxx" + +#include "cmCommand.h" + +#include "cmTargetPropCommandBase.h" + +class cmExecutionStatus; +class cmTarget; + +class cmTargetPrecompileHeadersCommand : public cmTargetPropCommandBase +{ +public: + std::unique_ptr Clone() override + { + return cm::make_unique(); + } + + bool InitialPass(std::vector const& args, + cmExecutionStatus& status) override; + +private: + void HandleMissingTarget(const std::string& name) override; + + bool HandleDirectContent(cmTarget* tgt, + const std::vector& content, + bool prepend, bool system) override; + + std::string Join(const std::vector& content) override; +}; + +#endif diff --git a/bootstrap b/bootstrap index 42503e3..e5e4aef 100755 --- a/bootstrap +++ b/bootstrap @@ -436,6 +436,7 @@ CMAKE_CXX_SOURCES="\ cmTargetCompileOptionsCommand \ cmTargetIncludeDirectoriesCommand \ cmTargetLinkLibrariesCommand \ + cmTargetPrecompileHeadersCommand \ cmTargetPropCommandBase \ cmTargetPropertyComputer \ cmTargetSourcesCommand \ -- cgit v0.12 From 375d01c6808713a0cfeef9ea092c8236ba063525 Mon Sep 17 00:00:00 2001 From: Daniel Pfeifer Date: Thu, 12 Mar 2015 17:45:20 +0100 Subject: PCH: add example/test --- Tests/PrecompileHeaders/CMakeLists.txt | 17 +++++++++++++++++ Tests/PrecompileHeaders/foo.c | 6 ++++++ Tests/PrecompileHeaders/foobar.c | 7 +++++++ Tests/PrecompileHeaders/include/bar.h | 9 +++++++++ Tests/PrecompileHeaders/include/foo.h | 6 ++++++ 5 files changed, 45 insertions(+) create mode 100644 Tests/PrecompileHeaders/CMakeLists.txt create mode 100644 Tests/PrecompileHeaders/foo.c create mode 100644 Tests/PrecompileHeaders/foobar.c create mode 100644 Tests/PrecompileHeaders/include/bar.h create mode 100644 Tests/PrecompileHeaders/include/foo.h diff --git a/Tests/PrecompileHeaders/CMakeLists.txt b/Tests/PrecompileHeaders/CMakeLists.txt new file mode 100644 index 0000000..90e1915 --- /dev/null +++ b/Tests/PrecompileHeaders/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.15) +project(PrecompileHeaders C) + +add_library(foo foo.c) +target_include_directories(foo PUBLIC include) +target_precompile_headers(foo PUBLIC + foo.h + + \"string.h\" +) + +add_library(bar INTERFACE) +target_include_directories(bar INTERFACE include) +target_precompile_headers(bar INTERFACE bar.h) + +add_executable(foobar foobar.c) +target_link_libraries(foobar foo bar) diff --git a/Tests/PrecompileHeaders/foo.c b/Tests/PrecompileHeaders/foo.c new file mode 100644 index 0000000..974a248 --- /dev/null +++ b/Tests/PrecompileHeaders/foo.c @@ -0,0 +1,6 @@ +#include "foo.h" + +int foo() +{ + return 0; +} diff --git a/Tests/PrecompileHeaders/foobar.c b/Tests/PrecompileHeaders/foobar.c new file mode 100644 index 0000000..6dbf8ce --- /dev/null +++ b/Tests/PrecompileHeaders/foobar.c @@ -0,0 +1,7 @@ +#include "bar.h" +#include "foo.h" + +int main() +{ + return foo() + bar(); +} diff --git a/Tests/PrecompileHeaders/include/bar.h b/Tests/PrecompileHeaders/include/bar.h new file mode 100644 index 0000000..5feb983 --- /dev/null +++ b/Tests/PrecompileHeaders/include/bar.h @@ -0,0 +1,9 @@ +#ifndef bar_h +#define bar_h + +static int bar() +{ + return 0; +} + +#endif diff --git a/Tests/PrecompileHeaders/include/foo.h b/Tests/PrecompileHeaders/include/foo.h new file mode 100644 index 0000000..4a49474 --- /dev/null +++ b/Tests/PrecompileHeaders/include/foo.h @@ -0,0 +1,6 @@ +#ifndef foo_h +#define foo_h + +extern int foo(); + +#endif -- cgit v0.12 From b8626261e95e0f99c9227d619671822f9a60ef1a Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Sat, 13 Jul 2019 12:07:30 +0200 Subject: Precompile headers: Add methods to generate PCH sources Co-Author: Daniel Pfeifer --- Modules/Compiler/Clang.cmake | 2 + Modules/Compiler/GNU.cmake | 8 ++ Modules/Compiler/Intel.cmake | 7 ++ Modules/Platform/Windows-Clang.cmake | 7 ++ Modules/Platform/Windows-Embarcadero.cmake | 7 ++ Modules/Platform/Windows-MSVC.cmake | 9 ++ Source/cmGeneratorTarget.cxx | 110 +++++++++++++++++++++++++ Source/cmGeneratorTarget.h | 5 ++ Source/cmLocalGenerator.cxx | 83 +++++++++++++++++++ Source/cmLocalGenerator.h | 2 + Source/cmMakefileExecutableTargetGenerator.cxx | 2 + Source/cmMakefileLibraryTargetGenerator.cxx | 2 + Source/cmMakefileTargetGenerator.cxx | 20 ++++- Source/cmMakefileUtilityTargetGenerator.cxx | 2 + Source/cmNinjaNormalTargetGenerator.cxx | 2 + Source/cmNinjaTargetGenerator.cxx | 16 +++- Utilities/IWYU/mapping.imp | 2 + 17 files changed, 282 insertions(+), 4 deletions(-) diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index c3f13f3..45c33fb 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -96,5 +96,7 @@ else() set(CMAKE_${lang}_ARCHIVE_FINISH_IPO "\"${__ranlib}\" " ) + + set(CMAKE_PCH_PROLOGUE "#pragma clang system_header") endmacro() endif() diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake index 6b1bd3a..e0ff174 100644 --- a/Modules/Compiler/GNU.cmake +++ b/Modules/Compiler/GNU.cmake @@ -11,6 +11,9 @@ set(__COMPILER_GNU 1) include(Compiler/CMakeCommonCompilerMacros) include(Internal/CMakeCheckCompilerFlag) +set(__pch_header_C "c-header") +set(__pch_header_CXX "c++-header") + macro(__compiler_gnu lang) # Feature flags. set(CMAKE_${lang}_VERBOSE_FLAG "-v") @@ -104,4 +107,9 @@ macro(__compiler_gnu lang) unset(_COMPILER_ARGS) endif() list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp") + + set(CMAKE_PCH_EXTENSION .gch) + set(CMAKE_PCH_PROLOGUE "#pragma GCC system_header") + set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Winvalid-pch -include ) + set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Winvalid-pch -x ${__pch_header_${lang}} -include ) endmacro() diff --git a/Modules/Compiler/Intel.cmake b/Modules/Compiler/Intel.cmake index f2f16e0..d895ed0 100644 --- a/Modules/Compiler/Intel.cmake +++ b/Modules/Compiler/Intel.cmake @@ -32,5 +32,12 @@ else() unset(_COMPILER_ARGS) endif() list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-QdM" "-P" "-Za" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp") + + # Precompile Headers + set(CMAKE_PCH_EXTENSION .pchi) + set(CMAKE_LINK_PCH ON) + set(CMAKE_PCH_EPILOGUE "#pragma hdrstop") + set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Winvalid-pch -Wno-pch-messages -pch-use -include ) + set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Winvalid-pch -Wno-pch-messages -pch-create -include ) endmacro() endif() diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index 728e0b9..220649c 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -8,6 +8,9 @@ if(__WINDOWS_CLANG) endif() set(__WINDOWS_CLANG 1) +set(__pch_header_C "c-header") +set(__pch_header_CXX "c++-header") + macro(__windows_compiler_clang_gnu lang) set(CMAKE_LIBRARY_PATH_FLAG "-L") set(CMAKE_LINK_LIBRARY_FLAG "-l") @@ -73,6 +76,10 @@ macro(__windows_compiler_clang_gnu lang) string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG -Xclang -gcodeview ${__ADDED_FLAGS}") set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") + set(CMAKE_PCH_EXTENSION .gch) + set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Winvalid-pch -include ) + set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Winvalid-pch -x ${__pch_header_${lang}} -include ) + unset(__ADDED_FLAGS) unset(__ADDED_FLAGS_DEBUG) string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_LOWER) diff --git a/Modules/Platform/Windows-Embarcadero.cmake b/Modules/Platform/Windows-Embarcadero.cmake index 48b936e..370b56e 100644 --- a/Modules/Platform/Windows-Embarcadero.cmake +++ b/Modules/Platform/Windows-Embarcadero.cmake @@ -119,6 +119,13 @@ macro(__embarcadero_language lang) "tlib ${CMAKE_START_TEMP_FILE}/p512 /a ${CMAKE_END_TEMP_FILE}" ) + # Precompile Headers + if (EMBARCADERO) + set(CMAKE_PCH_EXTENSION .pch) + set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Xclang -include-pch -Xclang ) + set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Xclang -emit-pch -Xclang -include -Xclang ) + endif() + # Initial configuration flags. string(APPEND CMAKE_${lang}_FLAGS_INIT " ${_tM}") string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -Od -v") diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 7a83859..6ddcaa3 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -329,6 +329,15 @@ macro(__windows_compiler_msvc lang) set(CMAKE_${lang}_LINK_EXECUTABLE "${_CMAKE_VS_LINK_EXE} ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out: /implib: /pdb: /version:.${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}") + set(CMAKE_PCH_EXTENSION .pch) + set(CMAKE_LINK_PCH ON) + if(MSVC_VERSION GREATER_EQUAL 1910) + # VS 2017 or greater + set(CMAKE_PCH_PROLOGUE "#pragma system_header") + endif() + set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH /Yu /FI) + set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH /Yc /FI) + if("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xMSVC") set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 9e20b66..04738d8 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -21,6 +21,7 @@ #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" #include "cmCustomCommandLines.h" +#include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionDAGChecker.h" @@ -3355,6 +3356,115 @@ std::vector> cmGeneratorTarget::GetPrecompileHeaders( return list; } +std::string cmGeneratorTarget::GetPchHeader(const std::string& config, + const std::string& language) const +{ + if (language != "C" && language != "CXX") { + return std::string(); + } + if (this->GetPropertyAsBool("DISABLE_PRECOMPILE_HEADERS")) { + return std::string(); + } + const auto inserted = + this->PchHeaders.insert(std::make_pair(language + config, "")); + if (inserted.second) { + const std::vector> headers = + this->GetPrecompileHeaders(config, language); + if (headers.empty()) { + return std::string(); + } + std::string& filename = inserted.first->second; + + if (this->GetGlobalGenerator()->IsMultiConfig()) { + filename = + cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), "/"); + } else { + // For GCC we need to have the header file .h[xx] + // next to the .h[xx].gch file + filename = this->ObjectDirectory; + } + + filename = cmStrCat(filename, "CMakeFiles/", this->GetName(), + ".dir/cmake_pch", ((language == "C") ? ".h" : ".hxx")); + + const std::string filename_tmp = cmStrCat(filename, ".tmp"); + { + auto pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE"); + auto pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE"); + + cmGeneratedFileStream file( + filename_tmp, false, + this->GetGlobalGenerator()->GetMakefileEncoding()); + file << "/* generated by CMake */\n\n"; + if (pchPrologue) { + file << pchPrologue << "\n"; + } + if (this->GetGlobalGenerator()->IsXcode()) { + file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n"; + } + if (language == "CXX") { + file << "#ifdef __cplusplus\n"; + } + for (auto const& header_bt : headers) { + if (header_bt.Value.empty()) { + continue; + } + if (header_bt.Value[0] == '<' || header_bt.Value[0] == '"') { + file << "#include " << header_bt.Value << "\n"; + } else { + file << "#include \"" << header_bt.Value << "\"\n"; + } + } + if (language == "CXX") { + file << "#endif // __cplusplus\n"; + } + if (this->GetGlobalGenerator()->IsXcode()) { + file << "#endif // CMAKE_SKIP_PRECOMPILE_HEADERS\n"; + } + if (pchEpilogue) { + file << pchEpilogue << "\n"; + } + } + cmSystemTools::CopyFileIfDifferent(filename_tmp, filename); + cmSystemTools::RemoveFile(filename_tmp); + } + return inserted.first->second; +} + +std::string cmGeneratorTarget::GetPchSource(const std::string& config, + const std::string& language) const +{ + if (language != "C" && language != "CXX") { + return std::string(); + } + const auto inserted = + this->PchSources.insert(std::make_pair(language + config, "")); + if (inserted.second) { + const std::string pchHeader = this->GetPchHeader(config, language); + if (pchHeader.empty()) { + return std::string(); + } + std::string& filename = inserted.first->second; + filename = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), + "/CMakeFiles/", this->GetName(), ".dir/cmake_pch"); + + // For GCC the source extension will be tranformed into .h[xx].gch + if (!this->Makefile->IsOn("CMAKE_LINK_PCH")) { + filename += ((language == "C") ? ".h.c" : ".hxx.cxx"); + } else { + filename += ((language == "C") ? ".c" : ".cxx"); + } + const std::string filename_tmp = cmStrCat(filename, ".tmp"); + { + cmGeneratedFileStream file(filename_tmp); + file << "/* generated by CMake */\n"; + } + cmSystemTools::CopyFileIfDifferent(filename_tmp, filename); + cmSystemTools::RemoveFile(filename_tmp); + } + return inserted.first->second; +} + void cmGeneratorTarget::GetLinkOptions(std::vector& result, const std::string& config, const std::string& language) const diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 9d422ee..4701071 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -458,6 +458,11 @@ public: std::vector> GetPrecompileHeaders( const std::string& config, const std::string& language) const; + std::string GetPchHeader(const std::string& config, + const std::string& language) const; + std::string GetPchSource(const std::string& config, + const std::string& language) const; + bool IsSystemIncludeDirectory(const std::string& dir, const std::string& config, const std::string& language) const; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 57dabd1..d6d2f73 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -18,6 +18,7 @@ #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" +#include "cmSourceFileLocationKind.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" @@ -37,6 +38,7 @@ #include #include +#include #include #include #include @@ -2113,6 +2115,82 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags, this->AppendFlags(flags, this->EscapeForShell(rawFlag)); } +void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target, + const std::string& config) +{ + const std::string lang = target->GetLinkerLanguage(config); + const std::string buildType = cmSystemTools::UpperCase(config); + const std::string pchSource = target->GetPchSource(config, lang); + const std::string pchHeader = target->GetPchHeader(config, lang); + + if (pchSource.empty() || pchHeader.empty()) { + return; + } + + const std::string createOptVar = + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_CREATE_PCH"); + std::string createOptionList = + this->Makefile->GetSafeDefinition(createOptVar); + + const std::string useOptVar = + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_USE_PCH"); + std::string useOptionList = this->Makefile->GetSafeDefinition(useOptVar); + + const std::string pchExtension = + this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION"); + + if (createOptionList.empty() || useOptionList.empty() || + pchExtension.empty()) { + return; + } + + auto pch_sf = this->Makefile->GetOrCreateSource( + pchSource, false, cmSourceFileLocationKind::Known); + std::string pchFile = pchHeader; + + if (!this->GetGlobalGenerator()->IsXcode()) { + // Exclude the pch files from linking + if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { + cmSystemTools::ReplaceString(pchFile, (lang == "C" ? ".h" : ".hxx"), + pchExtension); + pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str()); + } else { + pchFile += pchExtension; + pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str()); + } + + target->AddSource(pchSource, true); + + for (auto& str : { std::ref(useOptionList), std::ref(createOptionList) }) { + cmSystemTools::ReplaceString(str, "", pchHeader); + cmSystemTools::ReplaceString(str, "", pchFile); + } + } + + pch_sf->SetProperty("COMPILE_OPTIONS", createOptionList.c_str()); + + std::vector sources; + target->GetSourceFiles(sources, buildType); + for (cmSourceFile* sf : sources) { + if (pch_sf == sf || sf->GetLanguage() != lang) { + continue; + } + + if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { + if (this->GetGlobalGenerator()->IsXcode()) { + sf->SetProperty("COMPILE_DEFINITIONS", + "CMAKE_SKIP_PRECOMPILE_HEADERS"); + } + continue; + } + + if (!this->GetGlobalGenerator()->IsXcode()) { + sf->SetProperty("OBJECT_DEPENDS", pchFile.c_str()); + sf->SetProperty("COMPILE_OPTIONS", useOptionList.c_str()); + } + } +} + void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, const std::string& config, @@ -2705,6 +2783,11 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( } } + const char* pchExtension = source.GetProperty("PCH_EXTENSION"); + if (pchExtension) { + customOutputExtension = pchExtension; + } + // Remove the source extension if it is to be replaced. if (replaceExt || customOutputExtension) { keptSourceExtension = false; diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 455e491..f63fe0f 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -124,6 +124,8 @@ public: virtual void AppendFlags(std::string& flags, const char* newFlags) const; virtual void AppendFlagEscape(std::string& flags, const std::string& rawFlag) const; + void AddPchDependencies(cmGeneratorTarget* target, + const std::string& config); void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, const std::string& config, const std::string& lang); diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 7bc05b1..bebd5c4 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -40,6 +40,8 @@ cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator( this->OSXBundleGenerator = cm::make_unique(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); + + this->LocalGenerator->AddPchDependencies(target, this->ConfigName); } cmMakefileExecutableTargetGenerator::~cmMakefileExecutableTargetGenerator() = diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 252279f..4244402 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -42,6 +42,8 @@ cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator( this->OSXBundleGenerator = cm::make_unique(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); + + this->LocalGenerator->AddPchDependencies(target, this->ConfigName); } cmMakefileLibraryTargetGenerator::~cmMakefileLibraryTargetGenerator() = diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index f99fe4e..90d8ea9 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -239,10 +239,15 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() this->GeneratorTarget->GetExtraSources(extraSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( extraSources, this->MacOSXContentGenerator); + const char* pchExtension = + this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector externalObjects; this->GeneratorTarget->GetExternalObjects(externalObjects, config); for (cmSourceFile const* sf : externalObjects) { - this->ExternalObjects.push_back(sf->GetFullPath()); + auto const& objectFileName = sf->GetFullPath(); + if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + this->ExternalObjects.push_back(objectFileName); + } } std::vector objectSources; this->GeneratorTarget->GetObjectSources(objectSources, config); @@ -1238,7 +1243,14 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( if (!lineContinue) { lineContinue = "\\"; } + + const char* pchExtension = + this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + for (std::string const& obj : this->Objects) { + if (cmSystemTools::StringEndsWith(obj, pchExtension)) { + continue; + } *this->BuildFileStream << " " << lineContinue << "\n"; *this->BuildFileStream << cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath( @@ -1331,10 +1343,16 @@ private: void cmMakefileTargetGenerator::WriteObjectsStrings( std::vector& objStrings, std::string::size_type limit) { + const char* pchExtension = + this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmMakefileTargetGeneratorObjectStrings helper( objStrings, this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory(), limit); for (std::string const& obj : this->Objects) { + if (cmSystemTools::StringEndsWith(obj, pchExtension)) { + continue; + } helper.Feed(obj); } for (std::string const& obj : this->ExternalObjects) { diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 8ed6be5..556191f 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -25,6 +25,8 @@ cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator( this->OSXBundleGenerator = cm::make_unique(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); + + this->LocalGenerator->AddPchDependencies(target, this->ConfigName); } cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator() = diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 2841245..462746a 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -59,6 +59,8 @@ cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator( this->OSXBundleGenerator = cm::make_unique(target, this->GetConfigName()); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); + + GetLocalGenerator()->AddPchDependencies(target, this->GetConfigName()); } cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 3d3d80d..29e8b74 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -790,10 +790,16 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() extraSources, this->MacOSXContentGenerator.get()); } { + const char* pchExtension = + GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); + std::vector externalObjects; this->GeneratorTarget->GetExternalObjects(externalObjects, config); for (cmSourceFile const* sf : externalObjects) { - this->Objects.push_back(this->GetSourceFilePath(sf)); + const auto objectFileName = this->GetSourceFilePath(sf); + if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + this->Objects.push_back(objectFileName); + } } } @@ -955,8 +961,12 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]); objBuild.Outputs.push_back(objectFileName); - // Add this object to the list of object files. - this->Objects.push_back(objectFileName); + const char* pchExtension = + this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); + if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + // Add this object to the list of object files. + this->Objects.push_back(objectFileName); + } objBuild.ExplicitDeps.push_back(sourceFileName); diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index 9fff442..78026fa 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -23,6 +23,7 @@ # HACK: check whether this can be removed with next iwyu release. { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, + { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, @@ -73,6 +74,7 @@ # Use '-Xiwyu -v7' to see the fully qualified names that need this. # TODO: Can this be simplified with an @-expression? #{ symbol: [ "@std::__decay_and_strip<.*>::__type", private, "\"cmConfigure.h\"", public ] }, + { symbol: [ "std::__decay_and_strip::__type", private, "\"cmConfigure.h\"", public ] }, { symbol: [ "std::__decay_and_strip::__type", private, "\"cmConfigure.h\"", public ] }, { symbol: [ "std::__decay_and_strip::__type", private, "\"cmConfigure.h\"", public ] }, { symbol: [ "std::__decay_and_strip::__type", private, "\"cmConfigure.h\"", public ] }, -- cgit v0.12 From 28be170fbc97a29be6383fb4afe5f62c6983fb2c Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Sat, 13 Jul 2019 12:07:30 +0200 Subject: Precompile headers: Add support for Xcode generator Co-Author: Daniel Pfeifer --- Source/cmGlobalXCodeGenerator.cxx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index a204fe0..427ab44 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2374,6 +2374,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION", this->CreateString(vso.str())); } + + // Precompile Headers + std::string pchHeader = gtgt->GetPchHeader(configName, llang); + if (!pchHeader.empty()) { + buildSettings->AddAttribute("GCC_PREFIX_HEADER", + this->CreateString(pchHeader)); + buildSettings->AddAttribute("GCC_PRECOMPILE_PREFIX_HEADER", + this->CreateString("YES")); + } + // put this last so it can override existing settings // Convert "XCODE_ATTRIBUTE_*" properties directly. { @@ -2829,6 +2839,8 @@ bool cmGlobalXCodeGenerator::CreateGroups( continue; } + generator->AddPchDependencies(gtgt, ""); + auto addSourceToGroup = [this, mf, gtgt, &sourceGroups](std::string const& source) { cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups); -- cgit v0.12 From 519606704eac6df1314ec6691a1b77d2131a6dbc Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Sat, 13 Jul 2019 12:07:30 +0200 Subject: Precompile headers: Add support for Visual Studio generators Tested with Visual C++ 2017 on Windows. Co-Author: Daniel Pfeifer --- Source/cmGlobalVisualStudioGenerator.h | 7 +++++++ Source/cmLocalVisualStudio7Generator.cxx | 2 ++ Source/cmVisualStudio10TargetGenerator.cxx | 13 ++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index cbab329..e4cd73f 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -110,6 +110,13 @@ public: bool IsIncludeExternalMSProjectSupported() const override { return true; } + /** Get encoding used by generator for generated source files + */ + codecvt::Encoding GetMakefileEncoding() const override + { + return codecvt::ANSI; + } + class TargetSet : public std::set { }; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 2c91974..795cee4 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1320,6 +1320,8 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, const std::string& libName, cmGeneratorTarget* target) { + this->AddPchDependencies(target, ""); + std::vector configs; this->Makefile->GetConfigurations(configs); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 13f6295..749d234 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -249,6 +249,8 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator( this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() == this->Makefile->GetCurrentBinaryDirectory()); + + this->LocalGenerator->AddPchDependencies(target, ""); } cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator() @@ -2145,6 +2147,9 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) { this->OutputSourceSpecificFlags(e2, si.Source); } + if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { + e2.Element("PrecompiledHeader", "NotUsing"); + } if (!exclude_configs.empty()) { this->WriteExcludeFromBuild(e2, exclude_configs); } @@ -2626,6 +2631,13 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->IPOEnabledConfigurations.insert(configName); } + // Precompile Headers + std::string pchHeader = + this->GeneratorTarget->GetPchHeader(configName, linkLanguage); + if (this->MSTools && vcxproj == this->ProjectType && pchHeader.empty()) { + clOptions.AddFlag("PrecompiledHeader", "NotUsing"); + } + // Get preprocessor definitions for this directory. std::string defineFlags = this->Makefile->GetDefineFlags(); if (this->MSTools) { @@ -2641,7 +2653,6 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( // replace this setting with "true" below. clOptions.AddFlag("UseFullPaths", "false"); } - clOptions.AddFlag("PrecompiledHeader", "NotUsing"); clOptions.AddFlag("AssemblerListingLocation", "$(IntDir)"); } } -- cgit v0.12 From 577293016430115a2d7dec5e3588f12bcabc96ec Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Wed, 31 Jul 2019 16:08:49 +0200 Subject: Precompile headers: Add unit tests --- Tests/PrecompileHeaders/CMakeLists.txt | 17 ------ Tests/PrecompileHeaders/foo.c | 6 -- Tests/PrecompileHeaders/foobar.c | 7 --- Tests/PrecompileHeaders/include/bar.h | 9 --- Tests/PrecompileHeaders/include/foo.h | 6 -- Tests/RunCMake/CMakeLists.txt | 2 + Tests/RunCMake/PrecompileHeaders/CMakeLists.txt | 3 + .../PrecompileHeaders/DisabledPch-check.cmake | 17 ++++++ Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake | 14 +++++ .../PrecompileHeaders/PchInterface-check.cmake | 36 +++++++++++ .../RunCMake/PrecompileHeaders/PchInterface.cmake | 20 +++++++ .../PchPrologueEpilogue-check.cmake | 12 ++++ .../PrecompileHeaders/PchPrologueEpilogue.cmake | 11 ++++ .../RunCMake/PrecompileHeaders/RunCMakeTest.cmake | 18 ++++++ .../PrecompileHeaders/SkipPrecompileHeaders.cmake | 13 ++++ Tests/RunCMake/PrecompileHeaders/foo.c | 6 ++ Tests/RunCMake/PrecompileHeaders/foobar.c | 7 +++ Tests/RunCMake/PrecompileHeaders/include/bar.h | 9 +++ Tests/RunCMake/PrecompileHeaders/include/foo.h | 6 ++ Tests/RunCMake/PrecompileHeaders/main.cpp | 4 ++ Tests/RunCMake/PrecompileHeaders/non-pch.cpp | 3 + Tests/RunCMake/PrecompileHeaders/pch.h | 3 + Tests/RunCMake/VS10Project/RunCMakeTest.cmake | 1 + .../VS10Project/VsPrecompileHeaders-check.cmake | 69 ++++++++++++++++++++++ .../RunCMake/VS10Project/VsPrecompileHeaders.cmake | 4 ++ Tests/RunCMake/XcodeProject/RunCMakeTest.cmake | 1 + .../XcodePrecompileHeaders-check.cmake | 35 +++++++++++ .../XcodeProject/XcodePrecompileHeaders.cmake | 4 ++ 28 files changed, 298 insertions(+), 45 deletions(-) delete mode 100644 Tests/PrecompileHeaders/CMakeLists.txt delete mode 100644 Tests/PrecompileHeaders/foo.c delete mode 100644 Tests/PrecompileHeaders/foobar.c delete mode 100644 Tests/PrecompileHeaders/include/bar.h delete mode 100644 Tests/PrecompileHeaders/include/foo.h create mode 100644 Tests/RunCMake/PrecompileHeaders/CMakeLists.txt create mode 100644 Tests/RunCMake/PrecompileHeaders/DisabledPch-check.cmake create mode 100644 Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake create mode 100644 Tests/RunCMake/PrecompileHeaders/PchInterface-check.cmake create mode 100644 Tests/RunCMake/PrecompileHeaders/PchInterface.cmake create mode 100644 Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue-check.cmake create mode 100644 Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue.cmake create mode 100644 Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/PrecompileHeaders/SkipPrecompileHeaders.cmake create mode 100644 Tests/RunCMake/PrecompileHeaders/foo.c create mode 100644 Tests/RunCMake/PrecompileHeaders/foobar.c create mode 100644 Tests/RunCMake/PrecompileHeaders/include/bar.h create mode 100644 Tests/RunCMake/PrecompileHeaders/include/foo.h create mode 100644 Tests/RunCMake/PrecompileHeaders/main.cpp create mode 100644 Tests/RunCMake/PrecompileHeaders/non-pch.cpp create mode 100644 Tests/RunCMake/PrecompileHeaders/pch.h create mode 100644 Tests/RunCMake/VS10Project/VsPrecompileHeaders-check.cmake create mode 100644 Tests/RunCMake/VS10Project/VsPrecompileHeaders.cmake create mode 100644 Tests/RunCMake/XcodeProject/XcodePrecompileHeaders-check.cmake create mode 100644 Tests/RunCMake/XcodeProject/XcodePrecompileHeaders.cmake diff --git a/Tests/PrecompileHeaders/CMakeLists.txt b/Tests/PrecompileHeaders/CMakeLists.txt deleted file mode 100644 index 90e1915..0000000 --- a/Tests/PrecompileHeaders/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required(VERSION 3.15) -project(PrecompileHeaders C) - -add_library(foo foo.c) -target_include_directories(foo PUBLIC include) -target_precompile_headers(foo PUBLIC - foo.h - - \"string.h\" -) - -add_library(bar INTERFACE) -target_include_directories(bar INTERFACE include) -target_precompile_headers(bar INTERFACE bar.h) - -add_executable(foobar foobar.c) -target_link_libraries(foobar foo bar) diff --git a/Tests/PrecompileHeaders/foo.c b/Tests/PrecompileHeaders/foo.c deleted file mode 100644 index 974a248..0000000 --- a/Tests/PrecompileHeaders/foo.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "foo.h" - -int foo() -{ - return 0; -} diff --git a/Tests/PrecompileHeaders/foobar.c b/Tests/PrecompileHeaders/foobar.c deleted file mode 100644 index 6dbf8ce..0000000 --- a/Tests/PrecompileHeaders/foobar.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "bar.h" -#include "foo.h" - -int main() -{ - return foo() + bar(); -} diff --git a/Tests/PrecompileHeaders/include/bar.h b/Tests/PrecompileHeaders/include/bar.h deleted file mode 100644 index 5feb983..0000000 --- a/Tests/PrecompileHeaders/include/bar.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef bar_h -#define bar_h - -static int bar() -{ - return 0; -} - -#endif diff --git a/Tests/PrecompileHeaders/include/foo.h b/Tests/PrecompileHeaders/include/foo.h deleted file mode 100644 index 4a49474..0000000 --- a/Tests/PrecompileHeaders/include/foo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef foo_h -#define foo_h - -extern int foo(); - -#endif diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 0e93cf8..9a31916 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -573,3 +573,5 @@ if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|9[0-9])") endif() add_RunCMake_test("CTestCommandExpandLists") + +add_RunCMake_test(PrecompileHeaders) diff --git a/Tests/RunCMake/PrecompileHeaders/CMakeLists.txt b/Tests/RunCMake/PrecompileHeaders/CMakeLists.txt new file mode 100644 index 0000000..7dbf32e --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.15.0) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/PrecompileHeaders/DisabledPch-check.cmake b/Tests/RunCMake/PrecompileHeaders/DisabledPch-check.cmake new file mode 100644 index 0000000..fa37c2c --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/DisabledPch-check.cmake @@ -0,0 +1,17 @@ +if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(foo_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foo.dir/CMakeFiles/foo.dir/cmake_pch.h") + set(foobar_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foobar.dir/CMakeFiles/foobar.dir/cmake_pch.h") +else() + set(foo_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foo.dir/cmake_pch.h") + set(foobar_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foobar.dir/cmake_pch.h") +endif() + +if (NOT EXISTS ${foo_pch_header}) + set(RunCMake_TEST_FAILED "Generated foo pch header ${foo_pch_header} does not exist") + return() +endif() + +if (EXISTS ${foobar_pch_header}) + set(RunCMake_TEST_FAILED "Generated foobar pch header ${foobar_pch_header} should not exist") + return() +endif() diff --git a/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake b/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake new file mode 100644 index 0000000..ee47980 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/DisabledPch.cmake @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.15) +project(DisabledPch C) + +add_library(foo foo.c) +target_include_directories(foo PUBLIC include) +target_precompile_headers(foo PUBLIC + foo.h + + \"string.h\" +) + +add_executable(foobar foobar.c) +target_link_libraries(foobar foo) +set_target_properties(foobar PROPERTIES DISABLE_PRECOMPILE_HEADERS ON) diff --git a/Tests/RunCMake/PrecompileHeaders/PchInterface-check.cmake b/Tests/RunCMake/PrecompileHeaders/PchInterface-check.cmake new file mode 100644 index 0000000..cbd6ede --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchInterface-check.cmake @@ -0,0 +1,36 @@ +if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(foo_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foo.dir/CMakeFiles/foo.dir/cmake_pch.h") + set(foobar_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foobar.dir/CMakeFiles/foobar.dir/cmake_pch.h") +else() + set(foo_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foo.dir/cmake_pch.h") + set(foobar_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/foobar.dir/cmake_pch.h") +endif() + +if (NOT EXISTS ${foo_pch_header}) + set(RunCMake_TEST_FAILED "Generated foo pch header ${foo_pch_header} does not exist") + return() +endif() + +if (NOT EXISTS ${foobar_pch_header}) + set(RunCMake_TEST_FAILED "Generated foobar pch header ${foobar_pch_header} does not exist") + return() +endif() + +file(STRINGS ${foo_pch_header} foo_pch_header_strings) + +if (NOT "#include \"foo.h\"" IN_LIST foo_pch_header_strings OR + NOT "#include " 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") + 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 " 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") + return() +endif() diff --git a/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake b/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake new file mode 100644 index 0000000..9041b09 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchInterface.cmake @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.15) +project(PchInterface C) + +add_library(foo foo.c) +target_include_directories(foo PUBLIC include) +target_precompile_headers(foo PUBLIC + foo.h + + \"string.h\" +) + +add_library(bar INTERFACE) +target_include_directories(bar INTERFACE include) +target_precompile_headers(bar INTERFACE bar.h) + +add_executable(foobar foobar.c) +target_link_libraries(foobar foo bar) + +enable_testing() +add_test(NAME foobar COMMAND foobar) diff --git a/Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue-check.cmake b/Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue-check.cmake new file mode 100644 index 0000000..fd82607 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue-check.cmake @@ -0,0 +1,12 @@ +if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(main_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/main.dir/CMakeFiles/main.dir/cmake_pch.hxx") +else() + set(main_pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/main.dir/cmake_pch.hxx") +endif() + +file(STRINGS ${main_pch_header} main_pch_header_strings) +string(REGEX MATCH "#pragma warning\\(push, 0\\).*#include.*pch.h.*#pragma warning\\(pop\\)" matched_code ${main_pch_header_strings}) +if(NOT matched_code) + set(RunCMake_TEST_FAILED "Generated pch file doesn't include expected prologue and epilogue code") + return() +endif() diff --git a/Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue.cmake b/Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue.cmake new file mode 100644 index 0000000..3e27620 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchPrologueEpilogue.cmake @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.15) + +project(PchPrologueEpilogue) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_PCH_PROLOGUE "#pragma warning(push, 0)") +set(CMAKE_PCH_EPILOGUE "#pragma warning(pop)") + +add_executable(main main.cpp) +target_precompile_headers(main PRIVATE pch.h) diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake new file mode 100644 index 0000000..fffcc47 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake @@ -0,0 +1,18 @@ +cmake_policy(SET CMP0057 NEW) +include(RunCMake) + +function(run_test name) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build) + run_cmake(${name}) + # Precompiled headers are not supported with multiple architectures. + if(NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]") + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug) + run_cmake_command(${name}-test ${CMAKE_CTEST_COMMAND} -C Debug) + endif() +endfunction() + +run_cmake(DisabledPch) +run_test(PchInterface) +run_cmake(PchPrologueEpilogue) +run_test(SkipPrecompileHeaders) diff --git a/Tests/RunCMake/PrecompileHeaders/SkipPrecompileHeaders.cmake b/Tests/RunCMake/PrecompileHeaders/SkipPrecompileHeaders.cmake new file mode 100644 index 0000000..49efbfb --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/SkipPrecompileHeaders.cmake @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.15) + +project(SkipPrecompileHeaders) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +add_executable(pch-test main.cpp non-pch.cpp) +target_precompile_headers(pch-test PRIVATE pch.h) + +set_source_files_properties(non-pch.cpp PROPERTIES SKIP_PRECOMPILE_HEADERS ON) + +enable_testing() +add_test(NAME pch-test COMMAND pch-test) diff --git a/Tests/RunCMake/PrecompileHeaders/foo.c b/Tests/RunCMake/PrecompileHeaders/foo.c new file mode 100644 index 0000000..974a248 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/foo.c @@ -0,0 +1,6 @@ +#include "foo.h" + +int foo() +{ + return 0; +} diff --git a/Tests/RunCMake/PrecompileHeaders/foobar.c b/Tests/RunCMake/PrecompileHeaders/foobar.c new file mode 100644 index 0000000..6dbf8ce --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/foobar.c @@ -0,0 +1,7 @@ +#include "bar.h" +#include "foo.h" + +int main() +{ + return foo() + bar(); +} diff --git a/Tests/RunCMake/PrecompileHeaders/include/bar.h b/Tests/RunCMake/PrecompileHeaders/include/bar.h new file mode 100644 index 0000000..5feb983 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/include/bar.h @@ -0,0 +1,9 @@ +#ifndef bar_h +#define bar_h + +static int bar() +{ + return 0; +} + +#endif diff --git a/Tests/RunCMake/PrecompileHeaders/include/foo.h b/Tests/RunCMake/PrecompileHeaders/include/foo.h new file mode 100644 index 0000000..4a49474 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/include/foo.h @@ -0,0 +1,6 @@ +#ifndef foo_h +#define foo_h + +extern int foo(); + +#endif diff --git a/Tests/RunCMake/PrecompileHeaders/main.cpp b/Tests/RunCMake/PrecompileHeaders/main.cpp new file mode 100644 index 0000000..f8b643a --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/main.cpp @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/Tests/RunCMake/PrecompileHeaders/non-pch.cpp b/Tests/RunCMake/PrecompileHeaders/non-pch.cpp new file mode 100644 index 0000000..df5a79f --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/non-pch.cpp @@ -0,0 +1,3 @@ +#ifdef PCH_INCLUDED +# error "PCH must not be included into this file!" +#endif diff --git a/Tests/RunCMake/PrecompileHeaders/pch.h b/Tests/RunCMake/PrecompileHeaders/pch.h new file mode 100644 index 0000000..81b6d9e --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/pch.h @@ -0,0 +1,3 @@ +#pragma once + +#define PCH_INCLUDED 1 diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index 5ca069a..72154e7 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -25,6 +25,7 @@ run_cmake(VsProjectImport) run_cmake(VsPackageReferences) run_cmake(VsDpiAware) run_cmake(VsDpiAwareBadParam) +run_cmake(VsPrecompileHeaders) if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) run_cmake(VsJustMyCode) diff --git a/Tests/RunCMake/VS10Project/VsPrecompileHeaders-check.cmake b/Tests/RunCMake/VS10Project/VsPrecompileHeaders-check.cmake new file mode 100644 index 0000000..82ca421 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsPrecompileHeaders-check.cmake @@ -0,0 +1,69 @@ +set(pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/cmake_pch.hxx") +set(pch_source "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/cmake_pch.cxx") + +file(TO_NATIVE_PATH "${pch_source}" pch_source_win) + +if(NOT EXISTS "${pch_header}") + set(RunCMake_TEST_FAILED "Generated PCH header ${pch_header} does not exist.") + return() +endif() +if(NOT EXISTS "${pch_source}") + set(RunCMake_TEST_FAILED "Generated PCH header ${pch_source} does not exist.") + return() +endif() + +set(tgt_project "${RunCMake_TEST_BINARY_DIR}/tgt.vcxproj") +if (NOT EXISTS "${tgt_project}") + set(RunCMake_TEST_FAILED "Generated project file ${tgt_project} doesn't exist.") + return() +endif() + +file(STRINGS ${tgt_project} tgt_projects_strings) + +foreach(line IN LISTS tgt_projects_strings) + if (line MATCHES "Use") + set(have_pch_use ON) + endif() + + if (line MATCHES "Create") + set(have_pch_create ON) + endif() + + if (line MATCHES "${pch_header}") + set(have_pch_header ON) + endif() + + if (line MATCHES "${pch_header}") + set(have_force_pch_header ON) + endif() + + string(FIND "${line}" "" find_pos) + if (NOT find_pos EQUAL "-1") + set(have_pch_source_compile ON) + endif() +endforeach() + +if (NOT have_pch_use) + set(RunCMake_TEST_FAILED "Generated project should have the Use block.") + return() +endif() + +if (NOT have_pch_create) + set(RunCMake_TEST_FAILED "Generated project should have the Create block.") + return() +endif() + +if (NOT have_pch_header) + set(RunCMake_TEST_FAILED "Generated project should have the ${pch_header} block.") + return() +endif() + +if (NOT have_force_pch_header) + set(RunCMake_TEST_FAILED "Generated project should have the ${pch_header} block.") + return() +endif() + +if (NOT have_pch_source_compile) + set(RunCMake_TEST_FAILED "Generated project should have the block.") + return() +endif() diff --git a/Tests/RunCMake/VS10Project/VsPrecompileHeaders.cmake b/Tests/RunCMake/VS10Project/VsPrecompileHeaders.cmake new file mode 100644 index 0000000..6d208c9 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsPrecompileHeaders.cmake @@ -0,0 +1,4 @@ +project(VsPrecompileHeaders CXX) + +add_library(tgt SHARED empty.cxx) +target_precompile_headers(tgt PRIVATE stdafx.h) diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index 191f56d..1dfa8b2 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -12,6 +12,7 @@ run_cmake(XcodeObjectNeedsQuote) run_cmake(XcodeOptimizationFlags) run_cmake(XcodePreserveNonOptimizationFlags) run_cmake(XcodePreserveObjcFlag) +run_cmake(XcodePrecompileHeaders) if (NOT XCODE_VERSION VERSION_LESS 6) run_cmake(XcodePlatformFrameworks) endif() diff --git a/Tests/RunCMake/XcodeProject/XcodePrecompileHeaders-check.cmake b/Tests/RunCMake/XcodeProject/XcodePrecompileHeaders-check.cmake new file mode 100644 index 0000000..aa3eafc --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodePrecompileHeaders-check.cmake @@ -0,0 +1,35 @@ +set(pch_header "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/cmake_pch.hxx") + +if(NOT EXISTS "${pch_header}") + set(RunCMake_TEST_FAILED "Generated PCH header ${pch_header} does not exist.") + return() +endif() + +set(tgt_project "${RunCMake_TEST_BINARY_DIR}/XcodePrecompileHeaders.xcodeproj/project.pbxproj") +if (NOT EXISTS "${tgt_project}") + set(RunCMake_TEST_FAILED "Generated project file ${tgt_project} doesn't exist.") + return() +endif() + +file(STRINGS ${tgt_project} tgt_projects_strings) + +foreach(line IN LISTS tgt_projects_strings) + if (line MATCHES "GCC_PRECOMPILE_PREFIX_HEADER = YES;") + set(have_pch_prefix ON) + endif() + + string(FIND "${line}" "GCC_PREFIX_HEADER = \"${pch_header}\";" find_pos) + if (NOT find_pos EQUAL "-1") + set(have_pch_header ON) + endif() +endforeach() + +if (NOT have_pch_prefix) + set(RunCMake_TEST_FAILED "Generated project should have the GCC_PRECOMPILE_PREFIX_HEADER = YES; line.") + return() +endif() + +if (NOT have_pch_header) + set(RunCMake_TEST_FAILED "Generated project should have the GCC_PREFIX_HEADER = \"${pch_header}\"; line.") + return() +endif() diff --git a/Tests/RunCMake/XcodeProject/XcodePrecompileHeaders.cmake b/Tests/RunCMake/XcodeProject/XcodePrecompileHeaders.cmake new file mode 100644 index 0000000..f86bcf4 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodePrecompileHeaders.cmake @@ -0,0 +1,4 @@ +project(XcodePrecompileHeaders CXX) + +add_library(tgt foo.cpp) +target_precompile_headers(tgt PRIVATE stdafx.h) -- cgit v0.12 From 8da78d4efe0e4d0ef8708ecd94cf886c3f7d9ae4 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Wed, 31 Jul 2019 18:54:44 +0200 Subject: Precompile headers: Update documentation --- Help/command/target_precompile_headers.rst | 56 ++++++++++++++++++++++ Help/manual/cmake-commands.7.rst | 1 + Help/manual/cmake-properties.7.rst | 4 ++ Help/manual/cmake-variables.7.rst | 1 + Help/prop_sf/SKIP_PRECOMPILE_HEADERS.rst | 13 +++++ Help/prop_tgt/DISABLE_PRECOMPILE_HEADERS.rst | 8 ++++ Help/prop_tgt/INTERFACE_PRECOMPILE_HEADERS.rst | 14 ++++++ Help/prop_tgt/PRECOMPILE_HEADERS.rst | 12 +++++ Help/release/dev/precompile-headers.rst | 6 +++ Help/variable/CMAKE_DISABLE_PRECOMPILE_HEADERS.rst | 6 +++ 10 files changed, 121 insertions(+) create mode 100644 Help/command/target_precompile_headers.rst create mode 100644 Help/prop_sf/SKIP_PRECOMPILE_HEADERS.rst create mode 100644 Help/prop_tgt/DISABLE_PRECOMPILE_HEADERS.rst create mode 100644 Help/prop_tgt/INTERFACE_PRECOMPILE_HEADERS.rst create mode 100644 Help/prop_tgt/PRECOMPILE_HEADERS.rst create mode 100644 Help/release/dev/precompile-headers.rst create mode 100644 Help/variable/CMAKE_DISABLE_PRECOMPILE_HEADERS.rst diff --git a/Help/command/target_precompile_headers.rst b/Help/command/target_precompile_headers.rst new file mode 100644 index 0000000..3e28265 --- /dev/null +++ b/Help/command/target_precompile_headers.rst @@ -0,0 +1,56 @@ +target_precompile_headers +------------------------- + +Add a list of header files to precompile. + +.. code-block:: cmake + + target_precompile_headers( + [header1...] + [ [header2...] ...]) + +Adds header files to :prop_tgt:`PRECOMPILE_HEADERS` or +:prop_tgt:`INTERFACE_PRECOMPILE_HEADERS` target properties. + +Precompiling header files can speed up compilation by creating a partially +processed version of some header files, and then using that version during +compilations rather than repeatedly parsing the original headers. + +The named ```` must have been created by a command such as +:command:`add_executable` or :command:`add_library` and must not be an +:ref:`ALIAS target `. + +The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to +specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC`` +items will populate the :prop_tgt:`PRECOMPILE_HEADERS` property of +````. ``PUBLIC`` and ``INTERFACE`` items will populate the +:prop_tgt:`INTERFACE_PRECOMPILE_HEADERS` property of ````. +(:ref:`IMPORTED targets ` only support ``INTERFACE`` items.) +Repeated calls for the same ```` append items in the order called. + +Arguments to ``target_precompile_headers`` may use "generator expressions" +with the syntax ``$<...>``. +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. + +.. code-block:: cmake + + target_precompile_headers( + PUBLIC + "project_header.h" + PRIVATE + + ) + +Header files will be double quoted if they are not specified with double +quotes or angle brackets. + +See Also +^^^^^^^^ + +For disabling precompile headers for specific targets there is the +property :prop_tgt:`DISABLE_PRECOMPILE_HEADERS`. + +For skipping certain source files there is the source file property +:prop_sf:`SKIP_PRECOMPILE_HEADERS`. diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index a3bc465..59ba897 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -112,6 +112,7 @@ These commands are available only in CMake projects. /command/target_link_directories /command/target_link_libraries /command/target_link_options + /command/target_precompile_headers /command/target_sources /command/try_compile /command/try_run diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 62d23c7..03f18fc 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -181,6 +181,7 @@ Properties on Targets /prop_tgt/DEFINE_SYMBOL /prop_tgt/DEPLOYMENT_REMOTE_DIRECTORY /prop_tgt/DEPLOYMENT_ADDITIONAL_FILES + /prop_tgt/DISABLE_PRECOMPILE_HEADERS /prop_tgt/DOTNET_TARGET_FRAMEWORK_VERSION /prop_tgt/EchoString /prop_tgt/ENABLE_EXPORTS @@ -240,6 +241,7 @@ Properties on Targets /prop_tgt/INTERFACE_LINK_DIRECTORIES /prop_tgt/INTERFACE_LINK_LIBRARIES /prop_tgt/INTERFACE_LINK_OPTIONS + /prop_tgt/INTERFACE_PRECOMPILE_HEADERS /prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE /prop_tgt/INTERFACE_SOURCES /prop_tgt/INTERFACE_SYSTEM_INCLUDE_DIRECTORIES @@ -295,6 +297,7 @@ Properties on Targets /prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG /prop_tgt/PDB_OUTPUT_DIRECTORY /prop_tgt/POSITION_INDEPENDENT_CODE + /prop_tgt/PRECOMPILE_HEADERS /prop_tgt/PREFIX /prop_tgt/PRIVATE_HEADER /prop_tgt/PROJECT_LABEL @@ -445,6 +448,7 @@ Properties on Source Files /prop_sf/SKIP_AUTOMOC /prop_sf/SKIP_AUTORCC /prop_sf/SKIP_AUTOUIC + /prop_sf/SKIP_PRECOMPILE_HEADERS /prop_sf/Swift_DEPENDENCIES_FILE /prop_sf/Swift_DIAGNOSTICS_FILE /prop_sf/SYMBOLIC diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 9ad1195..668b2a2 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -355,6 +355,7 @@ Variables that Control the Build /variable/CMAKE_CUDA_SEPARABLE_COMPILATION /variable/CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS /variable/CMAKE_DEBUG_POSTFIX + /variable/CMAKE_DISABLE_PRECOMPILE_HEADERS /variable/CMAKE_ENABLE_EXPORTS /variable/CMAKE_EXE_LINKER_FLAGS /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG diff --git a/Help/prop_sf/SKIP_PRECOMPILE_HEADERS.rst b/Help/prop_sf/SKIP_PRECOMPILE_HEADERS.rst new file mode 100644 index 0000000..5f39f30 --- /dev/null +++ b/Help/prop_sf/SKIP_PRECOMPILE_HEADERS.rst @@ -0,0 +1,13 @@ +SKIP_PRECOMPILE_HEADERS +----------------------- + +Is this source file skipped by :prop_tgt:`PRECOMPILE_HEADERS` feature. + +This property helps with build problems that one would run into +when using the :prop_tgt:`PRECOMPILE_HEADERS` feature. + +One example would be the usage of Objective-C (*.m) files, and +Objective-C++ (*.mm) files, which lead to compilation failure +because they are treated (in case of Ninja / Makefile generator) +as C, and CXX respectively. The precompile headers are not +compatible between languages. diff --git a/Help/prop_tgt/DISABLE_PRECOMPILE_HEADERS.rst b/Help/prop_tgt/DISABLE_PRECOMPILE_HEADERS.rst new file mode 100644 index 0000000..4cef023 --- /dev/null +++ b/Help/prop_tgt/DISABLE_PRECOMPILE_HEADERS.rst @@ -0,0 +1,8 @@ +DISABLE_PRECOMPILE_HEADERS +-------------------------- + +Disables the precompilation of header files specified by +:prop_tgt:`PRECOMPILE_HEADERS` property. + +If the property is not set, CMake will use the value provided +by :variable:`CMAKE_DISABLE_PRECOMPILE_HEADERS`. diff --git a/Help/prop_tgt/INTERFACE_PRECOMPILE_HEADERS.rst b/Help/prop_tgt/INTERFACE_PRECOMPILE_HEADERS.rst new file mode 100644 index 0000000..8ff7e8b --- /dev/null +++ b/Help/prop_tgt/INTERFACE_PRECOMPILE_HEADERS.rst @@ -0,0 +1,14 @@ +INTERFACE_PRECOMPILE_HEADERS +---------------------------- + +List of interface header files to precompile into consuming targets. + +Targets may populate this property to publish the header files +for consuming targets to precompile. The :command:`target_precompile_headers` +command populates this property with values given to the ``PUBLIC`` and +``INTERFACE`` keywords. Projects may also get and set the property directly. + +Contents of ``INTERFACE_PRECOMPILE_HEADERS`` may use "generator expressions" +with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` +manual for available expressions. See the :manual:`cmake-buildsystem(7)` +manual for more on defining buildsystem properties. diff --git a/Help/prop_tgt/PRECOMPILE_HEADERS.rst b/Help/prop_tgt/PRECOMPILE_HEADERS.rst new file mode 100644 index 0000000..9e70b65 --- /dev/null +++ b/Help/prop_tgt/PRECOMPILE_HEADERS.rst @@ -0,0 +1,12 @@ +PRECOMPILE_HEADERS +------------------ + +List of header files to precompile. + +This property holds a :ref:`semicolon-separated list ` +of header files to precompile specified so far for its target. +Use the :command:`target_precompile_headers` command to append more header +files. + +This property supports +:manual:`generator expressions `. diff --git a/Help/release/dev/precompile-headers.rst b/Help/release/dev/precompile-headers.rst new file mode 100644 index 0000000..8b62da7 --- /dev/null +++ b/Help/release/dev/precompile-headers.rst @@ -0,0 +1,6 @@ +Precompile Headers +------------------ + +* The :prop_tgt:`PRECOMPILE_HEADERS` target property was added to tell + generators to use a list of precompile headers for faster compilation + times. diff --git a/Help/variable/CMAKE_DISABLE_PRECOMPILE_HEADERS.rst b/Help/variable/CMAKE_DISABLE_PRECOMPILE_HEADERS.rst new file mode 100644 index 0000000..7c30ede --- /dev/null +++ b/Help/variable/CMAKE_DISABLE_PRECOMPILE_HEADERS.rst @@ -0,0 +1,6 @@ +CMAKE_DISABLE_PRECOMPILE_HEADERS +-------------------------------- + +Default value for :prop_tgt:`DISABLE_PRECOMPILE_HEADERS` of targets. + +By default ``CMAKE_DISABLE_PRECOMPILE_HEADERS`` is ``OFF``. -- cgit v0.12