summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2023-08-25 15:27:10 (GMT)
committerKitware Robot <kwrobot@kitware.com>2023-08-25 15:27:27 (GMT)
commit863891adb232cd89830080c702361444f496b4fe (patch)
tree4a7c0cb3b7a33d3cf2cfe85f0d5075f7455605ae /Source
parent5ae0030e90df07e56dc16b0210bd334650dcc9d4 (diff)
parent571b5e1f2c5569cd555377423930f8d61d5d2e99 (diff)
downloadCMake-863891adb232cd89830080c702361444f496b4fe.zip
CMake-863891adb232cd89830080c702361444f496b4fe.tar.gz
CMake-863891adb232cd89830080c702361444f496b4fe.tar.bz2
Merge topic 'modules-better-messages'
571b5e1f2c cxxmodules: improve error messages for C++ module setup 8b4d32c18b cmStandardLevelResolver: add query for the effective standard level 17ddc4ac76 cmStandardLevelResolver: compare with static string literals 6f1dae2b01 cmStandardLevelResolver: use `cmStrCat` where possible 0d45d40e13 cmStandardLevelResolver: use character literals where possible Acked-by: Kitware Robot <kwrobot@kitware.com> Tested-by: buildbot <buildbot@kitware.com> Merge-request: !8755
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGeneratorTarget.cxx31
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx4
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx4
-rw-r--r--Source/cmMakefileTargetGenerator.cxx6
-rw-r--r--Source/cmStandardLevelResolver.cxx157
-rw-r--r--Source/cmStandardLevelResolver.h3
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx6
7 files changed, 170 insertions, 41 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 70f51b0..db4be63 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -9100,25 +9100,34 @@ void cmGeneratorTarget::CheckCxxModuleStatus(std::string const& config) const
case cmGeneratorTarget::Cxx20SupportLevel::MissingCxx:
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- cmStrCat("The \"", this->GetName(),
- "\" target has C++ module sources but the \"CXX\" language "
- "has not been enabled"));
+ cmStrCat("The target named \"", this->GetName(),
+ "\" has C++ sources that export modules but the \"CXX\" "
+ "language has not been enabled"));
break;
case cmGeneratorTarget::Cxx20SupportLevel::MissingExperimentalFlag:
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- cmStrCat("The \"", this->GetName(),
- "\" target has C++ module sources but its experimental "
- "support has not been requested"));
+ cmStrCat("The target named \"", this->GetName(),
+ "\" has C++ sources that export modules but its "
+ "experimental support has not been requested"));
break;
- case cmGeneratorTarget::Cxx20SupportLevel::NoCxx20:
+ case cmGeneratorTarget::Cxx20SupportLevel::NoCxx20: {
+ cmStandardLevelResolver standardResolver(this->Makefile);
+ auto effStandard =
+ standardResolver.GetEffectiveStandard(this, "CXX", config);
+ if (effStandard.empty()) {
+ effStandard = "; no C++ standard found";
+ } else {
+ effStandard = cmStrCat("; found \"cxx_std_", effStandard, '"');
+ }
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat(
- "The \"", this->GetName(),
- "\" target has C++ module sources but is not using at least "
- "\"cxx_std_20\""));
- break;
+ "The target named \"", this->GetName(),
+ "\" has C++ sources that export modules but does not include "
+ "\"cxx_std_20\" (or newer) among its `target_compile_features`",
+ effStandard));
+ } break;
case cmGeneratorTarget::Cxx20SupportLevel::Supported:
// All is well.
break;
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index b2657a7..6953ec6 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -438,8 +438,8 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
if (target->HaveCxx20ModuleSources() && !this->SupportsCxxModuleDyndep()) {
root->GetMakefile()->IssueMessage(
MessageType::FATAL_ERROR,
- cmStrCat("The \"", target->GetName(),
- "\" target contains C++ module sources which are not "
+ cmStrCat("The target named \"", target->GetName(),
+ "\" contains C++ sources that export modules which is not "
"supported by the generator"));
}
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 9834b64..3b9d2fd 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1385,8 +1385,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
if (gtgt->HaveCxx20ModuleSources()) {
gtgt->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- cmStrCat("The \"", gtgt->GetName(),
- "\" target contains C++ module sources which are not "
+ cmStrCat("The target named \"", gtgt->GetName(),
+ "\" contains C++ sources that export modules which is not "
"supported by the generator"));
}
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 5e3bf61..caa5e67 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -207,9 +207,9 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
if (this->GeneratorTarget->HaveCxx20ModuleSources()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- cmStrCat("The \"", this->GeneratorTarget->GetName(),
- "\" target contains C++ module sources which are not supported "
- "by the generator"));
+ cmStrCat("The target named \"", this->GeneratorTarget->GetName(),
+ "\" contains C++ sources that export modules which is not "
+ "supported by the generator"));
}
// -- Write the custom commands for this target
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index f6e8bc6..de42bc6 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -13,7 +13,9 @@
#include <vector>
#include <cm/iterator>
+#include <cm/string_view>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
@@ -71,6 +73,8 @@ struct StandardLevelComputer
assert(this->Levels.size() == this->LevelsAsStrings.size());
}
+ // Note that the logic here is shadowed in `GetEffectiveStandard`; if one is
+ // changed, the other needs changed as well.
std::string GetCompileOptionDef(cmMakefile* makefile,
cmGeneratorTarget const* target,
std::string const& config) const
@@ -107,7 +111,7 @@ struct StandardLevelComputer
if (cmp0128 == cmPolicies::NEW) {
// Add extension flag if compiler's default doesn't match.
if (ext != defaultExt) {
- return cmStrCat("CMAKE_", this->Language, *defaultStd, "_", type,
+ return cmStrCat("CMAKE_", this->Language, *defaultStd, '_', type,
"_COMPILE_OPTION");
}
} else {
@@ -130,7 +134,7 @@ struct StandardLevelComputer
cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0128),
"\nFor compatibility with older versions of CMake, "
"compiler extensions won't be ",
- state, "."));
+ state, '.'));
}
}
@@ -144,7 +148,7 @@ struct StandardLevelComputer
if (target->GetLanguageStandardRequired(this->Language)) {
std::string option_flag = cmStrCat(
- "CMAKE_", this->Language, *standardProp, "_", type, "_COMPILE_OPTION");
+ "CMAKE_", this->Language, *standardProp, '_', type, "_COMPILE_OPTION");
cmValue opt = target->Target->GetMakefile()->GetDefinition(option_flag);
if (!opt) {
@@ -155,8 +159,8 @@ struct StandardLevelComputer
<< this->Language << *standardProp << "\" "
<< (ext ? "(with compiler extensions)" : "")
<< ". But the current compiler \""
- << makefile->GetSafeDefinition("CMAKE_" + this->Language +
- "_COMPILER_ID")
+ << makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", this->Language, "_COMPILER_ID"))
<< "\" does not support this, or "
"CMake does not know the flags to enable it.";
@@ -185,7 +189,7 @@ struct StandardLevelComputer
}
std::string standardStr(*standardProp);
- if (this->Language == "CUDA" && standardStr == "98") {
+ if (this->Language == "CUDA"_s && standardStr == "98"_s) {
standardStr = "03";
}
@@ -194,7 +198,7 @@ struct StandardLevelComputer
if (stdIt == cm::cend(stds)) {
std::string e =
cmStrCat(this->Language, "_STANDARD is set to invalid value '",
- standardStr, "'");
+ standardStr, '\'');
makefile->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
target->GetBacktrace());
return std::string{};
@@ -205,7 +209,7 @@ struct StandardLevelComputer
if (defaultStdIt == cm::cend(stds)) {
std::string e = cmStrCat("CMAKE_", this->Language,
"_STANDARD_DEFAULT is set to invalid value '",
- *defaultStd, "'");
+ *defaultStd, '\'');
makefile->IssueMessage(MessageType::INTERNAL_ERROR, e);
return std::string{};
}
@@ -216,7 +220,7 @@ struct StandardLevelComputer
(cmp0128 == cmPolicies::NEW &&
(stdIt < defaultStdIt || ext != defaultExt))) {
auto offset = std::distance(cm::cbegin(stds), stdIt);
- return cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type,
+ return cmStrCat("CMAKE_", this->Language, stdsStrings[offset], '_', type,
"_COMPILE_OPTION");
}
@@ -226,7 +230,7 @@ struct StandardLevelComputer
for (; defaultStdIt < stdIt; --stdIt) {
auto offset = std::distance(cm::cbegin(stds), stdIt);
std::string option_flag =
- cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type,
+ cmStrCat("CMAKE_", this->Language, stdsStrings[offset], '_', type,
"_COMPILE_OPTION");
if (target->Target->GetMakefile()->GetDefinition(option_flag)) {
return option_flag;
@@ -236,6 +240,105 @@ struct StandardLevelComputer
return std::string{};
}
+ std::string GetEffectiveStandard(cmMakefile* makefile,
+ cmGeneratorTarget const* target,
+ std::string const& config) const
+ {
+ const auto& stds = this->Levels;
+ const auto& stdsStrings = this->LevelsAsStrings;
+
+ cmValue defaultStd = makefile->GetDefinition(
+ cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT"));
+ if (!cmNonempty(defaultStd)) {
+ // this compiler has no notion of language standard levels
+ return std::string{};
+ }
+
+ cmPolicies::PolicyStatus const cmp0128{ makefile->GetPolicyStatus(
+ cmPolicies::CMP0128) };
+ bool const defaultExt{ cmIsOn(*makefile->GetDefinition(
+ cmStrCat("CMAKE_", this->Language, "_EXTENSIONS_DEFAULT"))) };
+ bool ext = true;
+
+ if (cmp0128 == cmPolicies::NEW) {
+ ext = defaultExt;
+ }
+
+ if (cmValue extPropValue = target->GetLanguageExtensions(this->Language)) {
+ ext = cmIsOn(*extPropValue);
+ }
+
+ std::string const type{ ext ? "EXTENSION" : "STANDARD" };
+
+ cmValue standardProp = target->GetLanguageStandard(this->Language, config);
+ if (!standardProp) {
+ if (cmp0128 == cmPolicies::NEW) {
+ // Add extension flag if compiler's default doesn't match.
+ if (ext != defaultExt) {
+ return *defaultStd;
+ }
+ } else {
+ if (ext) {
+ return *defaultStd;
+ }
+ }
+ return std::string{};
+ }
+
+ if (target->GetLanguageStandardRequired(this->Language)) {
+ return *standardProp;
+ }
+
+ // If the request matches the compiler's defaults we don't need to add
+ // anything.
+ if (*standardProp == *defaultStd && ext == defaultExt) {
+ if (cmp0128 == cmPolicies::NEW) {
+ return std::string{};
+ }
+ }
+
+ std::string standardStr(*standardProp);
+ if (this->Language == "CUDA"_s && standardStr == "98"_s) {
+ standardStr = "03";
+ }
+
+ auto stdIt =
+ std::find(cm::cbegin(stds), cm::cend(stds), ParseStd(standardStr));
+ if (stdIt == cm::cend(stds)) {
+ return std::string{};
+ }
+
+ auto defaultStdIt =
+ std::find(cm::cbegin(stds), cm::cend(stds), ParseStd(*defaultStd));
+ if (defaultStdIt == cm::cend(stds)) {
+ return std::string{};
+ }
+
+ // If the standard requested is older than the compiler's default or the
+ // extension mode doesn't match then we need to use a flag.
+ if ((cmp0128 != cmPolicies::NEW && stdIt <= defaultStdIt) ||
+ (cmp0128 == cmPolicies::NEW &&
+ (stdIt < defaultStdIt || ext != defaultExt))) {
+ auto offset = std::distance(cm::cbegin(stds), stdIt);
+ return stdsStrings[offset];
+ }
+
+ // The compiler's default is at least as new as the requested standard,
+ // and the requested standard 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 stdsStrings[offset];
+ }
+ }
+
+ return std::string{};
+ }
+
bool GetNewRequiredStandard(cmMakefile* makefile,
std::string const& targetName,
const std::string& feature,
@@ -418,6 +521,18 @@ std::string cmStandardLevelResolver::GetCompileOptionDef(
return mapping->second.GetCompileOptionDef(this->Makefile, target, config);
}
+std::string cmStandardLevelResolver::GetEffectiveStandard(
+ 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.GetEffectiveStandard(this->Makefile, target, config);
+}
+
bool cmStandardLevelResolver::AddRequiredTargetFeature(
cmTarget* target, const std::string& feature, std::string* error) const
{
@@ -474,11 +589,12 @@ bool cmStandardLevelResolver::CheckCompileFeaturesAvailable(
std::ostringstream e;
e << "The compiler feature \"" << feature << "\" is not known to " << lang
<< " compiler\n\""
- << this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID")
+ << this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_COMPILER_ID"))
<< "\"\nversion "
- << this->Makefile->GetSafeDefinition("CMAKE_" + lang +
- "_COMPILER_VERSION")
- << ".";
+ << this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_COMPILER_VERSION"))
+ << '.';
if (error) {
*error = e.str();
} else {
@@ -561,8 +677,8 @@ cmValue cmStandardLevelResolver::CompileFeaturesAvailable(
return nullptr;
}
- cmValue featuresKnown =
- this->Makefile->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES");
+ cmValue featuresKnown = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", lang, "_COMPILE_FEATURES"));
if (!cmNonempty(featuresKnown)) {
std::ostringstream e;
@@ -572,11 +688,12 @@ cmValue cmStandardLevelResolver::CompileFeaturesAvailable(
e << "No";
}
e << " known features for " << lang << " compiler\n\""
- << this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID")
+ << this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_COMPILER_ID"))
<< "\"\nversion "
- << this->Makefile->GetSafeDefinition("CMAKE_" + lang +
- "_COMPILER_VERSION")
- << ".";
+ << this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_COMPILER_VERSION"))
+ << '.';
if (error) {
*error = e.str();
} else {
diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h
index 4226456..03adf3f 100644
--- a/Source/cmStandardLevelResolver.h
+++ b/Source/cmStandardLevelResolver.h
@@ -22,6 +22,9 @@ public:
std::string GetCompileOptionDef(cmGeneratorTarget const* target,
std::string const& lang,
std::string const& config) const;
+ std::string GetEffectiveStandard(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/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 1bd4c57..7ca23a3 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -366,9 +366,9 @@ void cmVisualStudio10TargetGenerator::Generate()
!this->GlobalGenerator->SupportsCxxModuleDyndep()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
- cmStrCat("The \"", this->GeneratorTarget->GetName(),
- "\" target contains C++ module sources which are not supported "
- "by the generator"));
+ cmStrCat("The target named \"", this->GeneratorTarget->GetName(),
+ "\" contains C++ sources that export modules which is not "
+ "supported by the generator"));
}
this->ProjectType = computeProjectType(this->GeneratorTarget);