mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-26 04:09:35 +03:00
Refactor language standard computation
Instead of mutating the configure-time cmTarget's properties at generate time, compute and store it in a cmGeneratorTarget field.
This commit is contained in:
@@ -1742,9 +1742,9 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
|
||||
continue;
|
||||
}
|
||||
if (!context->LG->GetMakefile()->HaveStandardAvailable(
|
||||
target->Target, lit.first, it)) {
|
||||
target, lit.first, context->Config, it)) {
|
||||
if (evalLL) {
|
||||
cmProp l = target->GetProperty(lit.first + "_STANDARD");
|
||||
cmProp l = target->GetLanguageStandard(lit.first, context->Config);
|
||||
if (!l) {
|
||||
l = standardDefault;
|
||||
}
|
||||
|
||||
@@ -947,6 +947,45 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
|
||||
return it != this->ExplicitObjectName.end();
|
||||
}
|
||||
|
||||
cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang,
|
||||
std::string const& config) const
|
||||
{
|
||||
std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang);
|
||||
auto langStandardIter = this->LanguageStandardMap.find(key);
|
||||
if (langStandardIter != this->LanguageStandardMap.end()) {
|
||||
return &langStandardIter->second;
|
||||
}
|
||||
|
||||
return this->Target->GetProperty(cmStrCat(lang, "_STANDARD"));
|
||||
}
|
||||
|
||||
cmProp cmGeneratorTarget::GetLanguageStandardProperty(std::string const& lang,
|
||||
const char* suffix) const
|
||||
{
|
||||
cmProp propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix));
|
||||
if (propertyValue == nullptr) {
|
||||
// Check if we should use the value set by another language.
|
||||
if (lang == "OBJC") {
|
||||
propertyValue = this->GetLanguageStandardProperty("C", suffix);
|
||||
} else if (lang == "OBJCXX" || lang == "CUDA") {
|
||||
propertyValue = this->GetLanguageStandardProperty("CXX", suffix);
|
||||
}
|
||||
}
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
cmProp cmGeneratorTarget::GetLanguageExtensions(std::string const& lang) const
|
||||
{
|
||||
return this->GetLanguageStandardProperty(lang, "_EXTENSIONS");
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::GetLanguageStandardRequired(
|
||||
std::string const& lang) const
|
||||
{
|
||||
cmProp p = this->GetLanguageStandardProperty(lang, "_STANDARD_REQUIRED");
|
||||
return p && cmIsOn(*p);
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::GetModuleDefinitionSources(
|
||||
std::vector<cmSourceFile const*>& data, const std::string& config) const
|
||||
{
|
||||
@@ -4408,12 +4447,68 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
|
||||
|
||||
bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
|
||||
{
|
||||
// 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) {
|
||||
if (!this->Makefile->AddRequiredTargetFeature(this->Target, f.Value)) {
|
||||
std::string lang;
|
||||
if (!this->Makefile->CompileFeatureKnown(this->Target->GetName(), f.Value,
|
||||
lang, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang);
|
||||
cmProp currentLanguageStandard = this->GetLanguageStandard(lang, config);
|
||||
|
||||
std::string newRequiredStandard;
|
||||
if (!this->Makefile->GetNewRequiredStandard(
|
||||
this->Target->GetName(), f.Value, currentLanguageStandard,
|
||||
newRequiredStandard)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!newRequiredStandard.empty()) {
|
||||
this->LanguageStandardMap[key] = newRequiredStandard;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::ComputeCompileFeatures(
|
||||
std::string const& config, std::set<LanguagePair> const& languagePairs) const
|
||||
{
|
||||
for (const auto& language : languagePairs) {
|
||||
cmProp generatorTargetLanguageStandard =
|
||||
this->GetLanguageStandard(language.first, config);
|
||||
if (!generatorTargetLanguageStandard) {
|
||||
// If the standard isn't explicitly set we copy it over from the
|
||||
// specified paired language.
|
||||
std::string key =
|
||||
cmStrCat(cmSystemTools::UpperCase(config), '-', language.first);
|
||||
cmProp standardToCopy =
|
||||
this->GetLanguageStandard(language.second, config);
|
||||
if (standardToCopy != nullptr) {
|
||||
this->LanguageStandardMap[key] = *standardToCopy;
|
||||
generatorTargetLanguageStandard = &this->LanguageStandardMap[key];
|
||||
} else {
|
||||
cmProp defaultStandard = this->Makefile->GetDef(
|
||||
cmStrCat("CMAKE_", language.second, "_STANDARD_DEFAULT"));
|
||||
if (defaultStandard != nullptr) {
|
||||
this->LanguageStandardMap[key] = *defaultStandard;
|
||||
generatorTargetLanguageStandard = &this->LanguageStandardMap[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Custom updates for the CUDA standard.
|
||||
if (generatorTargetLanguageStandard != nullptr &&
|
||||
language.first == "CUDA") {
|
||||
if (*generatorTargetLanguageStandard == "98") {
|
||||
this->LanguageStandardMap[key] = "03";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -148,6 +148,13 @@ public:
|
||||
bool HasExplicitObjectName(cmSourceFile const* file) const;
|
||||
void AddExplicitObjectName(cmSourceFile const* sf);
|
||||
|
||||
cmProp GetLanguageStandard(std::string const& lang,
|
||||
std::string const& config) const;
|
||||
|
||||
cmProp GetLanguageExtensions(std::string const& lang) const;
|
||||
|
||||
bool GetLanguageStandardRequired(std::string const& lang) const;
|
||||
|
||||
void GetModuleDefinitionSources(std::vector<cmSourceFile const*>&,
|
||||
const std::string& config) const;
|
||||
void GetExternalObjects(std::vector<cmSourceFile const*>&,
|
||||
@@ -515,6 +522,11 @@ public:
|
||||
|
||||
bool ComputeCompileFeatures(std::string const& config) const;
|
||||
|
||||
using LanguagePair = std::pair<std::string, std::string>;
|
||||
bool ComputeCompileFeatures(
|
||||
std::string const& config,
|
||||
std::set<LanguagePair> const& languagePairs) const;
|
||||
|
||||
/**
|
||||
* Trace through the source files in this target and add al source files
|
||||
* that they depend on, used by all generators
|
||||
@@ -1038,6 +1050,11 @@ private:
|
||||
bool GetRPATH(const std::string& config, const std::string& prop,
|
||||
std::string& rpath) const;
|
||||
|
||||
mutable std::map<std::string, std::string> LanguageStandardMap;
|
||||
|
||||
cmProp GetLanguageStandardProperty(std::string const& lang,
|
||||
const char* suffix) const;
|
||||
|
||||
public:
|
||||
const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
|
||||
const std::string& config) const;
|
||||
|
||||
@@ -1442,12 +1442,10 @@ bool cmGlobalGenerator::Compute()
|
||||
localGen->AddHelperCommands();
|
||||
}
|
||||
|
||||
// Finalize the set of compile features for each target.
|
||||
// FIXME: This turns into calls to cmMakefile::AddRequiredTargetFeature
|
||||
// which actually modifies the <lang>_STANDARD target property
|
||||
// on the original cmTarget instance. It accumulates features
|
||||
// across all configurations. Some refactoring is needed to
|
||||
// compute a per-config resulta purely during generation.
|
||||
// Perform up-front computation in order to handle errors (such as unknown
|
||||
// features) at this point. While processing the compile features we also
|
||||
// calculate and cache the language standard required by the compile
|
||||
// features.
|
||||
for (const auto& localGen : this->LocalGenerators) {
|
||||
if (!localGen->ComputeTargetCompileFeatures()) {
|
||||
return false;
|
||||
|
||||
+10
-42
@@ -803,39 +803,8 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures()
|
||||
// Now that C/C++ _STANDARD values have been computed
|
||||
// set the values to ObjC/ObjCXX _STANDARD variables
|
||||
if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
|
||||
auto copyStandardToObjLang = [&](LanguagePair const& lang) -> bool {
|
||||
if (!target->GetProperty(cmStrCat(lang.first, "_STANDARD"))) {
|
||||
cmProp standard =
|
||||
target->GetProperty(cmStrCat(lang.second, "_STANDARD"));
|
||||
if (!standard) {
|
||||
standard = this->Makefile->GetDef(
|
||||
cmStrCat("CMAKE_", lang.second, "_STANDARD_DEFAULT"));
|
||||
}
|
||||
target->Target->SetProperty(cmStrCat(lang.first, "_STANDARD"),
|
||||
standard ? standard->c_str() : nullptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
auto copyPropertyToObjLang = [&](LanguagePair const& lang,
|
||||
const char* property) {
|
||||
if (!target->GetProperty(cmStrCat(lang.first, property)) &&
|
||||
target->GetProperty(cmStrCat(lang.second, property))) {
|
||||
cmProp p = target->GetProperty(cmStrCat(lang.second, property));
|
||||
target->Target->SetProperty(cmStrCat(lang.first, property),
|
||||
p ? p->c_str() : nullptr);
|
||||
}
|
||||
};
|
||||
for (auto const& lang : pairedLanguages) {
|
||||
if (copyStandardToObjLang(lang)) {
|
||||
copyPropertyToObjLang(lang, "_STANDARD_REQUIRED");
|
||||
copyPropertyToObjLang(lang, "_EXTENSIONS");
|
||||
}
|
||||
}
|
||||
if (cmProp standard = target->GetProperty("CUDA_STANDARD")) {
|
||||
if (*standard == "98") {
|
||||
target->Target->SetProperty("CUDA_STANDARD", "03");
|
||||
}
|
||||
for (std::string const& c : configNames) {
|
||||
target->ComputeCompileFeatures(c, inferredEnabledLanguages);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1026,7 +995,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
|
||||
}
|
||||
|
||||
for (auto const& it : target->GetMaxLanguageStandards()) {
|
||||
cmProp standard = target->GetProperty(it.first + "_STANDARD");
|
||||
cmProp standard = target->GetLanguageStandard(it.first, config);
|
||||
if (!standard) {
|
||||
continue;
|
||||
}
|
||||
@@ -1050,7 +1019,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
|
||||
}
|
||||
|
||||
std::string compReqFlag;
|
||||
this->AddCompilerRequirementFlag(compReqFlag, target, lang);
|
||||
this->AddCompilerRequirementFlag(compReqFlag, target, lang, config);
|
||||
if (!compReqFlag.empty()) {
|
||||
flags.emplace_back(std::move(compReqFlag));
|
||||
}
|
||||
@@ -2045,7 +2014,7 @@ void cmLocalGenerator::AddLanguageFlagsForLinking(
|
||||
// when linking in order to use the matching standard library.
|
||||
// FIXME: If CMake gains an abstraction for standard library
|
||||
// selection, this will have to be reconciled with it.
|
||||
this->AddCompilerRequirementFlag(flags, target, lang);
|
||||
this->AddCompilerRequirementFlag(flags, target, lang, config);
|
||||
}
|
||||
|
||||
this->AddLanguageFlags(flags, target, lang, config);
|
||||
@@ -2188,7 +2157,8 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
|
||||
}
|
||||
|
||||
void cmLocalGenerator::AddCompilerRequirementFlag(
|
||||
std::string& flags, cmGeneratorTarget const* target, const std::string& lang)
|
||||
std::string& flags, cmGeneratorTarget const* target, const std::string& lang,
|
||||
const std::string& config)
|
||||
{
|
||||
if (lang.empty()) {
|
||||
return;
|
||||
@@ -2199,15 +2169,13 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
|
||||
// This compiler has no notion of language standard levels.
|
||||
return;
|
||||
}
|
||||
std::string extProp = lang + "_EXTENSIONS";
|
||||
bool ext = true;
|
||||
if (cmProp extPropValue = target->GetProperty(extProp)) {
|
||||
if (cmProp extPropValue = target->GetLanguageExtensions(lang)) {
|
||||
if (cmIsOff(*extPropValue)) {
|
||||
ext = false;
|
||||
}
|
||||
}
|
||||
std::string stdProp = lang + "_STANDARD";
|
||||
cmProp standardProp = target->GetProperty(stdProp);
|
||||
cmProp standardProp = target->GetLanguageStandard(lang, config);
|
||||
if (!standardProp) {
|
||||
if (ext) {
|
||||
// No language standard is specified and extensions are not disabled.
|
||||
@@ -2227,7 +2195,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
|
||||
|
||||
std::string const type = ext ? "EXTENSION" : "STANDARD";
|
||||
|
||||
if (target->GetPropertyAsBool(lang + "_STANDARD_REQUIRED")) {
|
||||
if (target->GetLanguageStandardRequired(lang)) {
|
||||
std::string option_flag =
|
||||
"CMAKE_" + lang + *standardProp + "_" + type + "_COMPILE_OPTION";
|
||||
|
||||
|
||||
@@ -123,7 +123,8 @@ public:
|
||||
const std::string& config);
|
||||
void AddCompilerRequirementFlag(std::string& flags,
|
||||
cmGeneratorTarget const* target,
|
||||
const std::string& lang);
|
||||
const std::string& lang,
|
||||
const std::string& config);
|
||||
//! Append flags to a string.
|
||||
virtual void AppendFlags(std::string& flags,
|
||||
const std::string& newFlags) const;
|
||||
|
||||
+154
-41
@@ -39,6 +39,7 @@
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorExpressionEvaluationFile.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmInstallGenerator.h" // IWYU pragma: keep
|
||||
#include "cmInstallSubdirectoryGenerator.h"
|
||||
@@ -4673,7 +4674,33 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
|
||||
}
|
||||
|
||||
std::string lang;
|
||||
if (!this->CompileFeatureKnown(target->GetName(), feature, lang, error)) {
|
||||
if (!this->CheckCompileFeaturesAvailable(target->GetName(), feature, lang,
|
||||
error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
target->AppendProperty("COMPILE_FEATURES", feature);
|
||||
|
||||
// FIXME: Add a policy to avoid updating the <LANG>_STANDARD target
|
||||
// property due to COMPILE_FEATURES. The language standard selection
|
||||
// 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.
|
||||
if (lang == "C" || lang == "OBJC") {
|
||||
return this->AddRequiredTargetCFeature(target, feature, lang, error);
|
||||
}
|
||||
if (lang == "CUDA") {
|
||||
return this->AddRequiredTargetCudaFeature(target, feature, lang, error);
|
||||
}
|
||||
return this->AddRequiredTargetCxxFeature(target, feature, lang, error);
|
||||
}
|
||||
|
||||
bool cmMakefile::CheckCompileFeaturesAvailable(const std::string& targetName,
|
||||
const std::string& feature,
|
||||
std::string& lang,
|
||||
std::string* error) const
|
||||
{
|
||||
if (!this->CompileFeatureKnown(targetName, feature, lang, error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4699,15 +4726,7 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
|
||||
return false;
|
||||
}
|
||||
|
||||
target->AppendProperty("COMPILE_FEATURES", feature);
|
||||
|
||||
if (lang == "C" || lang == "OBJC") {
|
||||
return this->AddRequiredTargetCFeature(target, feature, lang, error);
|
||||
}
|
||||
if (lang == "CUDA") {
|
||||
return this->AddRequiredTargetCudaFeature(target, feature, lang, error);
|
||||
}
|
||||
return this->AddRequiredTargetCxxFeature(target, feature, lang, error);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmMakefile::CompileFeatureKnown(const std::string& targetName,
|
||||
@@ -4802,22 +4821,50 @@ const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang,
|
||||
return featuresKnown;
|
||||
}
|
||||
|
||||
bool cmMakefile::HaveStandardAvailable(cmTarget const* target,
|
||||
bool cmMakefile::GetNewRequiredStandard(const std::string& targetName,
|
||||
const std::string& feature,
|
||||
cmProp currentLangStandardValue,
|
||||
std::string& newRequiredStandard,
|
||||
std::string* error) const
|
||||
{
|
||||
std::string lang;
|
||||
if (!this->CheckCompileFeaturesAvailable(targetName, feature, lang, error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lang == "C" || lang == "OBJC") {
|
||||
return this->GetNewRequiredCStandard(targetName, feature, lang,
|
||||
currentLangStandardValue,
|
||||
newRequiredStandard, error);
|
||||
}
|
||||
if (lang == "CUDA") {
|
||||
return this->GetNewRequiredCudaStandard(targetName, feature, lang,
|
||||
currentLangStandardValue,
|
||||
newRequiredStandard, error);
|
||||
}
|
||||
return this->GetNewRequiredCxxStandard(targetName, feature, lang,
|
||||
currentLangStandardValue,
|
||||
newRequiredStandard, error);
|
||||
}
|
||||
|
||||
bool cmMakefile::HaveStandardAvailable(cmGeneratorTarget const* target,
|
||||
std::string const& lang,
|
||||
std::string const& config,
|
||||
const std::string& feature) const
|
||||
{
|
||||
if (lang == "C" || lang == "OBJC") {
|
||||
return this->HaveCStandardAvailable(target, feature, lang);
|
||||
return this->HaveCStandardAvailable(target, lang, config, feature);
|
||||
}
|
||||
if (lang == "CUDA") {
|
||||
return this->HaveCudaStandardAvailable(target, feature, lang);
|
||||
return this->HaveCudaStandardAvailable(target, lang, config, feature);
|
||||
}
|
||||
return this->HaveCxxStandardAvailable(target, feature, lang);
|
||||
return this->HaveCxxStandardAvailable(target, lang, config, feature);
|
||||
}
|
||||
|
||||
bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
|
||||
const std::string& feature,
|
||||
std::string const& lang) const
|
||||
bool cmMakefile::HaveCStandardAvailable(cmGeneratorTarget const* target,
|
||||
std::string const& lang,
|
||||
std::string const& config,
|
||||
const std::string& feature) const
|
||||
{
|
||||
cmProp defaultCStandard =
|
||||
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
|
||||
@@ -4846,7 +4893,7 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
|
||||
|
||||
this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
|
||||
|
||||
cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD"));
|
||||
cmProp existingCStandard = target->GetLanguageStandard(lang, config);
|
||||
if (!existingCStandard) {
|
||||
existingCStandard = defaultCStandard;
|
||||
}
|
||||
@@ -4909,9 +4956,10 @@ bool cmMakefile::IsLaterStandard(std::string const& lang,
|
||||
cm::cend(CXX_STANDARDS);
|
||||
}
|
||||
|
||||
bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
|
||||
const std::string& feature,
|
||||
std::string const& lang) const
|
||||
bool cmMakefile::HaveCxxStandardAvailable(cmGeneratorTarget const* target,
|
||||
std::string const& lang,
|
||||
std::string const& config,
|
||||
const std::string& feature) const
|
||||
{
|
||||
cmProp defaultCxxStandard =
|
||||
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
|
||||
@@ -4941,8 +4989,7 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
|
||||
this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
|
||||
needCxx17, needCxx20);
|
||||
|
||||
cmProp existingCxxStandard =
|
||||
target->GetProperty(cmStrCat(lang, "_STANDARD"));
|
||||
cmProp existingCxxStandard = target->GetLanguageStandard(lang, config);
|
||||
if (!existingCxxStandard) {
|
||||
existingCxxStandard = defaultCxxStandard;
|
||||
}
|
||||
@@ -5009,6 +5056,29 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
|
||||
std::string const& lang,
|
||||
std::string* error) const
|
||||
{
|
||||
std::string newRequiredStandard;
|
||||
if (this->GetNewRequiredCxxStandard(
|
||||
target->GetName(), feature, lang,
|
||||
target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard,
|
||||
error)) {
|
||||
if (!newRequiredStandard.empty()) {
|
||||
target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmMakefile::GetNewRequiredCxxStandard(const std::string& targetName,
|
||||
const std::string& feature,
|
||||
std::string const& lang,
|
||||
cmProp currentLangStandardValue,
|
||||
std::string& newRequiredStandard,
|
||||
std::string* error) const
|
||||
{
|
||||
newRequiredStandard.clear();
|
||||
|
||||
bool needCxx98 = false;
|
||||
bool needCxx11 = false;
|
||||
bool needCxx14 = false;
|
||||
@@ -5018,8 +5088,7 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
|
||||
this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
|
||||
needCxx17, needCxx20);
|
||||
|
||||
cmProp existingCxxStandard =
|
||||
target->GetProperty(cmStrCat(lang, "_STANDARD"));
|
||||
cmProp existingCxxStandard = currentLangStandardValue;
|
||||
if (existingCxxStandard == nullptr) {
|
||||
cmProp defaultCxxStandard =
|
||||
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
|
||||
@@ -5034,7 +5103,7 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
|
||||
cmStrCmp(*existingCxxStandard));
|
||||
if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
|
||||
const std::string e = cmStrCat(
|
||||
"The ", lang, "_STANDARD property on target \"", target->GetName(),
|
||||
"The ", lang, "_STANDARD property on target \"", targetName,
|
||||
"\" contained an invalid value: \"", *existingCxxStandard, "\".");
|
||||
if (error) {
|
||||
*error = e;
|
||||
@@ -5060,16 +5129,17 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
|
||||
// Ensure the C++ language level is high enough to support
|
||||
// the needed C++ features.
|
||||
if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
|
||||
target->SetProperty(cmStrCat(lang, "_STANDARD"), *needCxxLevel);
|
||||
newRequiredStandard = *needCxxLevel;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target,
|
||||
const std::string& feature,
|
||||
std::string const& lang) const
|
||||
bool cmMakefile::HaveCudaStandardAvailable(cmGeneratorTarget const* target,
|
||||
std::string const& lang,
|
||||
std::string const& config,
|
||||
const std::string& feature) const
|
||||
{
|
||||
cmProp defaultCudaStandard =
|
||||
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
|
||||
@@ -5100,8 +5170,7 @@ bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target,
|
||||
this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11,
|
||||
needCuda14, needCuda17, needCuda20);
|
||||
|
||||
cmProp existingCudaStandard =
|
||||
target->GetProperty(cmStrCat(lang, "_STANDARD"));
|
||||
cmProp existingCudaStandard = target->GetLanguageStandard(lang, config);
|
||||
if (!existingCudaStandard) {
|
||||
existingCudaStandard = defaultCudaStandard;
|
||||
}
|
||||
@@ -5168,6 +5237,28 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target,
|
||||
std::string const& lang,
|
||||
std::string* error) const
|
||||
{
|
||||
std::string newRequiredStandard;
|
||||
if (this->GetNewRequiredCudaStandard(
|
||||
target->GetName(), feature, lang,
|
||||
target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard,
|
||||
error)) {
|
||||
if (!newRequiredStandard.empty()) {
|
||||
target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmMakefile::GetNewRequiredCudaStandard(const std::string& targetName,
|
||||
const std::string& feature,
|
||||
std::string const& lang,
|
||||
cmProp currentLangStandardValue,
|
||||
std::string& newRequiredStandard,
|
||||
std::string* error) const
|
||||
{
|
||||
newRequiredStandard.clear();
|
||||
|
||||
bool needCuda03 = false;
|
||||
bool needCuda11 = false;
|
||||
bool needCuda14 = false;
|
||||
@@ -5177,8 +5268,7 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target,
|
||||
this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11,
|
||||
needCuda14, needCuda17, needCuda20);
|
||||
|
||||
cmProp existingCudaStandard =
|
||||
target->GetProperty(cmStrCat(lang, "_STANDARD"));
|
||||
cmProp existingCudaStandard = currentLangStandardValue;
|
||||
if (existingCudaStandard == nullptr) {
|
||||
cmProp defaultCudaStandard =
|
||||
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
|
||||
@@ -5193,7 +5283,7 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target,
|
||||
cmStrCmp(*existingCudaStandard));
|
||||
if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) {
|
||||
const std::string e = cmStrCat(
|
||||
"The ", lang, "_STANDARD property on target \"", target->GetName(),
|
||||
"The ", lang, "_STANDARD property on target \"", targetName,
|
||||
"\" contained an invalid value: \"", *existingCudaStandard, "\".");
|
||||
if (error) {
|
||||
*error = e;
|
||||
@@ -5219,7 +5309,7 @@ bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target,
|
||||
// Ensure the CUDA language level is high enough to support
|
||||
// the needed CUDA features.
|
||||
if (!existingCudaLevel || existingCudaLevel < needCudaLevel) {
|
||||
target->SetProperty("CUDA_STANDARD", *needCudaLevel);
|
||||
newRequiredStandard = *needCudaLevel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5252,13 +5342,36 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
|
||||
std::string const& lang,
|
||||
std::string* error) const
|
||||
{
|
||||
std::string newRequiredStandard;
|
||||
if (this->GetNewRequiredCStandard(
|
||||
target->GetName(), feature, lang,
|
||||
target->GetProperty(cmStrCat(lang, "_STANDARD")), newRequiredStandard,
|
||||
error)) {
|
||||
if (!newRequiredStandard.empty()) {
|
||||
target->SetProperty(cmStrCat(lang, "_STANDARD"), newRequiredStandard);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmMakefile::GetNewRequiredCStandard(const std::string& targetName,
|
||||
const std::string& feature,
|
||||
std::string const& lang,
|
||||
cmProp currentLangStandardValue,
|
||||
std::string& newRequiredStandard,
|
||||
std::string* error) const
|
||||
{
|
||||
newRequiredStandard.clear();
|
||||
|
||||
bool needC90 = false;
|
||||
bool needC99 = false;
|
||||
bool needC11 = false;
|
||||
|
||||
this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
|
||||
|
||||
cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD"));
|
||||
cmProp existingCStandard = currentLangStandardValue;
|
||||
if (existingCStandard == nullptr) {
|
||||
cmProp defaultCStandard =
|
||||
this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
|
||||
@@ -5270,7 +5383,7 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
|
||||
if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
|
||||
cmStrCmp(*existingCStandard)) == cm::cend(C_STANDARDS)) {
|
||||
const std::string e = cmStrCat(
|
||||
"The ", lang, "_STANDARD property on target \"", target->GetName(),
|
||||
"The ", lang, "_STANDARD property on target \"", targetName,
|
||||
"\" contained an invalid value: \"", *existingCStandard, "\".");
|
||||
if (error) {
|
||||
*error = e;
|
||||
@@ -5307,11 +5420,11 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
|
||||
}
|
||||
|
||||
if (setC11) {
|
||||
target->SetProperty(cmStrCat(lang, "_STANDARD"), "11");
|
||||
newRequiredStandard = "11";
|
||||
} else if (setC99) {
|
||||
target->SetProperty(cmStrCat(lang, "_STANDARD"), "99");
|
||||
newRequiredStandard = "99";
|
||||
} else if (setC90) {
|
||||
target->SetProperty(cmStrCat(lang, "_STANDARD"), "90");
|
||||
newRequiredStandard = "90";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+45
-9
@@ -47,6 +47,7 @@ class cmExpandedCommandArgument;
|
||||
class cmExportBuildFileGenerator;
|
||||
class cmFunctionBlocker;
|
||||
class cmGeneratorExpressionEvaluationFile;
|
||||
class cmGeneratorTarget;
|
||||
class cmGlobalGenerator;
|
||||
class cmImplicitDependsList;
|
||||
class cmInstallGenerator;
|
||||
@@ -935,7 +936,15 @@ public:
|
||||
const char* CompileFeaturesAvailable(const std::string& lang,
|
||||
std::string* error) const;
|
||||
|
||||
bool HaveStandardAvailable(cmTarget const* target, std::string const& lang,
|
||||
bool GetNewRequiredStandard(const std::string& targetName,
|
||||
const std::string& feature,
|
||||
cmProp currentLangStandardValue,
|
||||
std::string& newRequiredStandard,
|
||||
std::string* error = nullptr) const;
|
||||
|
||||
bool HaveStandardAvailable(cmGeneratorTarget const* target,
|
||||
std::string const& lang,
|
||||
std::string const& config,
|
||||
const std::string& feature) const;
|
||||
|
||||
bool IsLaterStandard(std::string const& lang, std::string const& lhs,
|
||||
@@ -1175,6 +1184,11 @@ private:
|
||||
std::string const& lang,
|
||||
std::string* error = nullptr) const;
|
||||
|
||||
bool CheckCompileFeaturesAvailable(const std::string& targetName,
|
||||
const std::string& feature,
|
||||
std::string& lang,
|
||||
std::string* error) const;
|
||||
|
||||
void CheckNeededCLanguage(const std::string& feature,
|
||||
std::string const& lang, bool& needC90,
|
||||
bool& needC99, bool& needC11) const;
|
||||
@@ -1187,15 +1201,37 @@ private:
|
||||
bool& needCuda11, bool& needCuda14,
|
||||
bool& needCuda17, bool& needCuda20) const;
|
||||
|
||||
bool HaveCStandardAvailable(cmTarget const* target,
|
||||
const std::string& feature,
|
||||
std::string const& lang) const;
|
||||
bool HaveCxxStandardAvailable(cmTarget const* target,
|
||||
const std::string& feature,
|
||||
std::string const& lang) const;
|
||||
bool HaveCudaStandardAvailable(cmTarget const* target,
|
||||
bool GetNewRequiredCStandard(const std::string& targetName,
|
||||
const std::string& feature,
|
||||
std::string const& lang,
|
||||
cmProp currentLangStandardValue,
|
||||
std::string& newRequiredStandard,
|
||||
std::string* error = nullptr) const;
|
||||
bool GetNewRequiredCxxStandard(const std::string& targetName,
|
||||
const std::string& feature,
|
||||
std::string const& lang) const;
|
||||
std::string const& lang,
|
||||
cmProp currentLangStandardValue,
|
||||
std::string& newRequiredStandard,
|
||||
std::string* error = nullptr) const;
|
||||
bool GetNewRequiredCudaStandard(const std::string& targetName,
|
||||
const std::string& feature,
|
||||
std::string const& lang,
|
||||
cmProp currentLangStandardValue,
|
||||
std::string& newRequiredStandard,
|
||||
std::string* error = nullptr) const;
|
||||
|
||||
bool HaveCStandardAvailable(cmGeneratorTarget const* target,
|
||||
std::string const& lang,
|
||||
std::string const& config,
|
||||
const std::string& feature) const;
|
||||
bool HaveCxxStandardAvailable(cmGeneratorTarget const* target,
|
||||
std::string const& lang,
|
||||
std::string const& config,
|
||||
const std::string& feature) const;
|
||||
bool HaveCudaStandardAvailable(cmGeneratorTarget const* target,
|
||||
std::string const& lang,
|
||||
std::string const& config,
|
||||
const std::string& feature) const;
|
||||
|
||||
void CheckForUnusedVariables() const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user