[cmake-commits] king committed cmComputeLinkDepends.cxx 1.5 1.6 cmComputeLinkDepends.h 1.2 1.3 cmComputeLinkInformation.cxx 1.14 1.15 cmComputeLinkInformation.h 1.9 1.10 cmDocumentVariables.cxx 1.13 1.14 cmExportFileGenerator.cxx 1.8 1.9 cmExportFileGenerator.h 1.6 1.7 cmTarget.cxx 1.187 1.188 cmTarget.h 1.102 1.103

cmake-commits at cmake.org cmake-commits at cmake.org
Thu Jan 31 15:45:33 EST 2008


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

Modified Files:
	cmComputeLinkDepends.cxx cmComputeLinkDepends.h 
	cmComputeLinkInformation.cxx cmComputeLinkInformation.h 
	cmDocumentVariables.cxx cmExportFileGenerator.cxx 
	cmExportFileGenerator.h cmTarget.cxx cmTarget.h 
Log Message:
ENH: Support linking to shared libs with dependent libs

  - Split IMPORTED_LINK_LIBRARIES into two parts:
      IMPORTED_LINK_INTERFACE_LIBRARIES
      IMPORTED_LINK_DEPENDENT_LIBRARIES
  - Add CMAKE_DEPENDENT_SHARED_LIBRARY_MODE to select behavior
  - Set mode to LINK for Darwin (fixes universal binary problem)
  - Update ExportImport test to account for changes


Index: cmComputeLinkDepends.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmComputeLinkDepends.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- cmComputeLinkDepends.h	28 Jan 2008 13:38:35 -0000	1.2
+++ cmComputeLinkDepends.h	31 Jan 2008 20:45:30 -0000	1.3
@@ -41,8 +41,10 @@
   {
     std::string Item;
     cmTarget* Target;
-    LinkEntry(): Item(), Target(0) {}
-    LinkEntry(LinkEntry const& r): Item(r.Item), Target(r.Target) {}
+    bool IsSharedDep;
+    LinkEntry(): Item(), Target(0), IsSharedDep(false) {}
+    LinkEntry(LinkEntry const& r):
+      Item(r.Item), Target(r.Target), IsSharedDep(r.IsSharedDep) {}
   };
 
   typedef std::vector<LinkEntry> EntryVector;
@@ -65,8 +67,9 @@
 
   typedef cmTarget::LinkLibraryVectorType LinkLibraryVectorType;
 
+  std::map<cmStdString, int>::iterator
+  AllocateLinkEntry(std::string const& item);
   int AddLinkEntry(std::string const& item);
-  void AddImportedLinkEntries(int depender_index, cmTarget* target);
   void AddVarLinkEntries(int depender_index, const char* value);
   void AddTargetLinkEntries(int depender_index,
                             LinkLibraryVectorType const& libs);
@@ -86,6 +89,19 @@
   std::queue<BFSEntry> BFSQueue;
   void FollowLinkEntry(BFSEntry const&);
 
+  // Shared libraries that are included only because they are
+  // dependencies of other shared libraries, not because they are part
+  // of the interface.
+  struct SharedDepEntry
+  {
+    std::string Item;
+    int DependerIndex;
+  };
+  std::queue<SharedDepEntry> SharedDepQueue;
+  void QueueSharedDependencies(int depender_index,
+                               std::vector<std::string> const& deps);
+  void HandleSharedDependency(SharedDepEntry const& dep);
+
   // Dependency inferral for each link item.
   struct DependSet: public std::set<int> {};
   struct DependSetList: public std::vector<DependSet> {};

Index: cmExportFileGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportFileGenerator.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- cmExportFileGenerator.h	31 Jan 2008 11:51:43 -0000	1.6
+++ cmExportFileGenerator.h	31 Jan 2008 20:45:31 -0000	1.7
@@ -70,10 +70,10 @@
   void SetImportLinkProperties(const char* config,
                                std::string const& suffix, cmTarget* target,
                                ImportPropertyMap& properties);
