From eb534ea5cb1d52dfa1a2f8c31aa388d511474c0d Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 4 Oct 2023 16:55:01 -0400 Subject: Tests: Modernize name of RunCMake.CXXModules compiler inspection case We use the case name `Inspect` for similar purposes in other tests. --- Tests/RunCMake/CXXModules/Inspect.cmake | 28 ++++++++++++++++++++++ Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 4 ++-- .../CXXModules/compiler_introspection.cmake | 28 ---------------------- 3 files changed, 30 insertions(+), 30 deletions(-) create mode 100644 Tests/RunCMake/CXXModules/Inspect.cmake delete mode 100644 Tests/RunCMake/CXXModules/compiler_introspection.cmake diff --git a/Tests/RunCMake/CXXModules/Inspect.cmake b/Tests/RunCMake/CXXModules/Inspect.cmake new file mode 100644 index 0000000..8c74940 --- /dev/null +++ b/Tests/RunCMake/CXXModules/Inspect.cmake @@ -0,0 +1,28 @@ +enable_language(CXX) + +set(info "") + +# See `Modules/Compiler/MSVC-CXX.cmake` for this. If there is explicitly no +# default, the feature list is populated to be everything. +if (DEFINED CMAKE_CXX_STANDARD_DEFAULT AND + CMAKE_CXX_STANDARD_DEFAULT STREQUAL "") + set(CMAKE_CXX_COMPILE_FEATURES "") +endif () + +# Detect if the environment forces a C++ standard, let the test selection know. +set(forced_cxx_standard 0) +if (CMAKE_CXX_FLAGS MATCHES "-std=") + set(forced_cxx_standard 1) +endif () + +# Forward information about the C++ compile features. +string(APPEND info "\ +set(CMAKE_CXX_COMPILE_FEATURES \"${CMAKE_CXX_COMPILE_FEATURES}\") +set(CMAKE_MAKE_PROGRAM \"${CMAKE_MAKE_PROGRAM}\") +set(forced_cxx_standard \"${forced_cxx_standard}\") +set(CMAKE_CXX_COMPILER_VERSION \"${CMAKE_CXX_COMPILER_VERSION}\") +set(CMAKE_CXX_OUTPUT_EXTENSION \"${CMAKE_CXX_OUTPUT_EXTENSION}\") +set(CXXModules_default_build_type \"${CMAKE_BUILD_TYPE}\") +") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}") diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 8b22687..dd18d20 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -3,8 +3,8 @@ include(RunCMake) # For `if (IN_LIST)` cmake_policy(SET CMP0057 NEW) -run_cmake(compiler_introspection) -include("${RunCMake_BINARY_DIR}/compiler_introspection-build/info.cmake") +run_cmake(Inspect) +include("${RunCMake_BINARY_DIR}/Inspect-build/info.cmake") # Test negative cases where C++20 modules do not work. run_cmake(NoCXX) diff --git a/Tests/RunCMake/CXXModules/compiler_introspection.cmake b/Tests/RunCMake/CXXModules/compiler_introspection.cmake deleted file mode 100644 index 8c74940..0000000 --- a/Tests/RunCMake/CXXModules/compiler_introspection.cmake +++ /dev/null @@ -1,28 +0,0 @@ -enable_language(CXX) - -set(info "") - -# See `Modules/Compiler/MSVC-CXX.cmake` for this. If there is explicitly no -# default, the feature list is populated to be everything. -if (DEFINED CMAKE_CXX_STANDARD_DEFAULT AND - CMAKE_CXX_STANDARD_DEFAULT STREQUAL "") - set(CMAKE_CXX_COMPILE_FEATURES "") -endif () - -# Detect if the environment forces a C++ standard, let the test selection know. -set(forced_cxx_standard 0) -if (CMAKE_CXX_FLAGS MATCHES "-std=") - set(forced_cxx_standard 1) -endif () - -# Forward information about the C++ compile features. -string(APPEND info "\ -set(CMAKE_CXX_COMPILE_FEATURES \"${CMAKE_CXX_COMPILE_FEATURES}\") -set(CMAKE_MAKE_PROGRAM \"${CMAKE_MAKE_PROGRAM}\") -set(forced_cxx_standard \"${forced_cxx_standard}\") -set(CMAKE_CXX_COMPILER_VERSION \"${CMAKE_CXX_COMPILER_VERSION}\") -set(CMAKE_CXX_OUTPUT_EXTENSION \"${CMAKE_CXX_OUTPUT_EXTENSION}\") -set(CXXModules_default_build_type \"${CMAKE_BUILD_TYPE}\") -") - -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}") -- cgit v0.12 From 73a1d422a54fb62c429578429e146081307300bc Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 4 Oct 2023 12:28:28 -0400 Subject: cmStandardLevelResolver: Mark builtin language standards table as const --- Source/cmStandardLevelResolver.cxx | 58 ++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index de42bc6..50389b5 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -476,37 +476,33 @@ struct StandardLevelComputer std::vector LevelsAsStrings; }; -std::unordered_map - StandardComputerMapping = { - { "C", - StandardLevelComputer{ - "C", std::vector{ 90, 99, 11, 17, 23 }, - std::vector{ "90", "99", "11", "17", "23" } } }, - { "CXX", - StandardLevelComputer{ "CXX", - std::vector{ 98, 11, 14, 17, 20, 23, 26 }, - std::vector{ "98", "11", "14", "17", - "20", "23", "26" } } }, - { "CUDA", - StandardLevelComputer{ "CUDA", - std::vector{ 03, 11, 14, 17, 20, 23, 26 }, - std::vector{ "03", "11", "14", "17", - "20", "23", "26" } } }, - { "OBJC", - StandardLevelComputer{ - "OBJC", std::vector{ 90, 99, 11, 17, 23 }, - std::vector{ "90", "99", "11", "17", "23" } } }, - { "OBJCXX", - StandardLevelComputer{ "OBJCXX", - std::vector{ 98, 11, 14, 17, 20, 23, 26 }, - std::vector{ "98", "11", "14", "17", - "20", "23", "26" } } }, - { "HIP", - StandardLevelComputer{ "HIP", - std::vector{ 98, 11, 14, 17, 20, 23, 26 }, - std::vector{ "98", "11", "14", "17", - "20", "23", "26" } } } - }; +std::unordered_map const StandardComputerMapping = { + { "C", + StandardLevelComputer{ + "C", std::vector{ 90, 99, 11, 17, 23 }, + std::vector{ "90", "99", "11", "17", "23" } } }, + { "CXX", + StandardLevelComputer{ + "CXX", std::vector{ 98, 11, 14, 17, 20, 23, 26 }, + std::vector{ "98", "11", "14", "17", "20", "23", "26" } } }, + { "CUDA", + StandardLevelComputer{ + "CUDA", std::vector{ 03, 11, 14, 17, 20, 23, 26 }, + std::vector{ "03", "11", "14", "17", "20", "23", "26" } } }, + { "OBJC", + StandardLevelComputer{ + "OBJC", std::vector{ 90, 99, 11, 17, 23 }, + std::vector{ "90", "99", "11", "17", "23" } } }, + { "OBJCXX", + StandardLevelComputer{ + "OBJCXX", std::vector{ 98, 11, 14, 17, 20, 23, 26 }, + std::vector{ "98", "11", "14", "17", "20", "23", "26" } } }, + { "HIP", + StandardLevelComputer{ + "HIP", std::vector{ 98, 11, 14, 17, 20, 23, 26 }, + std::vector{ "98", "11", "14", "17", "20", "23", "26" } } } +}; } std::string cmStandardLevelResolver::GetCompileOptionDef( -- cgit v0.12 From fdd81a609a5f581d0bf6f935d3580377361a4b31 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 4 Oct 2023 13:24:27 -0400 Subject: cmStandardLevelResolver: Clarify local variable name --- Source/cmStandardLevelResolver.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 50389b5..469bef8 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -553,14 +553,14 @@ bool cmStandardLevelResolver::AddRequiredTargetFeature( // code put in these properties explicitly. That is mostly true now, // but for compatibility we need to continue updating the property here. std::string newRequiredStandard; - bool newRequired = this->GetNewRequiredStandard( + bool succeeded = this->GetNewRequiredStandard( target->GetName(), feature, target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard, error); if (!newRequiredStandard.empty()) { target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard); } - return newRequired; + return succeeded; } bool cmStandardLevelResolver::CheckCompileFeaturesAvailable( -- cgit v0.12 From 99fa01d3faa70f1e214acd56ce25002ae310c51d Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 4 Oct 2023 13:38:01 -0400 Subject: cmStandardLevelResolver: Factor out public representation of level --- Source/CMakeLists.txt | 1 + Source/cmStandardLevel.h | 21 +++++++++++++++++++++ Source/cmStandardLevelResolver.cxx | 32 +++++++++++++++----------------- 3 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 Source/cmStandardLevel.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 37d407b..1bc855e 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -417,6 +417,7 @@ add_library( cmSourceFileLocationKind.h cmSourceGroup.cxx cmSourceGroup.h + cmStandardLevel.h cmStandardLevelResolver.cxx cmStandardLevelResolver.h cmState.cxx diff --git a/Source/cmStandardLevel.h b/Source/cmStandardLevel.h new file mode 100644 index 0000000..86d178b --- /dev/null +++ b/Source/cmStandardLevel.h @@ -0,0 +1,21 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +class cmStandardLevel +{ + size_t index_; + +public: + cmStandardLevel(size_t index) + : index_(index) + { + } + size_t Index() const { return index_; } + friend bool operator<(cmStandardLevel const& l, cmStandardLevel const& r) + { + return l.index_ < r.index_; + } +}; diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 469bef8..41dd316 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmStandardLevel.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" #include "cmValue.h" @@ -46,12 +48,6 @@ const char* const HIP_FEATURES[] = { nullptr FOR_EACH_HIP_FEATURE( FEATURE_STRING) }; #undef FEATURE_STRING -struct StandardNeeded -{ - int index; - int value; -}; - int ParseStd(std::string const& level) { try { @@ -352,7 +348,8 @@ struct StandardLevelComputer newRequiredStandard.clear(); } - auto needed = this->HighestStandardNeeded(makefile, feature); + cm::optional needed = + this->HighestStandardNeeded(makefile, feature); cmValue existingStandard = currentLangStandardValue; if (!existingStandard) { @@ -382,12 +379,12 @@ struct StandardLevelComputer } } - if (needed.index != -1) { + if (needed) { // Ensure the C++ language level is high enough to support // the needed C++ features. if (existingLevelIter == cm::cend(this->Levels) || - existingLevelIter < this->Levels.begin() + needed.index) { - newRequiredStandard = this->LevelsAsStrings[needed.index]; + existingLevelIter < this->Levels.begin() + needed->Index()) { + newRequiredStandard = this->LevelsAsStrings[needed->Index()]; } } @@ -439,23 +436,24 @@ struct StandardLevelComputer return false; } - auto needed = this->HighestStandardNeeded(makefile, feature); + cm::optional needed = + this->HighestStandardNeeded(makefile, feature); - return (needed.index == -1) || - (this->Levels.begin() + needed.index) <= existingLevelIter; + return !needed || + (this->Levels.begin() + needed->Index()) <= existingLevelIter; } - StandardNeeded HighestStandardNeeded(cmMakefile* makefile, - std::string const& feature) const + cm::optional HighestStandardNeeded( + cmMakefile* makefile, std::string const& feature) const { std::string prefix = cmStrCat("CMAKE_", this->Language); - StandardNeeded maxLevel = { -1, -1 }; + cm::optional maxLevel; for (size_t i = 0; i < this->Levels.size(); ++i) { if (cmValue prop = makefile->GetDefinition( cmStrCat(prefix, this->LevelsAsStrings[i], "_COMPILE_FEATURES"))) { cmList props{ *prop }; if (cm::contains(props, feature)) { - maxLevel = { static_cast(i), this->Levels[i] }; + maxLevel = cmStandardLevel(i); } } } -- cgit v0.12 From 7519001ae6cf9da781da465c561870680f3c955d Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 4 Oct 2023 13:59:10 -0400 Subject: cmStandardLevelResolver: Add method to get feature standard level --- Source/cmStandardLevelResolver.cxx | 17 ++++++++++++++--- Source/cmStandardLevelResolver.h | 6 ++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 41dd316..a24d480 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -349,7 +349,7 @@ struct StandardLevelComputer } cm::optional needed = - this->HighestStandardNeeded(makefile, feature); + this->CompileFeatureStandardLevel(makefile, feature); cmValue existingStandard = currentLangStandardValue; if (!existingStandard) { @@ -437,13 +437,13 @@ struct StandardLevelComputer } cm::optional needed = - this->HighestStandardNeeded(makefile, feature); + this->CompileFeatureStandardLevel(makefile, feature); return !needed || (this->Levels.begin() + needed->Index()) <= existingLevelIter; } - cm::optional HighestStandardNeeded( + cm::optional CompileFeatureStandardLevel( cmMakefile* makefile, std::string const& feature) const { std::string prefix = cmStrCat("CMAKE_", this->Language); @@ -652,6 +652,17 @@ bool cmStandardLevelResolver::CompileFeatureKnown( return false; } +cm::optional +cmStandardLevelResolver::CompileFeatureStandardLevel( + std::string const& lang, std::string const& feature) const +{ + auto mapping = StandardComputerMapping.find(lang); + if (mapping == cm::cend(StandardComputerMapping)) { + return cm::nullopt; + } + return mapping->second.CompileFeatureStandardLevel(this->Makefile, feature); +} + cmValue cmStandardLevelResolver::CompileFeaturesAvailable( const std::string& lang, std::string* error) const { diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h index 03adf3f..2dd978c 100644 --- a/Source/cmStandardLevelResolver.h +++ b/Source/cmStandardLevelResolver.h @@ -4,10 +4,13 @@ #include +#include + #include "cmValue.h" class cmMakefile; class cmGeneratorTarget; +class cmStandardLevel; class cmTarget; class cmStandardLevelResolver @@ -33,6 +36,9 @@ public: const std::string& feature, std::string& lang, std::string* error) const; + cm::optional CompileFeatureStandardLevel( + std::string const& lang, std::string const& feature) const; + cmValue CompileFeaturesAvailable(const std::string& lang, std::string* error) const; -- cgit v0.12 From 23b57462aa5865d1e526c40dfd0f04f6a4af9e25 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 4 Oct 2023 14:28:45 -0400 Subject: cmStandardLevelResolver: Report feature std level from GetNewRequiredStandard Regardless of whether the feature requires a new (higher) standard level, always report the standard level that the feature needs. --- Source/cmGeneratorTarget.cxx | 4 +++- Source/cmStandardLevelResolver.cxx | 25 +++++++++++++------------ Source/cmStandardLevelResolver.h | 1 + 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 422d927..2454750 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -50,6 +50,7 @@ #include "cmSourceFileLocation.h" #include "cmSourceFileLocationKind.h" #include "cmSourceGroup.h" +#include "cmStandardLevel.h" #include "cmStandardLevelResolver.h" #include "cmState.h" #include "cmStringAlgorithms.h" @@ -5039,10 +5040,11 @@ bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang); cmValue currentLanguageStandard = this->GetLanguageStandard(lang, config); + cm::optional featureLevel; std::string newRequiredStandard; if (!standardResolver.GetNewRequiredStandard( this->Target->GetName(), f.Value, currentLanguageStandard, - newRequiredStandard)) { + featureLevel, newRequiredStandard)) { return false; } diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index a24d480..4a149e0 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -337,7 +337,7 @@ struct StandardLevelComputer bool GetNewRequiredStandard(cmMakefile* makefile, std::string const& targetName, - const std::string& feature, + cm::optional featureLevel, cmValue currentLangStandardValue, std::string& newRequiredStandard, std::string* error) const @@ -348,9 +348,6 @@ struct StandardLevelComputer newRequiredStandard.clear(); } - cm::optional needed = - this->CompileFeatureStandardLevel(makefile, feature); - cmValue existingStandard = currentLangStandardValue; if (!existingStandard) { cmValue defaultStandard = makefile->GetDefinition( @@ -379,12 +376,12 @@ struct StandardLevelComputer } } - if (needed) { + if (featureLevel) { // Ensure the C++ language level is high enough to support // the needed C++ features. if (existingLevelIter == cm::cend(this->Levels) || - existingLevelIter < this->Levels.begin() + needed->Index()) { - newRequiredStandard = this->LevelsAsStrings[needed->Index()]; + existingLevelIter < this->Levels.begin() + featureLevel->Index()) { + newRequiredStandard = this->LevelsAsStrings[featureLevel->Index()]; } } @@ -550,11 +547,12 @@ bool cmStandardLevelResolver::AddRequiredTargetFeature( // should be done purely at generate time based on whatever the project // code put in these properties explicitly. That is mostly true now, // but for compatibility we need to continue updating the property here. + cm::optional featureLevel; std::string newRequiredStandard; bool succeeded = this->GetNewRequiredStandard( target->GetName(), feature, - target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard, - error); + target->GetProperty(cmStrCat(lang, "_STANDARD")), featureLevel, + newRequiredStandard, error); if (!newRequiredStandard.empty()) { target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard); } @@ -711,18 +709,21 @@ cmValue cmStandardLevelResolver::CompileFeaturesAvailable( bool cmStandardLevelResolver::GetNewRequiredStandard( const std::string& targetName, const std::string& feature, - cmValue currentLangStandardValue, std::string& newRequiredStandard, - std::string* error) const + cmValue currentLangStandardValue, + cm::optional& featureLevel, + std::string& newRequiredStandard, std::string* error) const { std::string lang; if (!this->CheckCompileFeaturesAvailable(targetName, feature, lang, error)) { return false; } + featureLevel = this->CompileFeatureStandardLevel(lang, feature); + auto mapping = StandardComputerMapping.find(lang); if (mapping != cm::cend(StandardComputerMapping)) { return mapping->second.GetNewRequiredStandard( - this->Makefile, targetName, feature, currentLangStandardValue, + this->Makefile, targetName, featureLevel, currentLangStandardValue, newRequiredStandard, error); } return false; diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h index 2dd978c..09989ba 100644 --- a/Source/cmStandardLevelResolver.h +++ b/Source/cmStandardLevelResolver.h @@ -45,6 +45,7 @@ public: bool GetNewRequiredStandard(const std::string& targetName, const std::string& feature, cmValue currentLangStandardValue, + cm::optional& featureLevel, std::string& newRequiredStandard, std::string* error = nullptr) const; -- cgit v0.12 From c1f1aedcee3e24f96ec129105ae0119f3201d1cc Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 4 Oct 2023 15:12:47 -0400 Subject: cmStandardLevelResolver: Add method to look up standard level by name --- Source/cmStandardLevelResolver.cxx | 23 +++++++++++++++++++++++ Source/cmStandardLevelResolver.h | 3 +++ 2 files changed, 26 insertions(+) diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 4a149e0..e814690 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -457,6 +457,19 @@ struct StandardLevelComputer return maxLevel; } + cm::optional LanguageStandardLevel( + std::string const& standardStr) const + { + cm::optional langLevel; + auto const& stds = this->Levels; + auto stdIt = + std::find(cm::cbegin(stds), cm::cend(stds), ParseStd(standardStr)); + if (stdIt != cm::cend(stds)) { + langLevel = cmStandardLevel(std::distance(cm::cbegin(stds), stdIt)); + } + return langLevel; + } + bool IsLaterStandard(int lhs, int rhs) const { auto rhsIt = @@ -661,6 +674,16 @@ cmStandardLevelResolver::CompileFeatureStandardLevel( return mapping->second.CompileFeatureStandardLevel(this->Makefile, feature); } +cm::optional cmStandardLevelResolver::LanguageStandardLevel( + std::string const& lang, std::string const& standardStr) const +{ + auto mapping = StandardComputerMapping.find(lang); + if (mapping == cm::cend(StandardComputerMapping)) { + return cm::nullopt; + } + return mapping->second.LanguageStandardLevel(standardStr); +} + cmValue cmStandardLevelResolver::CompileFeaturesAvailable( const std::string& lang, std::string* error) const { diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h index 09989ba..29cab55 100644 --- a/Source/cmStandardLevelResolver.h +++ b/Source/cmStandardLevelResolver.h @@ -39,6 +39,9 @@ public: cm::optional CompileFeatureStandardLevel( std::string const& lang, std::string const& feature) const; + cm::optional LanguageStandardLevel( + std::string const& lang, std::string const& standardStr) const; + cmValue CompileFeaturesAvailable(const std::string& lang, std::string* error) const; -- cgit v0.12 From da36e0638b1adfdbdb75fb0228268b30f5832544 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 4 Oct 2023 18:38:20 -0400 Subject: cmGeneratorTarget: Remove outdated const/mutable pair --- Source/cmGeneratorTarget.cxx | 4 ++-- Source/cmGeneratorTarget.h | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 2454750..bbd5789 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -5025,7 +5025,7 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const } } -bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const +bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) { // Compute the language standard based on the compile features. cmStandardLevelResolver standardResolver(this->Makefile); @@ -5063,7 +5063,7 @@ bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const } bool cmGeneratorTarget::ComputeCompileFeatures( - std::string const& config, std::set const& languagePairs) const + std::string const& config, std::set const& languagePairs) { for (const auto& language : languagePairs) { BTs const* generatorTargetLanguageStandard = diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 72920d6..6bdb7ff 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -613,12 +613,11 @@ public: /** Add the target output files to the global generator manifest. */ void ComputeTargetManifest(const std::string& config) const; - bool ComputeCompileFeatures(std::string const& config) const; + bool ComputeCompileFeatures(std::string const& config); using LanguagePair = std::pair; - bool ComputeCompileFeatures( - std::string const& config, - std::set const& languagePairs) const; + bool ComputeCompileFeatures(std::string const& config, + std::set const& languagePairs); /** * Trace through the source files in this target and add al source files @@ -1241,7 +1240,7 @@ private: bool GetRPATH(const std::string& config, const std::string& prop, std::string& rpath) const; - mutable std::map> LanguageStandardMap; + std::map> LanguageStandardMap; cmValue GetPropertyWithPairedLanguageSupport(std::string const& lang, const char* suffix) const; -- cgit v0.12 From 68fca3eafeaf244c37843f186bd4af8a314df08c Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 4 Oct 2023 15:47:15 -0400 Subject: cmGeneratorTarget: Track explicitly enabled language standard levels Previously we only tracked when an explicit setting requires the standard level to be higher than the compiler's default. --- Source/cmGeneratorTarget.cxx | 40 +++++++++++++++++++++++++++++++++++++++- Source/cmGeneratorTarget.h | 8 ++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index bbd5789..1c339de 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -5025,10 +5025,44 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const } } +cm::optional cmGeneratorTarget::GetExplicitStandardLevel( + std::string const& lang, std::string const& config) const +{ + cm::optional level; + std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang); + auto i = this->ExplicitStandardLevel.find(key); + if (i != this->ExplicitStandardLevel.end()) { + level = i->second; + } + return level; +} + +void cmGeneratorTarget::UpdateExplicitStandardLevel(std::string const& lang, + std::string const& config, + cmStandardLevel level) +{ + auto e = this->ExplicitStandardLevel.emplace( + cmStrCat(cmSystemTools::UpperCase(config), '-', lang), level); + if (!e.second && e.first->second < level) { + e.first->second = level; + } +} + bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) { - // Compute the language standard based on the compile features. cmStandardLevelResolver standardResolver(this->Makefile); + + for (std::string const& lang : + this->Makefile->GetState()->GetEnabledLanguages()) { + if (cmValue languageStd = this->GetLanguageStandard(lang, config)) { + if (cm::optional langLevel = + standardResolver.LanguageStandardLevel(lang, *languageStd)) { + this->UpdateExplicitStandardLevel(lang, config, *langLevel); + } + } + } + + // Compute the language standard based on the compile features. std::vector> features = this->GetCompileFeatures(config); for (BT const& f : features) { std::string lang; @@ -5048,6 +5082,10 @@ bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) return false; } + if (featureLevel) { + this->UpdateExplicitStandardLevel(lang, config, *featureLevel); + } + if (!newRequiredStandard.empty()) { BTs& languageStandardProperty = this->LanguageStandardMap[key]; diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 6bdb7ff..bf49914 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -21,6 +21,7 @@ #include "cmLinkItem.h" #include "cmListFileCache.h" #include "cmPolicies.h" +#include "cmStandardLevel.h" #include "cmStateTypes.h" #include "cmValue.h" @@ -1242,6 +1243,13 @@ private: std::map> LanguageStandardMap; + cm::optional GetExplicitStandardLevel( + std::string const& lang, std::string const& config) const; + void UpdateExplicitStandardLevel(std::string const& lang, + std::string const& config, + cmStandardLevel level); + std::map ExplicitStandardLevel; + cmValue GetPropertyWithPairedLanguageSupport(std::string const& lang, const char* suffix) const; -- cgit v0.12 From b8ead378def8dc03dcae6b65f956c26c585eba3e Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 4 Oct 2023 15:48:36 -0400 Subject: cxxmodules: Scan only targets that explicitly enable C++ 20 Previously we scanned any targets for which C++ 20 is enabled, even if enabled only by the compiler's default, such as when `CXXFLAGS=-std=c++20`. --- Source/cmGeneratorTarget.cxx | 12 +++++------- Tests/RunCMake/CXXModules/ImplicitCXX20.cmake | 13 +++++++++++++ Tests/RunCMake/CXXModules/Inspect.cmake | 2 ++ Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 3 +++ 4 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 Tests/RunCMake/CXXModules/ImplicitCXX20.cmake diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 1c339de..01af14f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -9142,13 +9142,11 @@ cmGeneratorTarget::Cxx20SupportLevel cmGeneratorTarget::HaveCxxModuleSupport( } cmStandardLevelResolver standardResolver(this->Makefile); - if (!standardResolver.HaveStandardAvailable(this, "CXX", config, - "cxx_std_20") || - // During the ABI detection step we do not know the compiler's features. - // HaveStandardAvailable may return true as a fallback, but in this code - // path we do not want to assume C++ 20 is available. - this->Makefile->GetDefinition("CMAKE_CXX20_COMPILE_FEATURES") - .IsEmpty()) { + cmStandardLevel const cxxStd20 = + *standardResolver.LanguageStandardLevel("CXX", "20"); + cm::optional explicitLevel = + this->GetExplicitStandardLevel("CXX", config); + if (!explicitLevel || *explicitLevel < cxxStd20) { return Cxx20SupportLevel::NoCxx20; } diff --git a/Tests/RunCMake/CXXModules/ImplicitCXX20.cmake b/Tests/RunCMake/CXXModules/ImplicitCXX20.cmake new file mode 100644 index 0000000..cac1777 --- /dev/null +++ b/Tests/RunCMake/CXXModules/ImplicitCXX20.cmake @@ -0,0 +1,13 @@ +# Enable scanning by default for targets that explicitly use C++ 20. +cmake_policy(SET CMP0155 NEW) + +# Force CMAKE_CXX_STANDARD_DEFAULT to be C++ 20. +set(ENV{CXXFLAGS} "$ENV{CXXFLAGS} ${CMAKE_CXX20_STANDARD_COMPILE_OPTION}") +enable_language(CXX) + +# Hide any real scanning rule that may be available. +unset(CMAKE_CXX_SCANDEP_SOURCE) + +# Create a target that does not explicitly use C++ 20 to verify it works +# without any scanning rule available. +add_executable(cmp0155-new sources/module-use.cxx) diff --git a/Tests/RunCMake/CXXModules/Inspect.cmake b/Tests/RunCMake/CXXModules/Inspect.cmake index 8c74940..612b01b 100644 --- a/Tests/RunCMake/CXXModules/Inspect.cmake +++ b/Tests/RunCMake/CXXModules/Inspect.cmake @@ -23,6 +23,8 @@ set(forced_cxx_standard \"${forced_cxx_standard}\") set(CMAKE_CXX_COMPILER_VERSION \"${CMAKE_CXX_COMPILER_VERSION}\") set(CMAKE_CXX_OUTPUT_EXTENSION \"${CMAKE_CXX_OUTPUT_EXTENSION}\") set(CXXModules_default_build_type \"${CMAKE_BUILD_TYPE}\") +set(CMAKE_CXX_STANDARD_DEFAULT \"${CMAKE_CXX_STANDARD_DEFAULT}\") +set(CMAKE_CXX20_STANDARD_COMPILE_OPTION \"${CMAKE_CXX20_STANDARD_COMPILE_OPTION}\") ") file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}") diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index dd18d20..05d2655 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -13,6 +13,9 @@ if ("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES) # standard. If the compiler forces a standard to be used, skip it. if (NOT forced_cxx_standard) run_cmake(NoCXX20) + if(CMAKE_CXX_STANDARD_DEFAULT AND CMAKE_CXX20_STANDARD_COMPILE_OPTION) + run_cmake_with_options(ImplicitCXX20 -DCMAKE_CXX20_STANDARD_COMPILE_OPTION=${CMAKE_CXX20_STANDARD_COMPILE_OPTION}) + endif() endif () run_cmake(NoScanningSourceFileProperty) -- cgit v0.12