summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2023-10-06 12:35:53 (GMT)
committerKitware Robot <kwrobot@kitware.com>2023-10-06 12:36:02 (GMT)
commit24c5a3aecfee14ece66ecfe6198ddac1f465bbcd (patch)
treee4658121d42f5b6079059b590a5f72449f0d08d7
parenta48363782131c3ab45c4b40773ff25002e6c3adb (diff)
parentb8ead378def8dc03dcae6b65f956c26c585eba3e (diff)
downloadCMake-24c5a3aecfee14ece66ecfe6198ddac1f465bbcd.zip
CMake-24c5a3aecfee14ece66ecfe6198ddac1f465bbcd.tar.gz
CMake-24c5a3aecfee14ece66ecfe6198ddac1f465bbcd.tar.bz2
Merge topic 'cxxmodules-explicit-c++20' into release-3.28
b8ead378de cxxmodules: Scan only targets that explicitly enable C++ 20 68fca3eafe cmGeneratorTarget: Track explicitly enabled language standard levels da36e0638b cmGeneratorTarget: Remove outdated const/mutable pair c1f1aedcee cmStandardLevelResolver: Add method to look up standard level by name 23b57462aa cmStandardLevelResolver: Report feature std level from GetNewRequiredStandard 7519001ae6 cmStandardLevelResolver: Add method to get feature standard level 99fa01d3fa cmStandardLevelResolver: Factor out public representation of level fdd81a609a cmStandardLevelResolver: Clarify local variable name ... Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Reviewed-by: Ben Boeckel <ben.boeckel@kitware.com> Merge-request: !8860
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/cmGeneratorTarget.cxx60
-rw-r--r--Source/cmGeneratorTarget.h17
-rw-r--r--Source/cmStandardLevel.h21
-rw-r--r--Source/cmStandardLevelResolver.cxx143
-rw-r--r--Source/cmStandardLevelResolver.h10
-rw-r--r--Tests/RunCMake/CXXModules/ImplicitCXX20.cmake13
-rw-r--r--Tests/RunCMake/CXXModules/Inspect.cmake (renamed from Tests/RunCMake/CXXModules/compiler_introspection.cmake)2
-rw-r--r--Tests/RunCMake/CXXModules/RunCMakeTest.cmake7
9 files changed, 199 insertions, 75 deletions
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/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 422d927..01af14f 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"
@@ -5024,10 +5025,44 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
}
}
-bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
+cm::optional<cmStandardLevel> cmGeneratorTarget::GetExplicitStandardLevel(
+ std::string const& lang, std::string const& config) const
+{
+ cm::optional<cmStandardLevel> 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<cmStandardLevel> langLevel =
+ standardResolver.LanguageStandardLevel(lang, *languageStd)) {
+ this->UpdateExplicitStandardLevel(lang, config, *langLevel);
+ }
+ }
+ }
+
+ // Compute the language standard based on the compile features.
std::vector<BT<std::string>> features = this->GetCompileFeatures(config);
for (BT<std::string> const& f : features) {
std::string lang;
@@ -5039,13 +5074,18 @@ bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang);
cmValue currentLanguageStandard = this->GetLanguageStandard(lang, config);
+ cm::optional<cmStandardLevel> featureLevel;
std::string newRequiredStandard;
if (!standardResolver.GetNewRequiredStandard(
this->Target->GetName(), f.Value, currentLanguageStandard,
- newRequiredStandard)) {
+ featureLevel, newRequiredStandard)) {
return false;
}
+ if (featureLevel) {
+ this->UpdateExplicitStandardLevel(lang, config, *featureLevel);
+ }
+
if (!newRequiredStandard.empty()) {
BTs<std::string>& languageStandardProperty =
this->LanguageStandardMap[key];
@@ -5061,7 +5101,7 @@ bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
}
bool cmGeneratorTarget::ComputeCompileFeatures(
- std::string const& config, std::set<LanguagePair> const& languagePairs) const
+ std::string const& config, std::set<LanguagePair> const& languagePairs)
{
for (const auto& language : languagePairs) {
BTs<std::string> const* generatorTargetLanguageStandard =
@@ -9102,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<cmStandardLevel> explicitLevel =
+ this->GetExplicitStandardLevel("CXX", config);
+ if (!explicitLevel || *explicitLevel < cxxStd20) {
return Cxx20SupportLevel::NoCxx20;
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 72920d6..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"
@@ -613,12 +614,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<std::string, std::string>;
- bool ComputeCompileFeatures(
- std::string const& config,
- std::set<LanguagePair> const& languagePairs) const;
+ bool ComputeCompileFeatures(std::string const& config,
+ std::set<LanguagePair> const& languagePairs);
/**
* Trace through the source files in this target and add al source files
@@ -1241,7 +1241,14 @@ private:
bool GetRPATH(const std::string& config, const std::string& prop,
std::string& rpath) const;
- mutable std::map<std::string, BTs<std::string>> LanguageStandardMap;
+ std::map<std::string, BTs<std::string>> LanguageStandardMap;
+
+ cm::optional<cmStandardLevel> GetExplicitStandardLevel(
+ std::string const& lang, std::string const& config) const;
+ void UpdateExplicitStandardLevel(std::string const& lang,
+ std::string const& config,
+ cmStandardLevel level);
+ std::map<std::string, cmStandardLevel> ExplicitStandardLevel;
cmValue GetPropertyWithPairedLanguageSupport(std::string const& lang,
const char* suffix) const;
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 de42bc6..e814690 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -13,6 +13,7 @@
#include <vector>
#include <cm/iterator>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/string_view>
@@ -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 {
@@ -341,7 +337,7 @@ struct StandardLevelComputer
bool GetNewRequiredStandard(cmMakefile* makefile,
std::string const& targetName,
- const std::string& feature,
+ cm::optional<cmStandardLevel> featureLevel,
cmValue currentLangStandardValue,
std::string& newRequiredStandard,
std::string* error) const
@@ -352,8 +348,6 @@ struct StandardLevelComputer
newRequiredStandard.clear();
}
- auto needed = this->HighestStandardNeeded(makefile, feature);
-
cmValue existingStandard = currentLangStandardValue;
if (!existingStandard) {
cmValue defaultStandard = makefile->GetDefinition(
@@ -382,12 +376,12 @@ struct StandardLevelComputer
}
}
- if (needed.index != -1) {
+ 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()];
}
}
@@ -439,29 +433,43 @@ struct StandardLevelComputer
return false;
}
- auto needed = this->HighestStandardNeeded(makefile, feature);
+ cm::optional<cmStandardLevel> needed =
+ this->CompileFeatureStandardLevel(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<cmStandardLevel> CompileFeatureStandardLevel(
+ cmMakefile* makefile, std::string const& feature) const
{
std::string prefix = cmStrCat("CMAKE_", this->Language);
- StandardNeeded maxLevel = { -1, -1 };
+ cm::optional<cmStandardLevel> 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<int>(i), this->Levels[i] };
+ maxLevel = cmStandardLevel(i);
}
}
}
return maxLevel;
}
+ cm::optional<cmStandardLevel> LanguageStandardLevel(
+ std::string const& standardStr) const
+ {
+ cm::optional<cmStandardLevel> 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 =
@@ -476,37 +484,33 @@ struct StandardLevelComputer
std::vector<std::string> LevelsAsStrings;
};
-std::unordered_map<std::string, StandardLevelComputer>
- StandardComputerMapping = {
- { "C",
- StandardLevelComputer{
- "C", std::vector<int>{ 90, 99, 11, 17, 23 },
- std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
- { "CXX",
- StandardLevelComputer{ "CXX",
- std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 },
- std::vector<std::string>{ "98", "11", "14", "17",
- "20", "23", "26" } } },
- { "CUDA",
- StandardLevelComputer{ "CUDA",
- std::vector<int>{ 03, 11, 14, 17, 20, 23, 26 },
- std::vector<std::string>{ "03", "11", "14", "17",
- "20", "23", "26" } } },
- { "OBJC",
- StandardLevelComputer{
- "OBJC", std::vector<int>{ 90, 99, 11, 17, 23 },
- std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
- { "OBJCXX",
- StandardLevelComputer{ "OBJCXX",
- std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 },
- std::vector<std::string>{ "98", "11", "14", "17",
- "20", "23", "26" } } },
- { "HIP",
- StandardLevelComputer{ "HIP",
- std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 },
- std::vector<std::string>{ "98", "11", "14", "17",
- "20", "23", "26" } } }
- };
+std::unordered_map<std::string,
+ StandardLevelComputer> const StandardComputerMapping = {
+ { "C",
+ StandardLevelComputer{
+ "C", std::vector<int>{ 90, 99, 11, 17, 23 },
+ std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
+ { "CXX",
+ StandardLevelComputer{
+ "CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 },
+ std::vector<std::string>{ "98", "11", "14", "17", "20", "23", "26" } } },
+ { "CUDA",
+ StandardLevelComputer{
+ "CUDA", std::vector<int>{ 03, 11, 14, 17, 20, 23, 26 },
+ std::vector<std::string>{ "03", "11", "14", "17", "20", "23", "26" } } },
+ { "OBJC",
+ StandardLevelComputer{
+ "OBJC", std::vector<int>{ 90, 99, 11, 17, 23 },
+ std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
+ { "OBJCXX",
+ StandardLevelComputer{
+ "OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 },
+ std::vector<std::string>{ "98", "11", "14", "17", "20", "23", "26" } } },
+ { "HIP",
+ StandardLevelComputer{
+ "HIP", std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 },
+ std::vector<std::string>{ "98", "11", "14", "17", "20", "23", "26" } } }
+};
}
std::string cmStandardLevelResolver::GetCompileOptionDef(
@@ -556,15 +560,16 @@ 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<cmStandardLevel> featureLevel;
std::string newRequiredStandard;
- bool newRequired = this->GetNewRequiredStandard(
+ 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);
}
- return newRequired;
+ return succeeded;
}
bool cmStandardLevelResolver::CheckCompileFeaturesAvailable(
@@ -658,6 +663,27 @@ bool cmStandardLevelResolver::CompileFeatureKnown(
return false;
}
+cm::optional<cmStandardLevel>
+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);
+}
+
+cm::optional<cmStandardLevel> 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
{
@@ -706,18 +732,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<cmStandardLevel>& 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 03adf3f..29cab55 100644
--- a/Source/cmStandardLevelResolver.h
+++ b/Source/cmStandardLevelResolver.h
@@ -4,10 +4,13 @@
#include <string>
+#include <cm/optional>
+
#include "cmValue.h"
class cmMakefile;
class cmGeneratorTarget;
+class cmStandardLevel;
class cmTarget;
class cmStandardLevelResolver
@@ -33,12 +36,19 @@ public:
const std::string& feature, std::string& lang,
std::string* error) const;
+ cm::optional<cmStandardLevel> CompileFeatureStandardLevel(
+ std::string const& lang, std::string const& feature) const;
+
+ cm::optional<cmStandardLevel> LanguageStandardLevel(
+ std::string const& lang, std::string const& standardStr) const;
+
cmValue CompileFeaturesAvailable(const std::string& lang,
std::string* error) const;
bool GetNewRequiredStandard(const std::string& targetName,
const std::string& feature,
cmValue currentLangStandardValue,
+ cm::optional<cmStandardLevel>& featureLevel,
std::string& newRequiredStandard,
std::string* error = nullptr) const;
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/compiler_introspection.cmake b/Tests/RunCMake/CXXModules/Inspect.cmake
index 8c74940..612b01b 100644
--- a/Tests/RunCMake/CXXModules/compiler_introspection.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 8b22687..05d2655 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)
@@ -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)