diff options
Diffstat (limited to 'Source/cmMakefile.cxx')
-rw-r--r-- | Source/cmMakefile.cxx | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 1328974..64163de 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -41,6 +41,8 @@ #include <ctype.h> // for isspace #include <assert.h> +#define FOR_EACH_CXX_FEATURE(F) + class cmMakefile::Internals { public: @@ -4494,3 +4496,114 @@ void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm) pm[pid] = this->GetPolicyStatus(pid); } } + +#define FEATURE_STRING(F) , #F + +static const char * const CXX_FEATURES[] = { + 0 + FOR_EACH_CXX_FEATURE(FEATURE_STRING) +}; + +static const char * const CXX_STANDARDS[] = { + "98" + , "11" +}; + +//---------------------------------------------------------------------------- +bool cmMakefile:: +AddRequiredTargetFeature(cmTarget *target, const std::string& feature, + std::string *error) const +{ + bool isCxxFeature = std::find_if(cmArrayBegin(CXX_FEATURES) + 1, + cmArrayEnd(CXX_FEATURES), cmStrCmp(feature)) + != cmArrayEnd(CXX_FEATURES); + if (!isCxxFeature) + { + cmOStringStream e; + e << "specified unknown feature \"" << feature << "\" specified for " + "target \"" << target->GetName() << "\"."; + if (error) + { + *error = e.str(); + } + else + { + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + } + return false; + } + + std::string lang = "CXX"; + + const char* featuresKnown = + this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES"); + + if (!featuresKnown || !*featuresKnown) + { + // We know of no features for the compiler at all. + return true; + } + + std::vector<std::string> availableFeatures; + cmSystemTools::ExpandListArgument(featuresKnown, availableFeatures); + if (std::find(availableFeatures.begin(), + availableFeatures.end(), + feature) == availableFeatures.end()) + { + cmOStringStream e; + e << "The compiler feature \"" << feature + << "\" is not known to compiler\n\"" + << this->GetDefinition("CMAKE_" + lang + "_COMPILER_ID") + << "\"\nversion " + << this->GetDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << "."; + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + + target->AppendProperty("COMPILE_FEATURES", feature.c_str()); + + bool needCxx11 = false; + + if (const char *propCxx11 = + this->GetDefinition("CMAKE_CXX11_COMPILE_FEATURES")) + { + std::vector<std::string> props; + cmSystemTools::ExpandListArgument(propCxx11, props); + needCxx11 = std::find(props.begin(), props.end(), feature) != props.end(); + } + + const char *existingCxxStandard = target->GetProperty("CXX_STANDARD"); + if (existingCxxStandard) + { + if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), + cmStrCmp(existingCxxStandard)) == cmArrayEnd(CXX_STANDARDS)) + { + cmOStringStream e; + e << "The CXX_STANDARD property on target \"" << target->GetName() + << "\" contained an invalid value: \"" << existingCxxStandard << "\"."; + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + } + const char * const *existingCxxIt = existingCxxStandard + ? std::find_if(cmArrayBegin(CXX_STANDARDS), + cmArrayEnd(CXX_STANDARDS), + cmStrCmp(existingCxxStandard)) + : cmArrayEnd(CXX_STANDARDS); + + bool setCxx11 = needCxx11 && !existingCxxStandard; + + if (needCxx11 && existingCxxStandard && existingCxxIt < + std::find_if(cmArrayBegin(CXX_STANDARDS), + cmArrayEnd(CXX_STANDARDS), + cmStrCmp("11"))) + { + setCxx11 = true; + } + + if (setCxx11) + { + target->SetProperty("CXX_STANDARD", "11"); + } + return true; +} |