diff options
Diffstat (limited to 'Source/cmGeneratorTarget.cxx')
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 157 |
1 files changed, 155 insertions, 2 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 3048c5f..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); } @@ -1593,7 +1600,7 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, kind = SourceKindHeader; } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { kind = SourceKindExternalObject; - } else if (!sf->GetLanguage().empty()) { + } else if (!sf->GetOrDetermineLanguage().empty()) { kind = SourceKindObjectSource; } else if (ext == "def") { kind = SourceKindModuleDefinition; @@ -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 @@ -6055,7 +6208,7 @@ void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages, std::vector<cmSourceFile*> sourceFiles; this->GetSourceFiles(sourceFiles, config); for (cmSourceFile* src : sourceFiles) { - const std::string& lang = src->GetLanguage(); + const std::string& lang = src->GetOrDetermineLanguage(); if (!lang.empty()) { languages.insert(lang); } |