diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index c46cab8fe8b8b5661cf9a9dc44df5a4bb02b8137..269aa69c36ffc33b9c2c223be0d5c601d4d92c51 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -19,6 +19,7 @@
 #include "cmOutputConverter.h"
 #include "cmMakefile.h"
 #include "cmTarget.h"
+#include "cmGeneratorTarget.h"
 #include "cmake.h"
 #include "cmAlgorithms.h"
 
@@ -579,8 +580,12 @@ bool cmComputeLinkInformation::Compute()
 //----------------------------------------------------------------------------
 void cmComputeLinkInformation::AddImplicitLinkInfo()
 {
+  cmGeneratorTarget *gtgt = this->Target->GetMakefile()
+                                ->GetGlobalGenerator()
+                                ->GetGeneratorTarget(this->Target);
+
   // The link closure lists all languages whose implicit info is needed.
-  cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config);
+  cmGeneratorTarget::LinkClosure const* lc=gtgt->GetLinkClosure(this->Config);
   for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
       li != lc->Languages.end(); ++li)
     {
@@ -2006,8 +2011,12 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
   // Add runtime paths required by the languages to always be
   // present.  This is done even when skipping rpath support.
   {
-  cmTarget::LinkClosure const* lc =
-    this->Target->GetLinkClosure(this->Config);
+  cmGeneratorTarget *gtgt = this->Makefile
+                                ->GetGlobalGenerator()
+                                ->GetGeneratorTarget(this->Target);
+
+  cmGeneratorTarget::LinkClosure const* lc =
+    gtgt->GetLinkClosure(this->Config);
   for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
       li != lc->Languages.end(); ++li)
     {
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 3afbb92b61f4806790de440c241168a7d4b4dfeb..2d7a5a5cf3e939a3c51c582cc9076819cd9c9ec4 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -20,6 +20,7 @@ class cmake;
 class cmGlobalGenerator;
 class cmMakefile;
 class cmTarget;
+class cmGeneratorTarget;
 class cmOrderDirectories;
 
 /** \class cmComputeLinkInformation
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 4de5e9c40134596dda658639e8087c97099e5e7b..c31437233ba9de40f2ffba2713267b8d037c56fb 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -27,6 +27,13 @@
 #include <errno.h>
 #include "assert.h"
 
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+#include <cmsys/hash_set.hxx>
+#define UNORDERED_SET cmsys::hash_set
+#else
+#define UNORDERED_SET std::set
+#endif
+
 //----------------------------------------------------------------------------
 void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib,
                      cmTarget *target, cmake *cm)
@@ -1025,6 +1032,223 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const
     }
 }
 
+//----------------------------------------------------------------------------
+class cmTargetCollectLinkLanguages
+{
+public:
+  cmTargetCollectLinkLanguages(cmGeneratorTarget const* target,
+                               const std::string& config,
+                               UNORDERED_SET<std::string>& languages,
+                               cmTarget const* head):
+    Config(config), Languages(languages), HeadTarget(head),
+    Makefile(target->Target->GetMakefile()), Target(target)
+  { this->Visited.insert(target->Target); }
+
+  void Visit(cmLinkItem const& item)
+    {
+    if(!item.Target)
+      {
+      if(item.find("::") != std::string::npos)
+        {
+        bool noMessage = false;
+        cmake::MessageType messageType = cmake::FATAL_ERROR;
+        std::stringstream e;
+        switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0028))
+          {
+          case cmPolicies::WARN:
+            {
+            e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n";
+            messageType = cmake::AUTHOR_WARNING;
+            }
+            break;
+          case cmPolicies::OLD:
+            noMessage = true;
+          case cmPolicies::REQUIRED_IF_USED:
+          case cmPolicies::REQUIRED_ALWAYS:
+          case cmPolicies::NEW:
+            // Issue the fatal message.
+            break;
+          }
+
+        if(!noMessage)
+          {
+          e << "Target \"" << this->Target->GetName()
+            << "\" links to target \"" << item
+            << "\" but the target was not found.  Perhaps a find_package() "
+            "call is missing for an IMPORTED target, or an ALIAS target is "
+            "missing?";
+          this->Makefile->GetCMakeInstance()->IssueMessage(
+            messageType, e.str(), this->Target->Target->GetBacktrace());
+          }
+        }
+      return;
+      }
+    if(!this->Visited.insert(item.Target).second)
+      {
+      return;
+      }
+
+    cmTarget::LinkInterface const* iface =
+      item.Target->GetLinkInterface(this->Config, this->HeadTarget);
+    if(!iface) { return; }
+
+    for(std::vector<std::string>::const_iterator
+          li = iface->Languages.begin(); li != iface->Languages.end(); ++li)
+      {
+      this->Languages.insert(*li);
+      }
+
+    for(std::vector<cmLinkItem>::const_iterator
+          li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li)
+      {
+      this->Visit(*li);
+      }
+    }
+private:
+  std::string Config;
+  UNORDERED_SET<std::string>& Languages;
+  cmTarget const* HeadTarget;
+  cmMakefile* Makefile;
+  const cmGeneratorTarget* Target;
+  std::set<cmTarget const*> Visited;
+};
+
+//----------------------------------------------------------------------------
+cmGeneratorTarget::LinkClosure const*
+cmGeneratorTarget::GetLinkClosure(const std::string& config) const
+{
+  std::string key(cmSystemTools::UpperCase(config));
+  LinkClosureMapType::iterator
+    i = this->LinkClosureMap.find(key);
+  if(i == this->LinkClosureMap.end())
+    {
+    LinkClosure lc;
+    this->ComputeLinkClosure(config, lc);
+    LinkClosureMapType::value_type entry(key, lc);
+    i = this->LinkClosureMap.insert(entry).first;
+    }
+  return &i->second;
+}
+
+//----------------------------------------------------------------------------
+class cmTargetSelectLinker
+{
+  int Preference;
+  cmGeneratorTarget const* Target;
+  cmMakefile* Makefile;
+  cmGlobalGenerator* GG;
+  std::set<std::string> Preferred;
+public:
+  cmTargetSelectLinker(cmGeneratorTarget const* target)
+      : Preference(0), Target(target)
+    {
+    this->Makefile = this->Target->Makefile;
+    this->GG = this->Makefile->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)
+      {
+      std::stringstream e;
+      e << "Target " << this->Target->GetName()
+        << " contains multiple languages with the highest linker preference"
+        << " (" << this->Preference << "):\n";
+      for(std::set<std::string>::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->Target->GetBacktrace());
+      }
+    return *this->Preferred.begin();
+    }
+};
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
+                                           LinkClosure& lc) const
+{
+  // Get languages built in this target.
+  UNORDERED_SET<std::string> languages;
+  cmTarget::LinkImplementation const* impl =
+                            this->Target->GetLinkImplementation(config);
+  for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
+      li != impl->Languages.end(); ++li)
+    {
+    languages.insert(*li);
+    }
+
+  // Add interface languages from linked targets.
+  cmTargetCollectLinkLanguages cll(this, config, languages, this->Target);
+  for(std::vector<cmLinkImplItem>::const_iterator li = impl->Libraries.begin();
+      li != impl->Libraries.end(); ++li)
+    {
+    cll.Visit(*li);
+    }
+
+  // Store the transitive closure of languages.
+  for(UNORDERED_SET<std::string>::const_iterator li = languages.begin();
+      li != languages.end(); ++li)
+    {
+    lc.Languages.push_back(*li);
+    }
+
+  // Choose the language whose linker should be used.
+  if(this->GetProperty("HAS_CXX"))
+    {
+    lc.LinkerLanguage = "CXX";
+    }
+  else if(const char* linkerLang = this->GetProperty("LINKER_LANGUAGE"))
+    {
+    lc.LinkerLanguage = linkerLang;
+    }
+  else
+    {
+    // Find the language with the highest preference value.
+    cmTargetSelectLinker tsl(this);
+
+    // First select from the languages compiled directly in this target.
+    for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
+        li != impl->Languages.end(); ++li)
+      {
+      tsl.Consider(li->c_str());
+      }
+
+    // Now consider languages that propagate from linked targets.
+    for(UNORDERED_SET<std::string>::const_iterator sit = languages.begin();
+        sit != languages.end(); ++sit)
+      {
+      std::string propagates = "CMAKE_"+*sit+"_LINKER_PREFERENCE_PROPAGATES";
+      if(this->Makefile->IsOn(propagates))
+        {
+        tsl.Consider(sit->c_str());
+        }
+      }
+
+    lc.LinkerLanguage = tsl.Choose();
+    }
+}
+
 //----------------------------------------------------------------------------
 void cmGeneratorTarget::GetFullNameComponents(std::string& prefix,
                                               std::string& base,
@@ -2058,7 +2282,7 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
 std::string
 cmGeneratorTarget::GetLinkerLanguage(const std::string& config) const
 {
-  return this->Target->GetLinkClosure(config)->LinkerLanguage;
+  return this->GetLinkClosure(config)->LinkerLanguage;
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 41fb8487d41ffee2b51afd799576d4b1ea0e6d0e..a1193a63ef97d4e83da4f12a78dddd0be24dc960 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -165,6 +165,20 @@ public:
 
   std::string GetModuleDefinitionFile(const std::string& config) const;
 
+  /** Link information from the transitive closure of the link
+      implementation and the interfaces of its dependencies.  */
+  struct LinkClosure
+  {
+    // The preferred linker language.
+    std::string LinkerLanguage;
+
+    // Languages whose runtime libraries must be linked.
+    std::vector<std::string> Languages;
+  };
+
+  LinkClosure const* GetLinkClosure(const std::string& config) const;
+  void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
+
   /** Full path with trailing slash to the top-level directory
       holding object files for this target.  Includes the build
       time config name placeholder if needed for the generator.  */
@@ -301,6 +315,9 @@ private:
                            std::string& outPrefix, std::string& outBase,
                            std::string& outSuffix) const;
 
+  typedef std::map<std::string, LinkClosure> LinkClosureMapType;
+  mutable LinkClosureMapType LinkClosureMap;
+
   struct CompatibleInterfacesBase
   {
     std::set<std::string> PropsBool;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index c7118dc5d47225df01dd2d6210ac4aa9762f9831..62aa12a26e837715deb9e0f932f7a20eed082877 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -160,9 +160,6 @@ public:
                    HeadToLinkImplementationMap> LinkImplMapType;
   LinkImplMapType LinkImplMap;
 
-  typedef std::map<std::string, cmTarget::LinkClosure> LinkClosureMapType;
-  LinkClosureMapType LinkClosureMap;
-
   typedef std::map<std::string, std::vector<cmSourceFile*> >
                                                        SourceFilesMapType;
   SourceFilesMapType SourceFilesMap;
@@ -511,7 +508,6 @@ void cmTarget::ClearLinkMaps()
   this->Internal->LinkImplMap.clear();
   this->Internal->LinkInterfaceMap.clear();
   this->Internal->LinkInterfaceUsageRequirementsOnlyMap.clear();
-  this->Internal->LinkClosureMap.clear();
   this->Internal->SourceFilesMap.clear();
 }
 
@@ -3135,223 +3131,6 @@ bool cmTarget::GetPropertyAsBool(const std::string& prop) const
   return cmSystemTools::IsOn(this->GetProperty(prop));
 }
 
