diff options
author | Brad King <brad.king@kitware.com> | 2020-07-16 14:17:39 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2020-07-16 14:17:52 (GMT) |
commit | 4662c041eac50888d445a77ed091f395cafe61fe (patch) | |
tree | cfceaeab6d6407a1b86f9ddb5c7168cb6a68db15 | |
parent | ffb888b7487b4e9df3465d264428bb5458854326 (diff) | |
parent | 56cf509a72588d3aa2b169a1eb59ae1cdee9157c (diff) | |
download | CMake-4662c041eac50888d445a77ed091f395cafe61fe.zip CMake-4662c041eac50888d445a77ed091f395cafe61fe.tar.gz CMake-4662c041eac50888d445a77ed091f395cafe61fe.tar.bz2 |
Merge topic 'move_more_queries_to_cmStandardLevelResolver'
56cf509a72 Move AddCompilerRequirementFlag to cmStandardLevelResolver
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !4989
-rw-r--r-- | Source/cmLocalGenerator.cxx | 147 | ||||
-rw-r--r-- | Source/cmStandardLevelResolver.cxx | 159 | ||||
-rw-r--r-- | Source/cmStandardLevelResolver.h | 4 | ||||
-rw-r--r-- | Tests/RunCMake/try_compile/CudaStandard-stderr.txt | 2 | ||||
-rw-r--r-- | Tests/RunCMake/try_compile/CudaStandard.cmake | 2 |
5 files changed, 161 insertions, 153 deletions
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index af9c1b4..fe0d0a7 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2156,152 +2156,17 @@ void cmLocalGenerator::AddCompilerRequirementFlag( std::string& flags, cmGeneratorTarget const* target, const std::string& lang, const std::string& config) { - if (lang.empty()) { - return; - } - const char* defaultStd = - this->Makefile->GetDefinition("CMAKE_" + lang + "_STANDARD_DEFAULT"); - if (!defaultStd || !*defaultStd) { - // This compiler has no notion of language standard levels. - return; - } - bool ext = true; - if (cmProp extPropValue = target->GetLanguageExtensions(lang)) { - if (cmIsOff(*extPropValue)) { - ext = false; - } - } - cmProp standardProp = target->GetLanguageStandard(lang, config); - if (!standardProp) { - if (ext) { - // No language standard is specified and extensions are not disabled. - // Check if this compiler needs a flag to enable extensions. - std::string const option_flag = - "CMAKE_" + lang + "_EXTENSION_COMPILE_OPTION"; - if (const char* opt = - target->Target->GetMakefile()->GetDefinition(option_flag)) { - std::vector<std::string> optVec = cmExpandedList(opt); - for (std::string const& i : optVec) { - this->AppendFlagEscape(flags, i); - } - } - } - return; - } - - std::string const type = ext ? "EXTENSION" : "STANDARD"; - - if (target->GetLanguageStandardRequired(lang)) { - std::string option_flag = - "CMAKE_" + lang + *standardProp + "_" + type + "_COMPILE_OPTION"; - - const char* opt = - target->Target->GetMakefile()->GetDefinition(option_flag); - if (!opt) { - std::ostringstream e; - e << "Target \"" << target->GetName() - << "\" requires the language " - "dialect \"" - << lang << *standardProp << "\" " - << (ext ? "(with compiler extensions)" : "") - << ", but CMake " - "does not know the compile flags to use to enable it."; - this->IssueMessage(MessageType::FATAL_ERROR, e.str()); - } else { - std::vector<std::string> optVec = cmExpandedList(opt); - for (std::string const& i : optVec) { - this->AppendFlagEscape(flags, i); - } - } - return; - } - - static std::map<std::string, std::vector<std::string>> langStdMap; - if (langStdMap.empty()) { - // Maintain sorted order, most recent first. - langStdMap["CXX"].emplace_back("20"); - langStdMap["CXX"].emplace_back("17"); - langStdMap["CXX"].emplace_back("14"); - langStdMap["CXX"].emplace_back("11"); - langStdMap["CXX"].emplace_back("98"); - - langStdMap["OBJCXX"].emplace_back("20"); - langStdMap["OBJCXX"].emplace_back("17"); - langStdMap["OBJCXX"].emplace_back("14"); - langStdMap["OBJCXX"].emplace_back("11"); - langStdMap["OBJCXX"].emplace_back("98"); - - langStdMap["C"].emplace_back("11"); - langStdMap["C"].emplace_back("99"); - langStdMap["C"].emplace_back("90"); - - langStdMap["OBJC"].emplace_back("11"); - langStdMap["OBJC"].emplace_back("99"); - langStdMap["OBJC"].emplace_back("90"); - - langStdMap["CUDA"].emplace_back("20"); - langStdMap["CUDA"].emplace_back("17"); - langStdMap["CUDA"].emplace_back("14"); - langStdMap["CUDA"].emplace_back("11"); - langStdMap["CUDA"].emplace_back("03"); - } - - std::string standard(*standardProp); - if (lang == "CUDA" && standard == "98") { - standard = "03"; - } - std::vector<std::string>& stds = langStdMap[lang]; - - auto stdIt = std::find(stds.begin(), stds.end(), standard); - if (stdIt == stds.end()) { - - std::string e = - lang + "_STANDARD is set to invalid value '" + standard + "'"; - this->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - MessageType::FATAL_ERROR, e, target->GetBacktrace()); - return; - } - - auto defaultStdIt = std::find(stds.begin(), stds.end(), defaultStd); - if (defaultStdIt == stds.end()) { - std::string e = "CMAKE_" + lang + - "_STANDARD_DEFAULT is set to invalid value '" + std::string(defaultStd) + - "'"; - this->IssueMessage(MessageType::INTERNAL_ERROR, e); - return; - } - - // If the standard requested is older than the compiler's default - // then we need to use a flag to change it. The comparison is - // greater-or-equal because the standards are stored in backward - // chronological order. - if (stdIt >= defaultStdIt) { - std::string option_flag = - "CMAKE_" + lang + *stdIt + "_" + type + "_COMPILE_OPTION"; - - std::string const& opt = - target->Target->GetMakefile()->GetRequiredDefinition(option_flag); - std::vector<std::string> optVec = cmExpandedList(opt); - for (std::string const& i : optVec) { - this->AppendFlagEscape(flags, i); - } - return; - } - - // The standard requested is at least as new as the compiler's default, - // and the standard request is not required. Decay to the newest standard - // for which a flag is defined. - for (; stdIt < defaultStdIt; ++stdIt) { - std::string option_flag = - cmStrCat("CMAKE_", lang, *stdIt, "_", type, "_COMPILE_OPTION"); + cmStandardLevelResolver standardResolver(this->Makefile); - if (const char* opt = - target->Target->GetMakefile()->GetDefinition(option_flag)) { + std::string const& optionFlagDef = + standardResolver.GetCompileOptionDef(target, lang, config); + if (!optionFlagDef.empty()) { + auto opt = target->Target->GetMakefile()->GetDefinition(optionFlagDef); + if (opt) { std::vector<std::string> optVec = cmExpandedList(opt); for (std::string const& i : optVec) { this->AppendFlagEscape(flags, i); } - return; } } } diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 096ae9d..0eb869c 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -7,6 +7,7 @@ #include <cassert> #include <cstddef> #include <sstream> +#include <stdexcept> #include <unordered_map> #include <utility> #include <vector> @@ -45,10 +46,126 @@ struct StandardNeeded struct StanardLevelComputer { - explicit StanardLevelComputer(std::string lang, std::vector<int> levels) + explicit StanardLevelComputer(std::string lang, std::vector<int> levels, + std::vector<std::string> levelsStr) : Language(std::move(lang)) , Levels(std::move(levels)) + , LevelsAsStrings(std::move(levelsStr)) { + assert(levels.size() == levelsStr.size()); + } + + std::string GetCompileOptionDef(cmMakefile* makefile, + cmGeneratorTarget const* target, + std::string const& config) const + { + + const auto& stds = this->Levels; + const auto& stdsStrings = this->LevelsAsStrings; + + const char* defaultStd = makefile->GetDefinition( + cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT")); + if (!defaultStd || !*defaultStd) { + // this compiler has no notion of language standard levels + return std::string{}; + } + + bool ext = true; + if (cmProp extPropValue = target->GetLanguageExtensions(this->Language)) { + if (cmIsOff(*extPropValue)) { + ext = false; + } + } + + cmProp standardProp = target->GetLanguageStandard(this->Language, config); + if (!standardProp) { + if (ext) { + // No language standard is specified and extensions are not disabled. + // Check if this compiler needs a flag to enable extensions. + return cmStrCat("CMAKE_", this->Language, "_EXTENSION_COMPILE_OPTION"); + } + return std::string{}; + } + + std::string const type = ext ? "EXTENSION" : "STANDARD"; + + if (target->GetLanguageStandardRequired(this->Language)) { + std::string option_flag = cmStrCat( + "CMAKE_", this->Language, *standardProp, "_", type, "_COMPILE_OPTION"); + + const char* opt = + target->Target->GetMakefile()->GetDefinition(option_flag); + if (!opt) { + std::ostringstream e; + e << "Target \"" << target->GetName() + << "\" requires the language " + "dialect \"" + << this->Language << *standardProp << "\" " + << (ext ? "(with compiler extensions)" : "") + << ", but CMake " + "does not know the compile flags to use to enable it."; + makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + } + return option_flag; + } + + std::string standardStr(*standardProp); + if (this->Language == "CUDA" && standardStr == "98") { + standardStr = "03"; + } + + int standardValue = -1; + int defaultValue = -1; + try { + standardValue = std::stoi(standardStr); + defaultValue = std::stoi(defaultStd); + } catch (std::invalid_argument&) { + // fall through as we want an error + // when we can't find the bad value in the `stds` vector + } + + auto stdIt = std::find(cm::cbegin(stds), cm::cend(stds), standardValue); + if (stdIt == cm::cend(stds)) { + std::string e = + cmStrCat(this->Language, "_STANDARD is set to invalid value '", + standardStr, "'"); + makefile->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e, + target->GetBacktrace()); + return std::string{}; + } + + auto defaultStdIt = + std::find(cm::cbegin(stds), cm::cend(stds), defaultValue); + if (defaultStdIt == cm::cend(stds)) { + std::string e = cmStrCat("CMAKE_", this->Language, + "_STANDARD_DEFAULT is set to invalid value '", + defaultStd, "'"); + makefile->IssueMessage(MessageType::INTERNAL_ERROR, e); + return std::string{}; + } + + // If the standard requested is older than the compiler's default + // then we need to use a flag to change it. + if (stdIt <= defaultStdIt) { + auto offset = std::distance(cm::cbegin(stds), stdIt); + return cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type, + "_COMPILE_OPTION"); + } + + // The standard requested is at least as new as the compiler's default, + // and the standard request is not required. Decay to the newest standard + // for which a flag is defined. + for (; defaultStdIt < stdIt; --stdIt) { + auto offset = std::distance(cm::cbegin(stds), stdIt); + std::string option_flag = + cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type, + "_COMPILE_OPTION"); + if (target->Target->GetMakefile()->GetDefinition(option_flag)) { + return option_flag; + } + } + + return std::string{}; } bool GetNewRequiredStandard(cmMakefile* makefile, @@ -99,7 +216,7 @@ struct StanardLevelComputer // the needed C++ features. if (existingLevelIter == cm::cend(this->Levels) || existingLevelIter < this->Levels.begin() + needed.index) { - newRequiredStandard = std::to_string(this->Levels[needed.index]); + newRequiredStandard = this->LevelsAsStrings[needed.index]; } } @@ -163,8 +280,8 @@ struct StanardLevelComputer std::string prefix = cmStrCat("CMAKE_", this->Language); StandardNeeded maxLevel = { -1, -1 }; for (size_t i = 0; i < this->Levels.size(); ++i) { - if (const char* prop = makefile->GetDefinition(cmStrCat( - prefix, std::to_string(this->Levels[i]), "_COMPILE_FEATURES"))) { + if (const char* prop = makefile->GetDefinition( + cmStrCat(prefix, this->LevelsAsStrings[i], "_COMPILE_FEATURES"))) { std::vector<std::string> props = cmExpandedList(prop); if (cm::contains(props, feature)) { maxLevel = { static_cast<int>(i), this->Levels[i] }; @@ -185,22 +302,44 @@ struct StanardLevelComputer std::string Language; std::vector<int> Levels; + std::vector<std::string> LevelsAsStrings; }; std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping = { - { "C", StanardLevelComputer{ "C", std::vector<int>{ 90, 99, 11 } } }, + { "C", + StanardLevelComputer{ "C", std::vector<int>{ 90, 99, 11 }, + std::vector<std::string>{ "90", "99", "11" } } }, { "CXX", - StanardLevelComputer{ "CXX", std::vector<int>{ 98, 11, 14, 17, 20 } } }, + StanardLevelComputer{ + "CXX", std::vector<int>{ 98, 11, 14, 17, 20 }, + std::vector<std::string>{ "98", "11", "14", "17", "20" } } }, { "CUDA", - StanardLevelComputer{ "CUDA", std::vector<int>{ 03, 11, 14, 17, 20 } } }, - { "OBJC", StanardLevelComputer{ "OBJC", std::vector<int>{ 90, 99, 11 } } }, + StanardLevelComputer{ + "CUDA", std::vector<int>{ 03, 11, 14, 17, 20 }, + std::vector<std::string>{ "03", "11", "14", "17", "20" } } }, + { "OBJC", + StanardLevelComputer{ "OBJC", std::vector<int>{ 90, 99, 11 }, + std::vector<std::string>{ "90", "99", "11" } } }, { "OBJCXX", - StanardLevelComputer{ "OBJCXX", - std::vector<int>{ 98, 11, 14, 17, 20 } } }, + StanardLevelComputer{ + "OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20 }, + std::vector<std::string>{ "98", "11", "14", "17", "20" } } }, }; } +std::string cmStandardLevelResolver::GetCompileOptionDef( + cmGeneratorTarget const* target, std::string const& lang, + std::string const& config) const +{ + const auto& mapping = StandardComputerMapping.find(lang); + if (mapping == cm::cend(StandardComputerMapping)) { + return std::string{}; + } + + return mapping->second.GetCompileOptionDef(this->Makefile, target, config); +} + bool cmStandardLevelResolver::AddRequiredTargetFeature( cmTarget* target, const std::string& feature, std::string* error) const { diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h index 193c053..959a5f9 100644 --- a/Source/cmStandardLevelResolver.h +++ b/Source/cmStandardLevelResolver.h @@ -20,6 +20,10 @@ public: { } + std::string GetCompileOptionDef(cmGeneratorTarget const* target, + std::string const& lang, + std::string const& config) const; + bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature, std::string* error = nullptr) const; diff --git a/Tests/RunCMake/try_compile/CudaStandard-stderr.txt b/Tests/RunCMake/try_compile/CudaStandard-stderr.txt index 3c6bdf6..bcf95d5 100644 --- a/Tests/RunCMake/try_compile/CudaStandard-stderr.txt +++ b/Tests/RunCMake/try_compile/CudaStandard-stderr.txt @@ -1,5 +1,5 @@ ^CMake Error at .*/Tests/RunCMake/try_compile/CudaStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\): - CUDA_STANDARD is set to invalid value '3' + CUDA_STANDARD is set to invalid value '4' + CMake Error at CudaStandard.cmake:[0-9]+ \(try_compile\): Failed to generate test project build system. diff --git a/Tests/RunCMake/try_compile/CudaStandard.cmake b/Tests/RunCMake/try_compile/CudaStandard.cmake index 96da422..a230424 100644 --- a/Tests/RunCMake/try_compile/CudaStandard.cmake +++ b/Tests/RunCMake/try_compile/CudaStandard.cmake @@ -1,7 +1,7 @@ enable_language(CUDA) try_compile(result ${CMAKE_CURRENT_BINARY_DIR} SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cu - CUDA_STANDARD 3 + CUDA_STANDARD 4 OUTPUT_VARIABLE out ) message("try_compile output:\n${out}") |