Преглед изворни кода

Refactor target linker language selection

This factors the decision logic out of cmTarget::ComputeLinkClosure into
dedicated class cmTargetSelectLinker.  We replace several local
variables with a single object instance, and organize code into methods.
Brad King пре 16 година
родитељ
комит
fd633b33cf
1 измењених фајлова са 56 додато и 29 уклоњено
  1. 56 29
      Source/cmTarget.cxx

+ 56 - 29
Source/cmTarget.cxx

@@ -2413,6 +2413,59 @@ cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config)
   return &i->second;
 }
 
+//----------------------------------------------------------------------------
+class cmTargetSelectLinker
+{
+  int Preference;
+  cmTarget* Target;
+  cmMakefile* Makefile;
+  cmGlobalGenerator* GG;
+  std::set<cmStdString> Preferred;
+public:
+  cmTargetSelectLinker(cmTarget* target): Preference(0), Target(target)
+    {
+    this->Makefile = this->Target->GetMakefile();
+    this->GG = this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
+    }
+  void Consider(const char* lang)
+    {
+    int preference = this->GG->GetLinkerPreference(lang);
+    if(preference > this->Preference)
+      {
+      this->Preference = preference;
+      this->Preferred.clear();
+      }
+    if(preference == this->Preference)
+      {
+      this->Preferred.insert(lang);
+      }
+    }
+  std::string Choose()
+    {
+    if(this->Preferred.empty())
+      {
+      return "";
+      }
+    else if(this->Preferred.size() > 1)
+      {
+      cmOStringStream e;
+      e << "Target " << this->Target->GetName()
+        << " contains multiple languages with the highest linker preference"
+        << " (" << this->Preference << "):\n";
+      for(std::set<cmStdString>::const_iterator
+            li = this->Preferred.begin(); li != this->Preferred.end(); ++li)
+        {
+        e << "  " << *li << "\n";
+        }
+      e << "Set the LINKER_LANGUAGE property for this target.";
+      cmake* cm = this->Makefile->GetCMakeInstance();
+      cm->IssueMessage(cmake::FATAL_ERROR, e.str(),
+                       this->Target->GetBacktrace());
+      }
+    return *this->Preferred.begin();
+    }
+};
+
 //----------------------------------------------------------------------------
 void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
 {
@@ -2452,39 +2505,13 @@ void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
   else
     {
     // Find the language with the highest preference value.
-    cmGlobalGenerator* gg =
-      this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
-    std::string linkerLangList;              // only used for the error message
-    int maxLinkerPref = 0;
-    bool multiplePreferedLanguages = false;
+    cmTargetSelectLinker tsl(this);
     for(std::set<cmStdString>::const_iterator sit = languages.begin();
         sit != languages.end(); ++sit)
       {
-      int linkerPref = gg->GetLinkerPreference(sit->c_str());
-      if (lc.LinkerLanguage.empty() || (linkerPref > maxLinkerPref))
-        {
-        maxLinkerPref = linkerPref;
-        lc.LinkerLanguage = *sit;
-        linkerLangList = *sit;
-        multiplePreferedLanguages = false;
-        }
-      else if (linkerPref == maxLinkerPref)
-        {
-        linkerLangList += "; ";
-        linkerLangList += *sit;
-        multiplePreferedLanguages = true;
-        }
-      }
-
-    if (multiplePreferedLanguages)
-      {
-      cmOStringStream err;
-      err << "Error: Target " << this->Name << " contains multiple languages "
-          << "with the highest linker preference (" << maxLinkerPref << "): "
-          << linkerLangList << "\n"
-          << "You must set the LINKER_LANGUAGE property for this target.";
-      cmSystemTools::Error(err.str().c_str());
+      tsl.Consider(sit->c_str());
       }
+    lc.LinkerLanguage = tsl.Choose();
     }
 }