-  void SetImportLinkProperties(std::string const& suffix,
-                               cmTarget* target,
-                               std::vector<std::string> const& libs,
-                               ImportPropertyMap& properties);
+  void SetImportLinkProperty(std::string const& suffix,
+                             cmTarget* target, const char* propName,
+                             std::vector<std::string> const& libs,
+                             ImportPropertyMap& properties);
 
   /** Each subclass knows how to generate its kind of export file.  */
   virtual bool GenerateMainFile(std::ostream& os) = 0;

Index: cmComputeLinkInformation.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmComputeLinkInformation.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cmComputeLinkInformation.h	31 Jan 2008 12:50:40 -0000	1.9
+++ cmComputeLinkInformation.h	31 Jan 2008 20:45:30 -0000	1.10
@@ -58,7 +58,7 @@
   std::string GetChrpathTool();
   std::set<cmTarget*> const& GetSharedLibrariesLinked();
 private:
-  void AddItem(std::string const& item, cmTarget* tgt);
+  void AddItem(std::string const& item, cmTarget* tgt, bool isSharedDep);
 
   // Output information.
   ItemVector Items;
@@ -78,6 +78,14 @@
   const char* Config;
   const char* LinkLanguage;
 
+  // Modes for dealing with dependent shared libraries.
+  enum SharedDepMode
+  {
+    SharedDepModeNone, // Drop
+    SharedDepModeDir,  // Use in runtime information
+    SharedDepModeLink  // List file on link line
+  };
+
   // System info.
   bool UseImportLibrary;
   const char* LoaderFlag;
@@ -88,6 +96,7 @@
   std::string RuntimeSep;
   std::string RuntimeAlways;
   bool RuntimeUseChrpath;
+  SharedDepMode SharedDependencyMode;
 
   // Link type adjustment.
   void ComputeLinkTypeInfo();
@@ -134,6 +143,7 @@
   void AddLinkerSearchDirectories(std::vector<std::string> const& dirs);
   std::set<cmStdString> DirectoriesEmmitted;
   std::set<cmStdString> ImplicitLinkDirs;
+  std::vector<std::string> SharedDependencyDirectories;
 
   // Linker search path compatibility mode.
   std::vector<std::string> OldLinkDirs;

Index: cmComputeLinkInformation.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmComputeLinkInformation.cxx,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- cmComputeLinkInformation.cxx	31 Jan 2008 13:05:34 -0000	1.14
+++ cmComputeLinkInformation.cxx	31 Jan 2008 20:45:30 -0000	1.15
@@ -234,6 +234,21 @@
   // Setup framework support.
   this->ComputeFrameworkInfo();
 
+  // Choose a mode for dealing with shared library dependencies.
+  this->SharedDependencyMode = SharedDepModeNone;
+  if(const char* mode =
+     this->Makefile->GetDefinition("CMAKE_DEPENDENT_SHARED_LIBRARY_MODE"))
+    {
+    if(strcmp(mode, "LINK") == 0)
+      {
+      this->SharedDependencyMode = SharedDepModeLink;
+      }
+    else if(strcmp(mode, "DIR") == 0)
+      {
+      this->SharedDependencyMode = SharedDepModeDir;
+      }
+    }
+
   // Get the implicit link directories for this platform.
   if(const char* implicitLinks =
      (this->Makefile->GetDefinition
@@ -335,7 +350,7 @@
         lei = linkEntries.begin();
       lei != linkEntries.end(); ++lei)
     {
-    this->AddItem(lei->Item, lei->Target);
+    this->AddItem(lei->Item, lei->Target, lei->IsSharedDep);
     }
 
   // Restore the target link type so the correct system runtime
@@ -358,8 +373,14 @@
 
 //----------------------------------------------------------------------------
 void cmComputeLinkInformation::AddItem(std::string const& item,
-                                       cmTarget* tgt)
+                                       cmTarget* tgt, bool isSharedDep)
 {
+  // If dropping shared library dependencies, ignore them.
+  if(isSharedDep && this->SharedDependencyMode == SharedDepModeNone)
+    {
+    return;
+    }
+
   // Compute the proper name to use to link this library.
   const char* config = this->Config;
   bool impexe = (tgt && tgt->IsExecutableWithExports());
@@ -370,12 +391,6 @@
     return;
     }
 
