diff options
author | Brad King <brad.king@kitware.com> | 2019-08-29 13:37:26 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2019-08-29 13:38:21 (GMT) |
commit | fa36e2151d25358c7946a53c4440f0487210770d (patch) | |
tree | 8909e40db9d7a8c54ea047d5ea6d92f2592a3264 /Source/cmGeneratorTarget.cxx | |
parent | 030570d71ff8b15a7242203f2638d3b77af755b9 (diff) | |
parent | 8da78d4efe0e4d0ef8708ecd94cf886c3f7d9ae4 (diff) | |
download | CMake-fa36e2151d25358c7946a53c4440f0487210770d.zip CMake-fa36e2151d25358c7946a53c4440f0487210770d.tar.gz CMake-fa36e2151d25358c7946a53c4440f0487210770d.tar.bz2 |
Merge topic 'precompile-headers'
8da78d4efe Precompile headers: Update documentation
5772930164 Precompile headers: Add unit tests
519606704e Precompile headers: Add support for Visual Studio generators
28be170fbc Precompile headers: Add support for Xcode generator
b8626261e9 Precompile headers: Add methods to generate PCH sources
375d01c680 PCH: add example/test
9b6797e71d PCH: add target_precompile_headers command
0467a2f91b PCH: add PRECOMPILE_HEADERS to special properties
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Daniel Pfeifer <daniel@pfeifer-mail.de>
Acked-by: Ivan171 <heavenandhell171@gmail.com>
Acked-by: Stanislav Ershov <digital.stream.of.mind@gmail.com>
Acked-by: Steve Mokris <smokris@softpixel.com>
Acked-by: Evgeniy Dushistov <dushistov@mail.ru>
Acked-by: Danila Malyutin <flashmozzg@gmail.com>
Acked-by: Viktor Kirilov <vik.kirilov@gmail.com>
Acked-by: Lucas Zhao <zhaopf6@163.com>
Merge-request: !3553
Diffstat (limited to 'Source/cmGeneratorTarget.cxx')
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 1d64f1c..cc37232 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" @@ -278,6 +279,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) , DebugCompileDefinitionsDone(false) , DebugLinkOptionsDone(false) , DebugLinkDirectoriesDone(false) + , DebugPrecompileHeadersDone(false) , DebugSourcesDone(false) , LinkImplementationLanguageIsContextDependent(true) , UtilityItemsDone(false) @@ -312,6 +314,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 +333,7 @@ cmGeneratorTarget::~cmGeneratorTarget() cmDeleteAll(this->CompileDefinitionsEntries); cmDeleteAll(this->LinkOptionsEntries); cmDeleteAll(this->LinkDirectoriesEntries); + cmDeleteAll(this->PrecompileHeadersEntries); cmDeleteAll(this->SourceEntries); cmDeleteAll(this->LinkInformation); } @@ -3312,6 +3319,152 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( return list; } +std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders( + const std::string& config, const std::string& language) const +{ + std::unordered_set<std::string> uniqueOptions; + + cmGeneratorExpressionDAGChecker dagChecker(this, "PRECOMPILE_HEADERS", + nullptr, nullptr); + + std::vector<std::string> 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<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->PrecompileHeadersEntries); + + AddInterfaceEntries(this, config, "INTERFACE_PRECOMPILE_HEADERS", language, + &dagChecker, entries); + + std::vector<BT<std::string>> list; + processOptions(this, entries, list, uniqueOptions, debugDefines, + "precompile headers", OptionsParse::None); + + 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<BT<std::string>> 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<std::string>& result, const std::string& config, const std::string& language) const |