-//----------------------------------------------------------------------------
-class cmTargetCollectLinkLanguages
-{
-public:
-  cmTargetCollectLinkLanguages(cmTarget const* target,
-                               const std::string& config,
-                               UNORDERED_SET<std::string>& languages,
-                               cmTarget const* head):
-    Config(config), Languages(languages), HeadTarget(head),
-    Makefile(target->GetMakefile()), Target(target)
-  { this->Visited.insert(target); }
-
-  void Visit(cmLinkItem const& item)
-    {
-    if(!item.Target)
-      {
-      if(item.find("::") != std::string::npos)
-        {
-        bool noMessage = false;
-        cmake::MessageType messageType = cmake::FATAL_ERROR;
-        std::ostringstream e;
-        switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0028))
-          {
-          case cmPolicies::WARN:
-            {
-            e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n";
-            messageType = cmake::AUTHOR_WARNING;
-            }
-            break;
-          case cmPolicies::OLD:
-            noMessage = true;
-          case cmPolicies::REQUIRED_IF_USED:
-          case cmPolicies::REQUIRED_ALWAYS:
-          case cmPolicies::NEW:
-            // Issue the fatal message.
-            break;
-          }
-
-        if(!noMessage)
-          {
-          e << "Target \"" << this->Target->GetName()
-            << "\" links to target \"" << item
-            << "\" but the target was not found.  Perhaps a find_package() "
-            "call is missing for an IMPORTED target, or an ALIAS target is "
-            "missing?";
-          this->Makefile->GetCMakeInstance()->IssueMessage(messageType,
-                                                e.str(),
-                                                this->Target->GetBacktrace());
-          }
-        }
-      return;
-      }
-    if(!this->Visited.insert(item.Target).second)
-      {
-      return;
-      }
-
-    cmTarget::LinkInterface const* iface =
-      item.Target->GetLinkInterface(this->Config, this->HeadTarget);
-    if(!iface) { return; }
-
-    for(std::vector<std::string>::const_iterator
-          li = iface->Languages.begin(); li != iface->Languages.end(); ++li)
-      {
-      this->Languages.insert(*li);
-      }
-
-    for(std::vector<cmLinkItem>::const_iterator
-          li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li)
-      {
-      this->Visit(*li);
-      }
-    }
-private:
-  std::string Config;
-  UNORDERED_SET<std::string>& Languages;
-  cmTarget const* HeadTarget;
-  cmMakefile* Makefile;
-  const cmTarget* Target;
-  std::set<cmTarget const*> Visited;
-};
-
-//----------------------------------------------------------------------------
-cmTarget::LinkClosure const*
-cmTarget::GetLinkClosure(const std::string& config) const
-{
-  std::string key(cmSystemTools::UpperCase(config));
-  cmTargetInternals::LinkClosureMapType::iterator
-    i = this->Internal->LinkClosureMap.find(key);
-  if(i == this->Internal->LinkClosureMap.end())
-    {
-    LinkClosure lc;
-    this->ComputeLinkClosure(config, lc);
-    cmTargetInternals::LinkClosureMapType::value_type entry(key, lc);
-    i = this->Internal->LinkClosureMap.insert(entry).first;
-    }
-  return &i->second;
-}
-
-//----------------------------------------------------------------------------
-class cmTargetSelectLinker
-{
-  int Preference;
-  cmTarget const* Target;
-  cmMakefile* Makefile;
-  cmGlobalGenerator* GG;
-  UNORDERED_SET<std::string> Preferred;
-public:
-  cmTargetSelectLinker(cmTarget const* target): Preference(0), Target(target)
-    {
-    this->Makefile = this->Target->GetMakefile();
-    this->GG = this->Makefile->GetGlobalGenerator();
-    }
-  void Consider(const std::string& 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)
-      {
-      std::ostringstream e;
-      e << "Target " << this->Target->GetName()
-        << " contains multiple languages with the highest linker preference"
-        << " (" << this->Preference << "):\n";
-      for(UNORDERED_SET<std::string>::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 std::string& config,
-                                  LinkClosure& lc) const
-{
-  // Get languages built in this target.
-  UNORDERED_SET<std::string> languages;
-  LinkImplementation const* impl = this->GetLinkImplementation(config);
-  for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
-      li != impl->Languages.end(); ++li)
-    {
-    languages.insert(*li);
-    }
-
-  // Add interface languages from linked targets.
-  cmTargetCollectLinkLanguages cll(this, config, languages, this);
-  for(std::vector<cmLinkImplItem>::const_iterator
-        li = impl->Libraries.begin();
-      li != impl->Libraries.end(); ++li)
-    {
-    cll.Visit(*li);
-    }
-
-  // Store the transitive closure of languages.
-  for(UNORDERED_SET<std::string>::const_iterator li = languages.begin();
-      li != languages.end(); ++li)
-    {
-    lc.Languages.push_back(*li);
-    }
-
-  // Choose the language whose linker should be used.
-  if(this->GetProperty("HAS_CXX"))
-    {
-    lc.LinkerLanguage = "CXX";
-    }
-  else if(const char* linkerLang = this->GetProperty("LINKER_LANGUAGE"))
-    {
-    lc.LinkerLanguage = linkerLang;
-    }
-  else
-    {
-    // Find the language with the highest preference value.
-    cmTargetSelectLinker tsl(this);
-
-    // First select from the languages compiled directly in this target.
-    for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
-        li != impl->Languages.end(); ++li)
-      {
-      tsl.Consider(*li);
-      }
-
-    // Now consider languages that propagate from linked targets.
-    for(UNORDERED_SET<std::string>::const_iterator sit = languages.begin();
-        sit != languages.end(); ++sit)
-      {
-      std::string propagates = "CMAKE_"+*sit+"_LINKER_PREFERENCE_PROPAGATES";
-      if(this->Makefile->IsOn(propagates))
-        {
-        tsl.Consider(*sit);
-        }
-      }
-
-    lc.LinkerLanguage = tsl.Choose();
-    }
-}
-
 //----------------------------------------------------------------------------
 void cmTarget::ExpandLinkItems(std::string const& prop,
                                std::string const& value,
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index dea9bef56940ad42b84e794756e5faa52d856c18..9a4915ff04084ef63ef8a50887e341e48b0249d0 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -315,18 +315,6 @@ public:
   LinkImplementationLibraries const*
     GetLinkImplementationLibraries(const std::string& config) const;
 
-  /** Link information from the transitive closure of the link
-      implementation and the interfaces of its dependencies.  */
-  struct LinkClosure
-  {
-    // The preferred linker language.
-    std::string LinkerLanguage;
-
-    // Languages whose runtime libraries must be linked.
-    std::vector<std::string> Languages;
-  };
-  LinkClosure const* GetLinkClosure(const std::string& config) const;
-
   cmTarget const* FindTargetToLink(std::string const& name) const;
 
   /** Strip off leading and trailing whitespace from an item named in
@@ -662,7 +650,6 @@ private:
   LinkImplementationLibraries const*
     GetLinkImplementationLibrariesInternal(const std::string& config,
                                            cmTarget const* head) const;
-  void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
 
   void ExpandLinkItems(std::string const& prop, std::string const& value,
                        std::string const& config, cmTarget const* headTarget,