-  // Keep track of shared libraries linked.
-  if(tgt && tgt->GetType() == cmTarget::SHARED_LIBRARY)
-    {
-    this->SharedLibrariesLinked.insert(tgt);
-    }
-
   if(tgt && (tgt->GetType() == cmTarget::STATIC_LIBRARY ||
              tgt->GetType() == cmTarget::SHARED_LIBRARY ||
              tgt->GetType() == cmTarget::MODULE_LIBRARY ||
@@ -401,6 +416,14 @@
         (this->UseImportLibrary &&
          (impexe || tgt->GetType() == cmTarget::SHARED_LIBRARY));
 
+      // Handle shared dependencies in directory mode.
+      if(isSharedDep && this->SharedDependencyMode == SharedDepModeDir)
+        {
+        std::string dir = tgt->GetDirectory(config, implib);
+        this->SharedDependencyDirectories.push_back(dir);
+        return;
+        }
+
       // Pass the full path to the target file.
       std::string lib = tgt->GetFullPath(config, implib);
       this->Depends.push_back(lib);
@@ -411,6 +434,7 @@
         // link.
         std::string fw = tgt->GetDirectory(config, implib);
         this->AddFrameworkItem(fw);
+        this->SharedLibrariesLinked.insert(tgt);
         }
       else
         {
@@ -705,6 +729,12 @@
     this->Items.push_back(Item(this->LibLinkFileFlag, false));
     }
 
+  // Keep track of shared library targets linked.
+  if(target->GetType() == cmTarget::SHARED_LIBRARY)
+    {
+    this->SharedLibrariesLinked.insert(target);
+    }
+
   // Now add the full path to the library.
   this->Items.push_back(Item(item, true));
 }
@@ -991,6 +1021,18 @@
     {
     this->AddLinkerSearchDirectories(this->OldLinkDirs);
     }
+
+  // Help the linker find dependent shared libraries.
+  if(this->SharedDependencyMode == SharedDepModeDir)
+    {
+    // TODO: These directories should probably be added to the runtime
+    // path ordering analysis.  However they are a bit different.
+    // They should be placed both on the -L path and in the rpath.
+    // The link-with-runtime-path feature above should be replaced by
+    // this.
+    this->AddLinkerSearchDirectories(this->SharedDependencyDirectories);
+    }
+
 }
 
 //----------------------------------------------------------------------------

Index: cmExportFileGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportFileGenerator.cxx,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- cmExportFileGenerator.cxx	31 Jan 2008 11:51:43 -0000	1.8
+++ cmExportFileGenerator.cxx	31 Jan 2008 20:45:31 -0000	1.9
@@ -139,7 +139,12 @@
      target->GetLinkInterface(config))
     {
     // This target provides a link interface, so use it.
-    this->SetImportLinkProperties(suffix, target, *interface, properties);
+    this->SetImportLinkProperty(suffix, target,
+                                "IMPORTED_LINK_INTERFACE_LIBRARIES",
+                                interface->Libraries, properties);
+    this->SetImportLinkProperty(suffix, target,
+                                "IMPORTED_LINK_DEPENDENT_LIBRARIES",
+                                interface->SharedDeps, properties);
     }
   else if(target->GetType() == cmTarget::STATIC_LIBRARY ||
           target->GetType() == cmTarget::SHARED_LIBRARY)
@@ -183,17 +188,26 @@
     }
 
   // Store the entries in the property.
-  this->SetImportLinkProperties(suffix, target, actual_libs, properties);
+  this->SetImportLinkProperty(suffix, target,
+                              "IMPORTED_LINK_INTERFACE_LIBRARIES",
+                              actual_libs, properties);
 }
 
 //----------------------------------------------------------------------------
 void
 cmExportFileGenerator
