[Cmake-commits] [cmake-commits] king committed cmTarget.cxx 1.261 1.262 cmTarget.h 1.137 1.138

cmake-commits at cmake.org cmake-commits at cmake.org
Fri Jul 10 13:53:30 EDT 2009


Update of /cvsroot/CMake/CMake/Source
In directory public:/mounts/ram/cvs-serv17992/Source

Modified Files:
	cmTarget.cxx cmTarget.h 
Log Message:
ENH: Consider link dependencies for link language

This teaches cmTarget to account for the languages compiled into link
dependencies when determining the linker language for its target.

We list the languages compiled into a static archive in its link
interface.  Any target linking to it knows that the runtime libraries
for the static archive's languages must be available at link time.  For
now this affects only the linker language selection, but later it will
allow CMake to automatically list the language runtime libraries.


Index: cmTarget.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTarget.h,v
retrieving revision 1.137
retrieving revision 1.138
diff -C 2 -d -r1.137 -r1.138
*** cmTarget.h	8 Jul 2009 17:04:04 -0000	1.137
--- cmTarget.h	10 Jul 2009 17:53:28 -0000	1.138
***************
*** 241,244 ****
--- 241,247 ----
    struct LinkInterface
    {
+     // Languages whose runtime libraries must be linked.
+     std::vector<std::string> Languages;
+ 
      // Libraries listed in the interface.
      std::vector<std::string> Libraries;
***************
*** 260,263 ****
--- 263,269 ----
    struct LinkImplementation
    {
+     // Languages whose runtime libraries must be linked.
+     std::vector<std::string> Languages;
+ 
      // Libraries linked directly in this configuration.
      std::vector<std::string> Libraries;
***************
*** 269,272 ****
--- 275,290 ----
    LinkImplementation const* GetLinkImplementation(const char* config);
  
+   /** 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 char* config);
+ 
    /** Strip off leading and trailing whitespace from an item named in
        the link dependencies of this target.  */
***************
*** 536,539 ****
--- 554,558 ----
    void ComputeLinkImplementation(const char* config,
                                   LinkImplementation& impl);
+   void ComputeLinkClosure(const char* config, LinkClosure& lc);
  
    // The cmMakefile instance that owns this target.  This should

Index: cmTarget.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTarget.cxx,v
retrieving revision 1.261
retrieving revision 1.262
diff -C 2 -d -r1.261 -r1.262
*** cmTarget.cxx	10 Jul 2009 13:12:38 -0000	1.261
--- cmTarget.cxx	10 Jul 2009 17:53:27 -0000	1.262
***************
*** 86,89 ****
--- 86,92 ----
    typedef std::map<cmStdString, cmTarget::LinkImplementation> LinkImplMapType;
    LinkImplMapType LinkImplMap;
+ 
+   typedef std::map<cmStdString, cmTarget::LinkClosure> LinkClosureMapType;
+   LinkClosureMapType LinkClosureMap;
  };
  
***************
*** 2322,2341 ****
  
  //----------------------------------------------------------------------------
! const char* cmTarget::GetLinkerLanguage(const char*)
  {
!   cmGlobalGenerator* gg =
!     this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
!   if(this->GetProperty("HAS_CXX"))
      {
!     const_cast<cmTarget*>(this)->SetProperty("LINKER_LANGUAGE", "CXX");
      }
!   const char* linkerLang = this->GetProperty("LINKER_LANGUAGE");
!   if (linkerLang==0)
      {
!     // if the property has not yet been set, collect all languages in the
!     // target and then find the language with the highest preference value
!     std::set<cmStdString> languages;
!     this->GetLanguages(languages);
  
      std::string linkerLangList;              // only used for the error message
      int maxLinkerPref = 0;
--- 2325,2428 ----
  
  //----------------------------------------------------------------------------
! class cmTargetCollectLinkLanguages
  {
! public:
!   cmTargetCollectLinkLanguages(cmTarget* target, const char* config,
!                                std::set<cmStdString>& languages):
!     Config(config), Languages(languages) { this->Visited.insert(target); }
!   void Visit(cmTarget* target)
      {
!     if(!target || !this->Visited.insert(target).second)
!       {
!       return;
!       }
! 
!     cmTarget::LinkInterface const* iface =
!       target->GetLinkInterface(this->Config);
!     if(!iface) { return; }
! 
!     for(std::vector<std::string>::const_iterator
!           li = iface->Languages.begin(); li != iface->Languages.end(); ++li)
!       {
!       this->Languages.insert(*li);
!       }
! 
!     cmMakefile* mf = target->GetMakefile();
!     for(std::vector<std::string>::const_iterator
!           li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li)
!       {
!       this->Visit(mf->FindTargetToUse(li->c_str()));
!       }
      }
! private:
!   const char* Config;
!   std::set<cmStdString>& Languages;
!   std::set<cmTarget*> Visited;
! };
! 
! //----------------------------------------------------------------------------
! const char* cmTarget::GetLinkerLanguage(const char* config)
! {
!   const char* lang = this->GetLinkClosure(config)->LinkerLanguage.c_str();
!   return *lang? lang : 0;
! }
! 
! //----------------------------------------------------------------------------
! cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config)
! {
!   std::string key = cmSystemTools::UpperCase(config? 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;
! }
  
+ //----------------------------------------------------------------------------
+ void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
+ {
+   // Get languages built in this target.
+   std::set<cmStdString> 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);
+   for(std::vector<std::string>::const_iterator li = impl->Libraries.begin();
+       li != impl->Libraries.end(); ++li)
+     {
+     cll.Visit(this->Makefile->FindTargetToUse(li->c_str()));
+     }
+ 
+   // Store the transitive closure of languages.
+   for(std::set<cmStdString>::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.
+     cmGlobalGenerator* gg =
+       this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
      std::string linkerLangList;              // only used for the error message
      int maxLinkerPref = 0;
***************
*** 2345,2352 ****
        {
        int linkerPref = gg->GetLinkerPreference(sit->c_str());
!       if ((linkerPref > maxLinkerPref) || (linkerLang==0))
          {
          maxLinkerPref = linkerPref;
!         linkerLang = sit->c_str();
          linkerLangList = *sit;
          multiplePreferedLanguages = false;
--- 2432,2439 ----
        {
        int linkerPref = gg->GetLinkerPreference(sit->c_str());
!       if (lc.LinkerLanguage.empty() || (linkerPref > maxLinkerPref))
          {
          maxLinkerPref = linkerPref;
!         lc.LinkerLanguage = *sit;
          linkerLangList = *sit;
          multiplePreferedLanguages = false;
***************
*** 2360,2372 ****
        }
  
-     if (linkerLang!=0)
-       {
-       const_cast<cmTarget*>(this)->SetProperty("LINKER_LANGUAGE", linkerLang);
-       }
      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.";
--- 2447,2455 ----
        }
  
      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.";
***************
*** 2374,2378 ****
        }
      }
-   return this->GetProperty("LINKER_LANGUAGE");
  }
  
--- 2457,2460 ----
***************
*** 3830,3833 ****
--- 3912,3920 ----
      iface.Libraries = impl->Libraries;
      iface.WrongConfigLibraries = impl->WrongConfigLibraries;
+     if(this->GetType() == cmTarget::STATIC_LIBRARY)
+       {
+       // Targets using this archive need its language runtime libraries.
+       iface.Languages = impl->Languages;
+       }
      }
  
***************
*** 3870,3873 ****
--- 3957,3961 ----
    cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
  
+   // Collect libraries directly linked in this configuration.
    LinkLibraryVectorType const& llibs = this->GetOriginalLinkLibraries();
    for(cmTarget::LinkLibraryVectorType::const_iterator li = llibs.begin();
***************
*** 3892,3895 ****
--- 3980,3992 ----
        }
      }
+ 
+   // This target needs runtime libraries for its source languages.
+   std::set<cmStdString> languages;
+   this->GetLanguages(languages);
+   for(std::set<cmStdString>::iterator li = languages.begin();
+       li != languages.end(); ++li)
+     {
+     impl.Languages.push_back(*li);
+     }
  }
  



More information about the Cmake-commits mailing list