|
|
@@ -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;
|
|
|
+}
|