-::SetImportLinkProperties(std::string const& suffix,
-                          cmTarget* target,
-                          std::vector<std::string> const& libs,
-                          ImportPropertyMap& properties)
+::SetImportLinkProperty(std::string const& suffix,
+                        cmTarget* target,
+                        const char* propName,
+                        std::vector<std::string> const& libs,
+                        ImportPropertyMap& properties)
 {
+  // Skip the property if there are no libraries.
+  if(libs.empty())
+    {
+    return;
+    }
+
   // Get the makefile in which to lookup target information.
   cmMakefile* mf = target->GetMakefile();
 
@@ -233,6 +247,9 @@
           // known here.  This is probably user-error.
           this->ComplainAboutMissingTarget(target, li->c_str());
           }
+        // Assume the target will be exported by another command.
+        // Append it with the export namespace.
+        link_libs += this->Namespace;
         link_libs += *li;
         }
       }
@@ -244,7 +261,7 @@
     }
 
   // Store the property.
-  std::string prop = "IMPORTED_LINK_LIBRARIES";
+  std::string prop = propName;
   prop += suffix;
   properties[prop] = link_libs;
 }

Index: cmComputeLinkDepends.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmComputeLinkDepends.cxx,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cmComputeLinkDepends.cxx	30 Jan 2008 22:25:52 -0000	1.5
+++ cmComputeLinkDepends.cxx	31 Jan 2008 20:45:30 -0000	1.6
@@ -171,6 +171,14 @@
     this->FollowLinkEntry(qe);
     }
 
+  // Complete the search of shared library dependencies.
+  while(!this->SharedDepQueue.empty())
+    {
+    // Handle the next entry.
+    this->HandleSharedDependency(this->SharedDepQueue.front());
+    this->SharedDepQueue.pop();
+    }
+
   // Infer dependencies of targets for which they were not known.
   this->InferDependencies();
 
@@ -198,6 +206,20 @@
 }
 
 //----------------------------------------------------------------------------
+std::map<cmStdString, int>::iterator
+cmComputeLinkDepends::AllocateLinkEntry(std::string const& item)
+{
+  std::map<cmStdString, int>::value_type
+    index_entry(item, static_cast<int>(this->EntryList.size()));
+  std::map<cmStdString, int>::iterator
+    lei = this->LinkEntryIndex.insert(index_entry).first;
+  this->EntryList.push_back(LinkEntry());
+  this->InferredDependSets.push_back(0);
+  this->EntryConstraintGraph.push_back(EntryConstraintSet());
+  return lei;
+}
+
+//----------------------------------------------------------------------------
 int cmComputeLinkDepends::AddLinkEntry(std::string const& item)
 {
   // Check if the item entry has already been added.
@@ -209,14 +231,7 @@
     }
 
   // Allocate a spot for the item entry.
-  {
-  std::map<cmStdString, int>::value_type
-    index_entry(item, static_cast<int>(this->EntryList.size()));
-  lei = this->LinkEntryIndex.insert(index_entry).first;
-  this->EntryList.push_back(LinkEntry());
-  this->InferredDependSets.push_back(0);
-  this->EntryConstraintGraph.push_back(EntryConstraintSet());
-  }
+  lei = this->AllocateLinkEntry(item);
 
   // Initialize the item entry.
   int index = lei->second;
