Browse Source

cmMakefile: Refactor determining a targets C++ standard level

The original code doesn't scale well as we add support for each new
language level.

Co-Author: Brad King <[email protected]>
Robert Maynard 8 years ago
parent
commit
1d2d9c18bd
1 changed files with 36 additions and 73 deletions
  1. 36 73
      Source/cmMakefile.cxx

+ 36 - 73
Source/cmMakefile.cxx

@@ -4401,8 +4401,10 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
     existingCxxStandard = defaultCxxStandard;
   }
 
-  if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
-                   cmStrCmp(existingCxxStandard)) == cm::cend(CXX_STANDARDS)) {
+  const char* const* existingCxxLevel =
+    std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+                 cmStrCmp(existingCxxStandard));
+  if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
     std::ostringstream e;
     e << "The CXX_STANDARD property on target \"" << target->GetName()
       << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
@@ -4410,32 +4412,16 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
     return false;
   }
 
-  const char* const* existingCxxIt = existingCxxStandard
-    ? std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
-                   cmStrCmp(existingCxxStandard))
-    : cm::cend(CXX_STANDARDS);
+  /* clang-format off */
+  const char* const* needCxxLevel =
+    needCxx17 ? &CXX_STANDARDS[3]
+    : needCxx14 ? &CXX_STANDARDS[2]
+    : needCxx11 ? &CXX_STANDARDS[1]
+    : needCxx98 ? &CXX_STANDARDS[0]
+    : nullptr;
+  /* clang-format on */
 
-  if (needCxx17 &&
-      existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
-                                   cm::cend(CXX_STANDARDS), cmStrCmp("17"))) {
-    return false;
-  }
-  if (needCxx14 &&
-      existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
-                                   cm::cend(CXX_STANDARDS), cmStrCmp("14"))) {
-    return false;
-  }
-  if (needCxx11 &&
-      existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
-                                   cm::cend(CXX_STANDARDS), cmStrCmp("11"))) {
-    return false;
-  }
-  if (needCxx98 &&
-      existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
-                                   cm::cend(CXX_STANDARDS), cmStrCmp("98"))) {
-    return false;
-  }
-  return true;
+  return !needCxxLevel || needCxxLevel <= existingCxxLevel;
 }
 
 void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
@@ -4481,10 +4467,12 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
                                needCxx17);
 
   const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
+  const char* const* existingCxxLevel = nullptr;
   if (existingCxxStandard) {
-    if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
-                     cmStrCmp(existingCxxStandard)) ==
-        cm::cend(CXX_STANDARDS)) {
+    existingCxxLevel =
+      std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+                   cmStrCmp(existingCxxStandard));
+    if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
       std::ostringstream e;
       e << "The CXX_STANDARD property on target \"" << target->GetName()
         << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
@@ -4497,50 +4485,25 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
       return false;
     }
   }
-  const char* const* existingCxxIt = existingCxxStandard
-    ? std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
-                   cmStrCmp(existingCxxStandard))
-    : cm::cend(CXX_STANDARDS);
-
-  bool setCxx98 = needCxx98 && !existingCxxStandard;
-  bool setCxx11 = needCxx11 && !existingCxxStandard;
-  bool setCxx14 = needCxx14 && !existingCxxStandard;
-  bool setCxx17 = needCxx17 && !existingCxxStandard;
-
-  if (needCxx17 && existingCxxStandard &&
-      existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
-                                   cm::cend(CXX_STANDARDS), cmStrCmp("17"))) {
-    setCxx17 = true;
-  } else if (needCxx14 && existingCxxStandard &&
-             existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
-                                          cm::cend(CXX_STANDARDS),
-                                          cmStrCmp("14"))) {
-    setCxx14 = true;
-  } else if (needCxx11 && existingCxxStandard &&
-             existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
-                                          cm::cend(CXX_STANDARDS),
-                                          cmStrCmp("11"))) {
-    setCxx11 = true;
-  } else if (needCxx98 && existingCxxStandard &&
-             existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
-                                          cm::cend(CXX_STANDARDS),
-                                          cmStrCmp("98"))) {
-    setCxx98 = true;
-  }
-
-  if (setCxx17) {
-    target->SetProperty("CXX_STANDARD", "17");
-    target->SetProperty("CUDA_STANDARD", "17");
-  } else if (setCxx14) {
-    target->SetProperty("CXX_STANDARD", "14");
-    target->SetProperty("CUDA_STANDARD", "14");
-  } else if (setCxx11) {
-    target->SetProperty("CXX_STANDARD", "11");
-    target->SetProperty("CUDA_STANDARD", "11");
-  } else if (setCxx98) {
-    target->SetProperty("CXX_STANDARD", "98");
-    target->SetProperty("CUDA_STANDARD", "98");
+
+  /* clang-format off */
+  const char* const* needCxxLevel =
+    needCxx17 ? &CXX_STANDARDS[3]
+    : needCxx14 ? &CXX_STANDARDS[2]
+    : needCxx11 ? &CXX_STANDARDS[1]
+    : needCxx98 ? &CXX_STANDARDS[0]
+    : nullptr;
+  /* clang-format on */
+
+  if (needCxxLevel) {
+    // Ensure the C++ language level is high enough to support
+    // the needed C++ features.
+    if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
+      target->SetProperty("CXX_STANDARD", *needCxxLevel);
+      target->SetProperty("CUDA_STANDARD", *needCxxLevel);
+    }
   }
+
   return true;
 }