@@ -263,18 +278,17 @@
   if(entry.Target)
     {
     // Follow the target dependencies.
-    if(entry.Target->IsImported())
-      {
-      // Imported targets provide their own link information.
-      this->AddImportedLinkEntries(depender_index, entry.Target);
-      }
-    else if(cmTargetLinkInterface const* interface =
-            entry.Target->GetLinkInterface(this->Config))
+    if(cmTargetLinkInterface const* interface =
+       entry.Target->GetLinkInterface(this->Config))
       {
       // This target provides its own link interface information.
-      this->AddLinkEntries(depender_index, *interface);
+      this->AddLinkEntries(depender_index, interface->Libraries);
+
+      // Handle dependent shared libraries.
+      this->QueueSharedDependencies(depender_index, interface->SharedDeps);
       }
-    else if(entry.Target->GetType() != cmTarget::EXECUTABLE)
+    else if(!entry.Target->IsImported() &&
+            entry.Target->GetType() != cmTarget::EXECUTABLE)
       {
       // Use the target's link implementation as the interface.
       this->AddTargetLinkEntries(depender_index,
@@ -289,13 +303,60 @@
 }
 
 //----------------------------------------------------------------------------
-void cmComputeLinkDepends::AddImportedLinkEntries(int depender_index,
-                                                  cmTarget* target)
+void
+cmComputeLinkDepends
+::QueueSharedDependencies(int depender_index,
+                          std::vector<std::string> const& deps)
 {
-  if(std::vector<std::string> const* libs =
-     target->GetImportedLinkLibraries(this->Config))
+  for(std::vector<std::string>::const_iterator li = deps.begin();
+      li != deps.end(); ++li)
     {
-    this->AddLinkEntries(depender_index, *libs);
+    SharedDepEntry qe;
+    qe.Item = *li;
+    qe.DependerIndex = depender_index;
+    this->SharedDepQueue.push(qe);
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
+{
+  // Check if the target already has an entry.
+  std::map<cmStdString, int>::iterator lei =
+    this->LinkEntryIndex.find(dep.Item);
+  if(lei == this->LinkEntryIndex.end())
+    {
+    // Allocate a spot for the item entry.
+    lei = this->AllocateLinkEntry(dep.Item);
+
+    // Initialize the item entry.
+    LinkEntry& entry = this->EntryList[lei->second];
+    entry.Item = dep.Item;
+    entry.Target = this->Makefile->FindTargetToUse(dep.Item.c_str());
+
+    // This item was added specifically because it is a dependent
+    // shared library.  It may get special treatment
+    // in cmComputeLinkInformation.
+    entry.IsSharedDep = true;
+    }
+
+  // Get the link entry for this target.
+  int index = lei->second;
+  LinkEntry& entry = this->EntryList[index];
+
+  // This shared library dependency must be preceded by the item that
+  // listed it.
+  this->EntryConstraintGraph[index].insert(dep.DependerIndex);
+
+  // Target items may have their own dependencies.
+  if(entry.Target)
+    {
+    if(cmTargetLinkInterface const* interface =
+       entry.Target->GetLinkInterface(this->Config))
+      {
+      // We use just the shared dependencies, not the interface.
+      this->QueueSharedDependencies(index, interface->SharedDeps);
+      }
     }
 }
 

Index: cmDocumentVariables.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmDocumentVariables.cxx,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- cmDocumentVariables.cxx	30 Jan 2008 01:46:25 -0000	1.13
+++ cmDocumentVariables.cxx	31 Jan 2008 20:45:31 -0000	1.14
@@ -1104,5 +1104,7 @@
                      cmProperty::VARIABLE,0,0);
   cm->DefineProperty("CMAKE_SHARED_MODULE_RUNTIME_<LANG>_FLAG_SEP",
                      cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_DEPENDENT_SHARED_LIBRARY_MODE",
+                     cmProperty::VARIABLE,0,0);
 
 }

Index: cmTarget.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTarget.h,v
retrieving revision 1.102
retrieving revision 1.103
diff -u -d -r1.102 -r1.103
--- cmTarget.h	30 Jan 2008 22:25:52 -0000	1.102
+++ cmTarget.h	31 Jan 2008 20:45:31 -0000	1.103
@@ -35,9 +35,13 @@
   ~cmTargetLinkInformationMap();
 };
 
-struct cmTargetLinkInterface: public std::vector<std::string>
+struct cmTargetLinkInterface
 {
-  typedef std::vector<std::string> derived;
+  // Libraries listed in the interface.
+  std::vector<std::string> Libraries;
+
+  // Shared library dependencies needed for linking on some platforms.
+  std::vector<std::string> SharedDeps;
 };
 
 struct cmTargetLinkInterfaceMap:
@@ -218,11 +222,6 @@
 
   bool IsImported() const {return this->IsImportedTarget;}
 
-  /** Get link libraries for the given configuration of an imported
-      target.  */
-  std::vector<std::string> const*
-  GetImportedLinkLibraries(const char* config);
-
   /** Get the library interface dependencies.  This is the set of
       libraries from which something that links to this target may
       also receive symbols.  Returns 0 if the user has not specified
@@ -487,7 +486,7 @@
     std::string Location;
     std::string SOName;
     std::string ImportLibrary;
-    std::vector<std::string> LinkLibraries;
+    cmTargetLinkInterface LinkInterface;
   };
   typedef std::map<cmStdString, ImportInfo> ImportInfoMapType;
   ImportInfoMapType ImportInfoMap;

Index: cmTarget.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTarget.cxx,v
retrieving revision 1.187
retrieving revision 1.188
diff -u -d -r1.187 -r1.188
--- cmTarget.cxx	31 Jan 2008 13:05:34 -0000	1.187
+++ cmTarget.cxx	31 Jan 2008 20:45:31 -0000	1.188
@@ -188,15 +188,38 @@
      "from which the target is imported.");
 
   cm->DefineProperty
-    ("IMPORTED_LINK_LIBRARIES", cmProperty::TARGET,
-     "Transitive link dependencies of an IMPORTED target.",
-     "Lists dependencies that must be linked when an IMPORTED library "
+    ("IMPORTED_LINK_DEPENDENT_LIBRARIES", cmProperty::TARGET,
+     "Dependent shared libraries of an imported shared library.",
+     "Shared libraries may be linked to other shared libraries as part "
+     "of their implementation.  On some platforms the linker searches "
+     "for the dependent libraries of shared libraries they are including "
+     "in the link.  CMake gives the paths to these libraries to the linker "
+     "by listing them on the link line explicitly.  This property lists "
+     "the dependent shared libraries of an imported library.  The list "
+     "should be disjoint from the list of interface libraries in the "
+     "IMPORTED_LINK_INTERFACE_LIBRARIES property.  On platforms requiring "
+     "dependent shared libraries to be found at link time CMake uses this "
+     "list to add the dependent libraries to the link command line.");
+
+  cm->DefineProperty
+    ("IMPORTED_LINK_DEPENDENT_LIBRARIES_<CONFIG>", cmProperty::TARGET,
+     "Per-configuration version of IMPORTED_LINK_DEPENDENT_LIBRARIES.",
+     "This property is used when loading settings for the <CONFIG> "
+     "configuration of an imported target.  "
+     "Configuration names correspond to those provided by the project "
+     "from which the target is imported.");
+
+  cm->DefineProperty
+    ("IMPORTED_LINK_INTERFACE_LIBRARIES", cmProperty::TARGET,
+     "Transitive link interface of an IMPORTED target.",
+     "Lists libraries whose interface is included when an IMPORTED library "
      "target is linked to another target.  "
+     "The libraries will be included on the link line for the target.  "
      "Ignored for non-imported targets.");
 
   cm->DefineProperty
-    ("IMPORTED_LINK_LIBRARIES_<CONFIG>", cmProperty::TARGET,
-     "Per-configuration version of IMPORTED_LINK_LIBRARIES property.",
+    ("IMPORTED_LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET,
+     "Per-configuration version of IMPORTED_LINK_INTERFACE_LIBRARIES.",
      "This property is used when loading settings for the <CONFIG> "
      "configuration of an imported target.  "
      "Configuration names correspond to those provided by the project "
@@ -3045,43 +3068,56 @@
       }
     }
 
-  // Get the link dependencies.
+  // Get the link interface.
   {
-  std::string linkProp = "IMPORTED_LINK_LIBRARIES";
+  std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
   linkProp += suffix;
   if(const char* config_libs = this->GetProperty(linkProp.c_str()))
     {
-    cmSystemTools::ExpandListArgument(config_libs, info.LinkLibraries);
+    cmSystemTools::ExpandListArgument(config_libs,
+                                      info.LinkInterface.Libraries);
     }
-  else if(const char* libs = this->GetProperty("IMPORTED_LINK_LIBRARIES"))
+  else if(const char* libs =
+          this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES"))
     {
-    cmSystemTools::ExpandListArgument(libs, info.LinkLibraries);
+    cmSystemTools::ExpandListArgument(libs,
+                                      info.LinkInterface.Libraries);
     }
   }
-}
 
-//----------------------------------------------------------------------------
-std::vector<std::string> const*
-cmTarget::GetImportedLinkLibraries(const char* config)
-{
-  if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+  // Get the link dependencies.
+  {
+  std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES";
+  linkProp += suffix;
+  if(const char* config_libs = this->GetProperty(linkProp.c_str()))
     {
-    return &info->LinkLibraries;
+    cmSystemTools::ExpandListArgument(config_libs,
+                                      info.LinkInterface.SharedDeps);
     }
-  else
+  else if(const char* libs =
+          this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES"))
     {
-    return 0;
+    cmSystemTools::ExpandListArgument(libs, info.LinkInterface.SharedDeps);
     }
+  }
 }
 
 //----------------------------------------------------------------------------
 cmTargetLinkInterface const* cmTarget::GetLinkInterface(const char* config)
 {
-  // Link interfaces are supported only for non-imported shared
-  // libraries and executables that export symbols.  Imported targets
-  // provide their own link information.
-  if(this->IsImported() ||
-     (this->GetType() != cmTarget::SHARED_LIBRARY &&
+  // Imported targets have their own link interface.
+  if(this->IsImported())
+    {
+    if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+      {
+      return &info->LinkInterface;
+      }
+    return 0;
+    }
+
+  // Link interfaces are supported only for shared libraries and
+  // executables that export symbols.
+  if((this->GetType() != cmTarget::SHARED_LIBRARY &&
       !this->IsExecutableWithExports()))
     {
     return 0;
@@ -3139,13 +3175,77 @@
     return 0;
     }
 
-  // Return the interface libraries even if the list is empty.
-  if(cmTargetLinkInterface* interface = new cmTargetLinkInterface)
+  // Allocate the interface.
+  cmTargetLinkInterface* interface = new cmTargetLinkInterface;
+  if(!interface)
     {
-    cmSystemTools::ExpandListArgument(libs, *interface);
-    return interface;
+    return 0;
     }
-  return 0;
+
+  // Expand the list of libraries in the interface.
+  cmSystemTools::ExpandListArgument(libs, interface->Libraries);
+
+  // Now we need to construct a list of shared library dependencies
+  // not included in the interface.
+  if(this->GetType() == cmTarget::SHARED_LIBRARY)
+    {
+    // Use a set to keep track of what libraries have been emitted to
+    // either list.
+    std::set<cmStdString> emitted;
+    for(std::vector<std::string>::const_iterator
+          li = interface->Libraries.begin();
+        li != interface->Libraries.end(); ++li)
+      {
+      emitted.insert(*li);
+      }
+
+    // Compute which library configuration to link.
+    cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
+    if(config && cmSystemTools::UpperCase(config) == "DEBUG")
+      {
+      linkType = cmTarget::DEBUG;
+      }
+
+    // Construct the list of libs linked for this configuration.
+    cmTarget::LinkLibraryVectorType const& libs =
+      this->GetOriginalLinkLibraries();
+    for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
+        li != libs.end(); ++li)
+      {
+      // Skip entries that will resolve to the target itself, are empty,
+      // or are not meant for this configuration.
+      if(li->first == this->GetName() || li->first.empty() ||
+         !(li->second == cmTarget::GENERAL || li->second == linkType))
+        {
+        continue;
+        }
+
+      // Skip entries that have already been emitted into either list.
+      if(!emitted.insert(li->first).second)
+        {
+        continue;
+        }
+
+      // Add this entry if it is a shared library.
+      if(cmTarget* tgt = this->Makefile->FindTargetToUse(li->first.c_str()))
+        {
+        if(tgt->GetType() == cmTarget::SHARED_LIBRARY)
+          {
+          interface->SharedDeps.push_back(li->first);
+          }
+        }
+      else
+        {
+        // TODO: Recognize shared library file names.  Perhaps this
+        // should be moved to cmComputeLinkInformation, but that creates
+        // a chicken-and-egg problem since this list is needed for its
+        // construction.
+        }
+      }
+    }
+
+  // Return the completed interface.
+  return interface;
 }
 
 //----------------------------------------------------------------------------



More information about the Cmake-commits mailing list