[cmake-commits] king committed CMakeLists.txt 1.389 1.390 cmComputeLinkDepends.cxx 1.6 1.7 cmComputeLinkInformation.cxx 1.15 1.16 cmComputeLinkInformation.h 1.10 1.11 cmDocumentVariables.cxx 1.14 1.15 cmExportBuildFileGenerator.cxx 1.4 1.5 cmExportBuildFileGenerator.h 1.3 1.4 cmExportFileGenerator.cxx 1.9 1.10 cmExportFileGenerator.h 1.7 1.8 cmExportInstallFileGenerator.cxx 1.5 1.6 cmExportInstallFileGenerator.h 1.1 1.2 cmLocalGenerator.cxx 1.263 1.264 cmOrderRuntimeDirectories.cxx NONE 1.1 cmOrderRuntimeDirectories.h NONE 1.1 cmTarget.cxx 1.189 1.190

cmake-commits at cmake.org cmake-commits at cmake.org
Fri Feb 1 08:56:02 EST 2008


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

Modified Files:
	CMakeLists.txt cmComputeLinkDepends.cxx 
	cmComputeLinkInformation.cxx cmComputeLinkInformation.h 
	cmDocumentVariables.cxx cmExportBuildFileGenerator.cxx 
	cmExportBuildFileGenerator.h cmExportFileGenerator.cxx 
	cmExportFileGenerator.h cmExportInstallFileGenerator.cxx 
	cmExportInstallFileGenerator.h cmLocalGenerator.cxx 
	cmTarget.cxx 
Added Files:
	cmOrderRuntimeDirectories.cxx cmOrderRuntimeDirectories.h 
Log Message:
ENH: Pass dependent library search path to linker on some platforms.

  - Move runtime path ordering out of cmComputeLinkInformation
    into its own class cmOrderRuntimeDirectories.
  - Create an instance of cmOrderRuntimeDirectories for runtime
    path ordering and another instance for dependent library
    path ordering.
  - Replace CMAKE_DEPENDENT_SHARED_LIBRARY_MODE with explicit
    CMAKE_LINK_DEPENDENT_LIBRARY_FILES boolean.
  - Create CMAKE_LINK_DEPENDENT_LIBRARY_DIRS boolean.
  - Create variables to specify -rpath-link flags:
      CMAKE_SHARED_LIBRARY_RPATH_LINK_<LANG>_FLAG
      CMAKE_EXECUTABLE_RPATH_LINK_<LANG>_FLAG
  - Enable -rpath-link flag on Linux and QNX.
  - Documentation and error message updates


Index: cmLocalGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalGenerator.cxx,v
retrieving revision 1.263
retrieving revision 1.264
diff -u -d -r1.263 -r1.264
--- cmLocalGenerator.cxx	30 Jan 2008 02:16:49 -0000	1.263
+++ cmLocalGenerator.cxx	1 Feb 2008 13:56:00 -0000	1.264
@@ -1605,6 +1605,15 @@
       }
     }
 
+  // Add the linker runtime search path if any.
+  std::string rpath_link = cli.GetRPathLinkString();
+  if(!cli.GetRPathLinkFlag().empty() && !rpath_link.empty())
+    {
+    fout << cli.GetRPathLinkFlag();
+    fout << this->EscapeForShell(rpath_link.c_str(), true);
+    fout << " ";
+    }
+
   // Add standard libraries for this language.
   std::string standardLibsVar = "CMAKE_";
   standardLibsVar += cli.GetLinkLanguage();

Index: cmExportFileGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportFileGenerator.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cmExportFileGenerator.h	31 Jan 2008 20:45:31 -0000	1.7
+++ cmExportFileGenerator.h	1 Feb 2008 13:56:00 -0000	1.8
@@ -85,7 +85,8 @@
 
   /** Each subclass knows how to complain about a target that is
       missing from an export set.  */
-  virtual void ComplainAboutMissingTarget(cmTarget*, const char* dep) = 0;
+  virtual void ComplainAboutMissingTarget(cmTarget* depender,
+                                          cmTarget* dependee) = 0;
 
   // The namespace in which the exports are placed in the generated file.
   std::string Namespace;

Index: cmExportFileGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportFileGenerator.cxx,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cmExportFileGenerator.cxx	31 Jan 2008 20:45:31 -0000	1.9
+++ cmExportFileGenerator.cxx	1 Feb 2008 13:56:00 -0000	1.10
@@ -245,7 +245,7 @@
           {
           // We are not appending, so all exported targets should be
           // known here.  This is probably user-error.
-          this->ComplainAboutMissingTarget(target, li->c_str());
+          this->ComplainAboutMissingTarget(target, tgt);
           }
         // Assume the target will be exported by another command.
         // Append it with the export namespace.

Index: cmComputeLinkInformation.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmComputeLinkInformation.cxx,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- cmComputeLinkInformation.cxx	31 Jan 2008 20:45:30 -0000	1.15
+++ cmComputeLinkInformation.cxx	1 Feb 2008 13:56:00 -0000	1.16
@@ -17,14 +17,13 @@
 #include "cmComputeLinkInformation.h"
 
 #include "cmComputeLinkDepends.h"
+#include "cmOrderRuntimeDirectories.h"
 
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmTarget.h"
 
-#include <algorithm>
-
 #include <ctype.h>
 
 /*
@@ -150,6 +149,68 @@
       or SHLIB_PATH, in searching for shared libraries.  This changes
       the default search order of LD_LIBRARY_PATH, SHLIB_PATH, and
       RPATH (embedded path).
+
+------------------------------------------------------------------------------
+Notes about dependent (transitive) shared libraries:
+
+On non-Windows systems shared libraries may have transitive
+dependencies.  In order to support LINK_INTERFACE_LIBRARIES we must
+support linking to a shared library without listing all the libraries
+to which it links.  Some linkers want to be able to find the
+transitive dependencies (dependent libraries) of shared libraries
+listed on the command line.
+
+  - On Windows, DLLs are not directly linked, and the import libraries
+    have no transitive dependencies.
+
+  - On Mac, we need to actually list the transitive dependencies.
+    Otherwise when using -isysroot for universal binaries it cannot
+    find the dependent libraries.  Listing them on the command line
+    tells the linker where to find them, but unfortunately also links
+    the library.
+
+  - On HP-UX, the linker wants to find the transitive dependencies of
+    shared libraries in the -L paths even if the dependent libraries
+    are given on the link line.
+
+  - On AIX the transitive dependencies are not needed.
+
+  - On SGI, the linker wants to find the transitive dependencies of
+    shared libraries in the -L paths if they are not given on the link
+    line.  Transitive linking can be disabled using the options
+
+      -no_transitive_link -Wl,-no_transitive_link
+
+    which disable it.  Both options must be given when invoking the
+    linker through the compiler.
+
+  - On Sun, the linker wants to find the transitive dependencies of
+    shared libraries in the -L paths if they are not given on the link
+    line.
+
+  - On Linux, FreeBSD, and QNX:
+
+    The linker wants to find the transitive dependencies of shared
+    libraries in the "-rpath-link" paths option if they have not been
+    given on the link line.  The option is like rpath but just for
+    link time:
+
+      -Wl,-rpath-link,"/path1:/path2"
+
+For -rpath-link, we need a separate runtime path ordering pass
+including just the dependent libraries that are not linked.
+
+For -L paths on non-HP, we can do the same thing as with rpath-link
+but put the results in -L paths.  The paths should be listed at the
+end to avoid conflicting with user search paths (?).
+
+For -L paths on HP, we should do a runtime path ordering pass with
+all libraries, both linked and non-linked.  Even dependent
+libraries that are also linked need to be listed in -L paths.
+
+In our implementation we add all dependent libraries to the runtime
+path computation.  Then the auto-generated RPATH will find everything.
+
 */
 
 //----------------------------------------------------------------------------
@@ -165,6 +226,12 @@
   // The configuration being linked.
   this->Config = config;
 
+  // Allocate internals.
+  this->OrderRuntimeSearchPath =
+    new cmOrderRuntimeDirectories(this->GlobalGenerator, target->GetName(),
+                                  "runtime path");
+  this->OrderDependentRPath = 0;
+
   // Get the language used for linking this target.
   this->LinkLanguage =
     this->Target->GetLinkerLanguage(this->GlobalGenerator);
@@ -204,15 +271,11 @@
   this->RuntimeUseChrpath = false;
   if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
     {
+    const char* tType =
+      ((this->Target->GetType() == cmTarget::EXECUTABLE)?
+       "EXECUTABLE" : "SHARED_LIBRARY");
     std::string rtVar = "CMAKE_";
-    if(this->Target->GetType() == cmTarget::EXECUTABLE)
-      {
-      rtVar += "EXECUTABLE";
-      }
-    else
-      {
-      rtVar += "SHARED_LIBRARY";
-      }
+    rtVar += tType;
     rtVar += "_RUNTIME_";
     rtVar += this->LinkLanguage;
     rtVar += "_FLAG";
@@ -223,6 +286,14 @@
       (this->Makefile->
        GetSafeDefinition("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH"));
     this->RuntimeUseChrpath = this->Target->IsChrpathUsed();
+
+    // Get options needed to help find dependent libraries.
+    std::string rlVar = "CMAKE_";
+    rlVar += tType;
+    rlVar += "_RPATH_LINK_";
+    rlVar += this->LinkLanguage;
+    rlVar += "_FLAG";
+    this->RPathLinkFlag = this->Makefile->GetSafeDefinition(rlVar.c_str());
     }
 
   // Get link type information.
@@ -236,17 +307,23 @@
 
   // 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(this->Makefile->IsOn("CMAKE_LINK_DEPENDENT_LIBRARY_FILES"))
     {
-    if(strcmp(mode, "LINK") == 0)
-      {
-      this->SharedDependencyMode = SharedDepModeLink;
-      }
-    else if(strcmp(mode, "DIR") == 0)
-      {
-      this->SharedDependencyMode = SharedDepModeDir;
-      }
+    this->SharedDependencyMode = SharedDepModeLink;
+    }
+  else if(this->Makefile->IsOn("CMAKE_LINK_DEPENDENT_LIBRARY_DIRS"))
+    {
+    this->SharedDependencyMode = SharedDepModeDir;
+    }
+  else if(!this->RPathLinkFlag.empty())
+    {
+    this->SharedDependencyMode = SharedDepModeDir;
+    }
+  if(this->SharedDependencyMode == SharedDepModeDir)
+    {
+    this->OrderDependentRPath =
+      new cmOrderRuntimeDirectories(this->GlobalGenerator, target->GetName(),
+                                    "dependent library path");
     }
 
   // Get the implicit link directories for this platform.
@@ -265,7 +342,6 @@
     }
 
   // Initial state.
-  this->RuntimeSearchPathComputed = false;
   this->HaveUserFlagItem = false;
 
   // Decide whether to enable compatible library search path mode.
@@ -289,6 +365,13 @@
 }
 
 //----------------------------------------------------------------------------
+cmComputeLinkInformation::~cmComputeLinkInformation()
+{
+  delete this->OrderRuntimeSearchPath;
+  delete this->OrderDependentRPath;
+}
+
+//----------------------------------------------------------------------------
 cmComputeLinkInformation::ItemVector const&
 cmComputeLinkInformation::GetItems()
 {
@@ -302,6 +385,31 @@
 }
 
 //----------------------------------------------------------------------------
+std::string cmComputeLinkInformation::GetRPathLinkString()
+{
+  // If there is no separate linker runtime search flag (-rpath-link)
+  // there is no reason to compute a string.
+  if(!this->OrderDependentRPath || this->RPathLinkFlag.empty())
+    {
+    return "";
+    }
+
+  // Construct the linker runtime search path.
+  std::string rpath_link;
+  const char* sep = "";
+  std::vector<std::string> const& dirs =
+    this->OrderDependentRPath->GetRuntimePath();
+  for(std::vector<std::string>::const_iterator di = dirs.begin();
+      di != dirs.end(); ++di)
+    {
+    rpath_link += sep;
+    sep = ":";
+    rpath_link += *di;
+    }
+  return rpath_link;
+}
+
+//----------------------------------------------------------------------------
 std::vector<std::string> const& cmComputeLinkInformation::GetDepends()
 {
   return this->Depends;
@@ -350,7 +458,14 @@
         lei = linkEntries.begin();
       lei != linkEntries.end(); ++lei)
     {
-    this->AddItem(lei->Item, lei->Target, lei->IsSharedDep);
+    if(lei->IsSharedDep)
+      {
+      this->AddSharedDepItem(lei->Item, lei->Target);
+      }
+    else
+      {
+      this->AddItem(lei->Item, lei->Target);
+      }
     }
 
   // Restore the target link type so the correct system runtime
@@ -372,15 +487,8 @@
 }
 
 //----------------------------------------------------------------------------
-void cmComputeLinkInformation::AddItem(std::string const& item,
-                                       cmTarget* tgt, bool isSharedDep)
+void cmComputeLinkInformation::AddItem(std::string const& item, cmTarget* tgt)
 {
-  // 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());
@@ -416,14 +524,6 @@
         (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);
@@ -434,7 +534,6 @@
         // link.
         std::string fw = tgt->GetDirectory(config, implib);
         this->AddFrameworkItem(fw);
-        this->SharedLibrariesLinked.insert(tgt);
         }
       else
         {
@@ -470,6 +569,84 @@
 }
 
 //----------------------------------------------------------------------------
+void cmComputeLinkInformation::AddSharedDepItem(std::string const& item,
+                                                cmTarget* tgt)
+{
+  // If dropping shared library dependencies, ignore them.
+  if(this->SharedDependencyMode == SharedDepModeNone)
+    {
+    return;
+    }
+
+  // The user may have incorrectly named an item.  Skip items that are
+  // not full paths to shared libraries.
+  if(tgt)
+    {
+    // The target will provide a full path.  Make sure it is a shared
+    // library.
+    if(tgt->GetType() != cmTarget::SHARED_LIBRARY)
+      {
+      return;
+      }
+    }
+  else
+    {
+    // Skip items that are not full paths.  We will not be able to
+    // reliably specify them.
+    if(!cmSystemTools::FileIsFullPath(item.c_str()))
+      {
+      return;
+      }
+
+    // Get the name of the library from the file name.
+    std::string file = cmSystemTools::GetFilenameName(item);
+    if(!this->ExtractSharedLibraryName.find(file.c_str()))
+      {
+      // This is not the name of a shared library.
+      return;
+      }
+    }
+
+  // If in linking mode, just link to the shared library.
+  if(this->SharedDependencyMode == SharedDepModeLink)
+    {
+    this->AddItem(item, tgt);
+    return;
+    }
+
+  // Get a full path to the dependent shared library.
+  // Add it to the runtime path computation so that the target being
+  // linked will be able to find it.
+  std::string lib;
+  if(tgt)
+    {
+    lib = tgt->GetFullPath(this->Config, this->UseImportLibrary);
+    this->AddLibraryRuntimeInfo(lib, tgt);
+    }
+  else
+    {
+    lib = item;
+    this->AddLibraryRuntimeInfo(lib);
+    }
+
+  // Add the item to the separate dependent library search path if
+  // this platform wants one.
+  if(this->OrderDependentRPath)
+    {
+    if(tgt)
+      {
+      std::string soName = tgt->GetSOName(this->Config);
+      const char* soname = soName.empty()? 0 : soName.c_str();
+      this->OrderDependentRPath->AddLibrary(lib, soname);
+      }
+    else
+      {
+      this->OrderDependentRPath->AddLibrary(lib);
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
 void cmComputeLinkInformation::ComputeLinkTypeInfo()
 {
   // First assume we cannot do link type stuff.
@@ -1022,17 +1199,14 @@
     this->AddLinkerSearchDirectories(this->OldLinkDirs);
     }
 
-  // Help the linker find dependent shared libraries.
-  if(this->SharedDependencyMode == SharedDepModeDir)
+  // If there is no separate linker runtime search flag (-rpath-link)
+  // and we have a search path for dependent libraries add it to the
+  // link directories.
+  if(this->OrderDependentRPath && this->RPathLinkFlag.empty())
     {
-    // 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);
+    this->AddLinkerSearchDirectories
+      (this->OrderDependentRPath->GetRuntimePath());
     }
-
 }
 
 //----------------------------------------------------------------------------
@@ -1054,23 +1228,9 @@
 std::vector<std::string> const&
 cmComputeLinkInformation::GetRuntimeSearchPath()
 {
-  if(!this->RuntimeSearchPathComputed)
-    {
-    this->RuntimeSearchPathComputed = true;
-    this->CollectRuntimeDirectories();
-    this->FindConflictingLibraries();
-    this->OrderRuntimeSearchPath();
-    }
-  return this->RuntimeSearchPath;
+  return this->OrderRuntimeSearchPath->GetRuntimePath();
 }
 
-//============================================================================
-// Directory ordering computation.
-//   - Useful to compute a safe runtime library path order
-//   - Need runtime path for supporting INSTALL_RPATH_USE_LINK_PATH
-//   - Need runtime path at link time to pickup transitive link dependencies
-//     for shared libraries (in future when we do not always add them).
-
 //----------------------------------------------------------------------------
 void
 cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath,
@@ -1104,262 +1264,8 @@
     return;
     }
 
-  // Add the runtime information at most once.
-  if(this->LibraryRuntimeInfoEmmitted.insert(fullPath).second)
-    {
-    // Construct the runtime information entry for this library.
-    LibraryRuntimeEntry entry;
-    entry.FileName =  cmSystemTools::GetFilenameName(fullPath);
-    entry.SOName = soname? soname : "";
-    entry.Directory = cmSystemTools::GetFilenamePath(fullPath);
-    this->LibraryRuntimeInfo.push_back(entry);
-    }
-  else
-    {
-    // This can happen if the same library is linked multiple times.
-    // In that case the runtime information check need be done only
-    // once anyway.  For shared libs we could add a check in AddItem
-    // to not repeat them.
-    }
-}
-
-//----------------------------------------------------------------------------
-void cmComputeLinkInformation::CollectRuntimeDirectories()
-{
-  // Get all directories that should be in the runtime search path.
-
-  // Add directories containing libraries linked with full path.
-  for(std::vector<LibraryRuntimeEntry>::iterator
-        ei = this->LibraryRuntimeInfo.begin();
-      ei != this->LibraryRuntimeInfo.end(); ++ei)
-    {
-    ei->DirectoryIndex = this->AddRuntimeDirectory(ei->Directory);
-    }
-
-  // Add link directories specified for the target.
-  std::vector<std::string> const& dirs = this->Target->GetLinkDirectories();
-  for(std::vector<std::string>::const_iterator di = dirs.begin();
-      di != dirs.end(); ++di)
-    {
-    this->AddRuntimeDirectory(*di);
-    }
-}
-
-//----------------------------------------------------------------------------
-int cmComputeLinkInformation::AddRuntimeDirectory(std::string const& dir)
-{
-  // Add the runtime directory with a unique index.
-  std::map<cmStdString, int>::iterator i =
-    this->RuntimeDirectoryIndex.find(dir);
-  if(i == this->RuntimeDirectoryIndex.end())
-    {
-    std::map<cmStdString, int>::value_type
-      entry(dir, static_cast<int>(this->RuntimeDirectories.size()));
-    i = this->RuntimeDirectoryIndex.insert(entry).first;
-    this->RuntimeDirectories.push_back(dir);
-    }
-
-  return i->second;
-}
-
-//----------------------------------------------------------------------------
-struct cmCLIRuntimeConflictCompare
-{
-  typedef std::pair<int, int> RuntimeConflictPair;
-
-  // The conflict pair is unique based on just the directory
-  // (first).  The second element is only used for displaying
-  // information about why the entry is present.
-  bool operator()(RuntimeConflictPair const& l,
-                  RuntimeConflictPair const& r)
-    {
-    return l.first == r.first;
-    }
-};
-
-//----------------------------------------------------------------------------
-void cmComputeLinkInformation::FindConflictingLibraries()
-{
-  // Allocate the conflict graph.
-  this->RuntimeConflictGraph.resize(this->RuntimeDirectories.size());
-  this->RuntimeDirectoryVisited.resize(this->RuntimeDirectories.size(), 0);
-
-  // Find all runtime directories providing each library.
-  for(unsigned int lri = 0; lri < this->LibraryRuntimeInfo.size(); ++lri)
-    {
-    this->FindDirectoriesForLib(lri);
-    }
-
-  // Clean up the conflict graph representation.
-  for(std::vector<RuntimeConflictList>::iterator
-        i = this->RuntimeConflictGraph.begin();
-      i != this->RuntimeConflictGraph.end(); ++i)
-    {
-    // Sort the outgoing edges for each graph node so that the
-    // original order will be preserved as much as possible.
-    std::sort(i->begin(), i->end());
-
-    // Make the edge list unique so cycle detection will be reliable.
-    RuntimeConflictList::iterator last =
-      std::unique(i->begin(), i->end(), cmCLIRuntimeConflictCompare());
-    i->erase(last, i->end());
-    }
-}
-
-//----------------------------------------------------------------------------
-void cmComputeLinkInformation::FindDirectoriesForLib(unsigned int lri)
-{
-  // Search through the runtime directories to find those providing
-  // this library.
-  LibraryRuntimeEntry& re = this->LibraryRuntimeInfo[lri];
-  for(unsigned int i = 0; i < this->RuntimeDirectories.size(); ++i)
-    {
-    // Skip the directory that is supposed to provide the library.
-    if(this->RuntimeDirectories[i] == re.Directory)
-      {
-      continue;
-      }
-
-    // Determine which type of check to do.
-    if(!re.SOName.empty())
-      {
-      // We have the library soname.  Check if it will be found.
-      std::string file = this->RuntimeDirectories[i];
-      file += "/";
-      file += re.SOName;
-      std::set<cmStdString> const& files =
-        (this->GlobalGenerator
-         ->GetDirectoryContent(this->RuntimeDirectories[i], false));
-      if((std::set<cmStdString>::const_iterator(files.find(re.SOName)) !=
-          files.end()) ||
-         cmSystemTools::FileExists(file.c_str(), true))
-        {
-        // The library will be found in this directory but this is not
-        // the directory named for it.  Add an entry to make sure the
-        // desired directory comes before this one.
-        RuntimeConflictPair p(re.DirectoryIndex, lri);
-        this->RuntimeConflictGraph[i].push_back(p);
-        }
-      }
-    else
-      {
-      // We do not have the soname.  Look for files in the directory
-      // that may conflict.
-      std::set<cmStdString> const& files =
-        (this->GlobalGenerator
-         ->GetDirectoryContent(this->RuntimeDirectories[i], true));
-
-      // Get the set of files that might conflict.  Since we do not
-      // know the soname just look at all files that start with the
-      // file name.  Usually the soname starts with the library name.
-      std::string base = re.FileName;
-      std::set<cmStdString>::const_iterator first = files.lower_bound(base);
-      ++base[base.size()-1];
-      std::set<cmStdString>::const_iterator last = files.upper_bound(base);
-      bool found = false;
-      for(std::set<cmStdString>::const_iterator fi = first;
-          !found && fi != last; ++fi)
-        {
-        found = true;
-        }
-
-      if(found)
-        {
-        // The library may be found in this directory but this is not
-        // the directory named for it.  Add an entry to make sure the
-        // desired directory comes before this one.
-        RuntimeConflictPair p(re.DirectoryIndex, lri);
-        this->RuntimeConflictGraph[i].push_back(p);
-        }
-      }
-    }
-}
-
-//----------------------------------------------------------------------------
-void cmComputeLinkInformation::OrderRuntimeSearchPath()
-{
-  // Allow a cycle to be diagnosed once.
-  this->CycleDiagnosed = false;
-  this->WalkId = 0;
-
-  // Iterate through the directories in the original order.
-  for(unsigned int i=0; i < this->RuntimeDirectories.size(); ++i)
-    {
-    // Start a new DFS from this node.
-    ++this->WalkId;
-    this->VisitRuntimeDirectory(i);
-    }
-}
-
-//----------------------------------------------------------------------------
-void cmComputeLinkInformation::VisitRuntimeDirectory(unsigned int i)
-{
-  // Skip nodes already visited.
-  if(this->RuntimeDirectoryVisited[i])
-    {
-    if(this->RuntimeDirectoryVisited[i] == this->WalkId)
-      {
-      // We have reached a node previously visited on this DFS.
-      // There is a cycle.
-      this->DiagnoseCycle();
-      }
-    return;
-    }
-
-  // We are now visiting this node so mark it.
-  this->RuntimeDirectoryVisited[i] = this->WalkId;
-
-  // Visit the neighbors of the node first.
-  RuntimeConflictList const& clist = this->RuntimeConflictGraph[i];
-  for(RuntimeConflictList::const_iterator j = clist.begin();
-      j != clist.end(); ++j)
-    {
-    this->VisitRuntimeDirectory(j->first);
-    }
-
-  // Now that all directories required to come before this one have
-  // been emmitted, emit this directory.
-  this->RuntimeSearchPath.push_back(this->RuntimeDirectories[i]);
-}
-
-//----------------------------------------------------------------------------
-void cmComputeLinkInformation::DiagnoseCycle()
-{
-  // Report the cycle at most once.
-  if(this->CycleDiagnosed)
-    {
-    return;
-    }
-  this->CycleDiagnosed = true;
-
-  // Construct the message.
-  cmOStringStream e;
-  e << "WARNING: Cannot generate a safe runtime path for target "
-    << this->Target->GetName()
-    << " because there is a cycle in the constraint graph:\n";
-
-  // Display the conflict graph.
-  for(unsigned int i=0; i < this->RuntimeConflictGraph.size(); ++i)
-    {
-    RuntimeConflictList const& clist = this->RuntimeConflictGraph[i];
-    e << "dir " << i << " is [" << this->RuntimeDirectories[i] << "]\n";
-    for(RuntimeConflictList::const_iterator j = clist.begin();
-        j != clist.end(); ++j)
-      {
-      e << "  dir " << j->first << " must precede it due to [";
-      LibraryRuntimeEntry const& re = this->LibraryRuntimeInfo[j->second];
-      if(re.SOName.empty())
-        {
-        e << re.FileName;
-        }
-      else
-        {
-        e << re.SOName;
-        }
-      e << "]\n";
-      }
-    }
-  cmSystemTools::Message(e.str().c_str());
+  // Include this library in the runtime path ordering.
+  this->OrderRuntimeSearchPath->AddLibrary(fullPath, soname);
 }
 
 //----------------------------------------------------------------------------

Index: cmExportBuildFileGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportBuildFileGenerator.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cmExportBuildFileGenerator.h	30 Jan 2008 22:25:52 -0000	1.3
+++ cmExportBuildFileGenerator.h	1 Feb 2008 13:56:00 -0000	1.4
@@ -50,7 +50,8 @@
   virtual void GenerateImportTargetsConfig(std::ostream& os,
                                            const char* config,
                                            std::string const& suffix);
-  virtual void ComplainAboutMissingTarget(cmTarget* target, const char* dep);
+  virtual void ComplainAboutMissingTarget(cmTarget* depender,
+                                          cmTarget* dependee);
 
   /** Fill in properties indicating built file locations.  */
   void SetImportLocationProperty(const char* config,

Index: cmComputeLinkInformation.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmComputeLinkInformation.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- cmComputeLinkInformation.h	31 Jan 2008 20:45:30 -0000	1.10
+++ cmComputeLinkInformation.h	1 Feb 2008 13:56:00 -0000	1.11
@@ -25,6 +25,7 @@
 class cmLocalGenerator;
 class cmMakefile;
 class cmTarget;
+class cmOrderRuntimeDirectories;
 
 /** \class cmComputeLinkInformation
  * \brief Compute link information for a target in one configuration.
@@ -33,6 +34,7 @@
 {
 public:
   cmComputeLinkInformation(cmTarget* target, const char* config);
+  ~cmComputeLinkInformation();
   bool Compute();
 
   struct Item
@@ -57,8 +59,12 @@
   std::string GetChrpathString();
   std::string GetChrpathTool();
   std::set<cmTarget*> const& GetSharedLibrariesLinked();
+
+  std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; }
+  std::string GetRPathLinkString();
 private:
-  void AddItem(std::string const& item, cmTarget* tgt, bool isSharedDep);
+  void AddItem(std::string const& item, cmTarget* tgt);
+  void AddSharedDepItem(std::string const& item, cmTarget* tgt);
 
   // Output information.
   ItemVector Items;
@@ -96,6 +102,7 @@
   std::string RuntimeSep;
   std::string RuntimeAlways;
   bool RuntimeUseChrpath;
+  std::string RPathLinkFlag;
   SharedDepMode SharedDependencyMode;
 
   // Link type adjustment.
@@ -143,7 +150,6 @@
   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;
@@ -151,48 +157,13 @@
   bool HaveUserFlagItem;
 
   // Runtime path computation.
-  struct LibraryRuntimeEntry
-  {
-    // The file name of the library.
-    std::string FileName;
-
-    // The soname of the shared library if it is known.
-    std::string SOName;
-
-    // The directory in which the library is supposed to be found.
-    std::string Directory;
-
-    // The index assigned to the directory.
-    int DirectoryIndex;
-  };
-  bool RuntimeSearchPathComputed;
-  std::vector<LibraryRuntimeEntry> LibraryRuntimeInfo;
-  std::set<cmStdString> LibraryRuntimeInfoEmmitted;
-  std::vector<std::string> RuntimeDirectories;
-  std::map<cmStdString, int> RuntimeDirectoryIndex;
-  std::vector<int> RuntimeDirectoryVisited;
+  cmOrderRuntimeDirectories* OrderRuntimeSearchPath;
   void AddLibraryRuntimeInfo(std::string const& fullPath, cmTarget* target);
   void AddLibraryRuntimeInfo(std::string const& fullPath,
                              const char* soname = 0);
-  void CollectRuntimeDirectories();
-  int AddRuntimeDirectory(std::string const& dir);
-  void FindConflictingLibraries();
-  void FindDirectoriesForLib(unsigned int lri);
-  void OrderRuntimeSearchPath();
-  void VisitRuntimeDirectory(unsigned int i);
-  void DiagnoseCycle();
-  bool CycleDiagnosed;
-  int WalkId;
 
-  // Adjacency-list representation of runtime path ordering graph.
-  // This maps from directory to those that must come *before* it.
-  // Each entry that must come before is a pair.  The first element is
-  // the index of the directory that must come first.  The second
-  // element is the index of the runtime library that added the
-  // constraint.
-  typedef std::pair<int, int> RuntimeConflictPair;
-  struct RuntimeConflictList: public std::vector<RuntimeConflictPair> {};
-  std::vector<RuntimeConflictList> RuntimeConflictGraph;
+  // Dependent library path computation.
+  cmOrderRuntimeDirectories* OrderDependentRPath;
 };
 
 #endif

Index: cmComputeLinkDepends.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmComputeLinkDepends.cxx,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- cmComputeLinkDepends.cxx	31 Jan 2008 20:45:30 -0000	1.6
+++ cmComputeLinkDepends.cxx	1 Feb 2008 13:56:00 -0000	1.7
@@ -123,6 +123,14 @@
 edges are sorted by this index.  This preserves the original link
 order as much as possible subject to the dependencies.
 
+After the initial exploration of the link interface tree, any
+transitive (dependent) shared libraries that were encountered and not
+included in the interface are processed in their own BFS.  This BFS
+follows only the dependent library lists and not the link interfaces.
+They are added to the link items with a mark indicating that the are
+transitive dependencies.  Then cmComputeLinkInformation deals with
+them on a per-platform basis.
+
 */
 
 //----------------------------------------------------------------------------

Index: cmExportInstallFileGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportInstallFileGenerator.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- cmExportInstallFileGenerator.h	28 Jan 2008 13:38:35 -0000	1.1
+++ cmExportInstallFileGenerator.h	1 Feb 2008 13:56:00 -0000	1.2
@@ -66,7 +66,8 @@
   virtual void GenerateImportTargetsConfig(std::ostream& os,
                                            const char* config,
                                            std::string const& suffix);
-  virtual void ComplainAboutMissingTarget(cmTarget* target, const char* dep);
+  virtual void ComplainAboutMissingTarget(cmTarget* depender,
+                                          cmTarget* dependee);
 
   /** Generate a per-configuration file for the targets.  */
   bool GenerateImportFileConfig(const char* config);

--- NEW FILE: cmOrderRuntimeDirectories.cxx ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmOrderRuntimeDirectories.cxx,v $
  Language:  C++
  Date:      $Date: 2008/02/01 13:56:00 $
  Version:   $Revision: 1.1 $

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "cmOrderRuntimeDirectories.h"

#include "cmGlobalGenerator.h"
#include "cmSystemTools.h"

#include <algorithm>

/*
Directory ordering computation.
  - Useful to compute a safe runtime library path order
  - Need runtime path for supporting INSTALL_RPATH_USE_LINK_PATH
  - Need runtime path at link time to pickup transitive link dependencies
    for shared libraries.
*/

//----------------------------------------------------------------------------
cmOrderRuntimeDirectories::cmOrderRuntimeDirectories(cmGlobalGenerator* gg,
                                                     const char* name,
                                                     const char* purpose)
{
  this->GlobalGenerator = gg;
  this->Name = name;
  this->Purpose = purpose;
  this->Computed = false;
}

//----------------------------------------------------------------------------
std::vector<std::string> const& cmOrderRuntimeDirectories::GetRuntimePath()
{
  if(!this->Computed)
    {
    this->Computed = true;
    this->CollectRuntimeDirectories();
    this->FindConflictingLibraries();
    this->OrderRuntimeSearchPath();
    }
  return this->RuntimeSearchPath;
}

//----------------------------------------------------------------------------
void cmOrderRuntimeDirectories::AddLibrary(std::string const& fullPath,
                                           const char* soname)
{
  // Add the runtime information at most once.
  if(this->LibraryRuntimeInfoEmmitted.insert(fullPath).second)
    {
    // Construct the runtime information entry for this library.
    LibraryRuntimeEntry entry;
    entry.FileName =  cmSystemTools::GetFilenameName(fullPath);
    entry.SOName = soname? soname : "";
    entry.Directory = cmSystemTools::GetFilenamePath(fullPath);
    this->LibraryRuntimeInfo.push_back(entry);
    }
  else
    {
    // This can happen if the same library is linked multiple times.
    // In that case the runtime information check need be done only
    // once anyway.  For shared libs we could add a check in AddItem
    // to not repeat them.
    }
}

//----------------------------------------------------------------------------
void
cmOrderRuntimeDirectories
::AddDirectories(std::vector<std::string> const& extra)
{
  this->UserDirectories.insert(this->UserDirectories.end(),
                               extra.begin(), extra.end());
}

//----------------------------------------------------------------------------
void cmOrderRuntimeDirectories::CollectRuntimeDirectories()
{
  // Get all directories that should be in the runtime search path.

  // Add directories containing libraries.
  for(std::vector<LibraryRuntimeEntry>::iterator
        ei = this->LibraryRuntimeInfo.begin();
      ei != this->LibraryRuntimeInfo.end(); ++ei)
    {
    ei->DirectoryIndex = this->AddRuntimeDirectory(ei->Directory);
    }

  // Add link directories specified for inclusion.
  for(std::vector<std::string>::const_iterator
        di = this->UserDirectories.begin();
      di != this->UserDirectories.end(); ++di)
    {
    this->AddRuntimeDirectory(*di);
    }
}

//----------------------------------------------------------------------------
int cmOrderRuntimeDirectories::AddRuntimeDirectory(std::string const& dir)
{
  // Add the runtime directory with a unique index.
  std::map<cmStdString, int>::iterator i =
    this->RuntimeDirectoryIndex.find(dir);
  if(i == this->RuntimeDirectoryIndex.end())
    {
    std::map<cmStdString, int>::value_type
      entry(dir, static_cast<int>(this->RuntimeDirectories.size()));
    i = this->RuntimeDirectoryIndex.insert(entry).first;
    this->RuntimeDirectories.push_back(dir);
    }

  return i->second;
}

//----------------------------------------------------------------------------
struct cmOrderRuntimeDirectoriesCompare
{
  typedef std::pair<int, int> RuntimeConflictPair;

  // The conflict pair is unique based on just the directory
  // (first).  The second element is only used for displaying
  // information about why the entry is present.
  bool operator()(RuntimeConflictPair const& l,
                  RuntimeConflictPair const& r)
    {
    return l.first == r.first;
    }
};

//----------------------------------------------------------------------------
void cmOrderRuntimeDirectories::FindConflictingLibraries()
{
  // Allocate the conflict graph.
  this->RuntimeConflictGraph.resize(this->RuntimeDirectories.size());
  this->RuntimeDirectoryVisited.resize(this->RuntimeDirectories.size(), 0);

  // Find all runtime directories providing each library.
  for(unsigned int lri = 0; lri < this->LibraryRuntimeInfo.size(); ++lri)
    {
    this->FindDirectoriesForLib(lri);
    }

  // Clean up the conflict graph representation.
  for(std::vector<RuntimeConflictList>::iterator
        i = this->RuntimeConflictGraph.begin();
      i != this->RuntimeConflictGraph.end(); ++i)
    {
    // Sort the outgoing edges for each graph node so that the
    // original order will be preserved as much as possible.
    std::sort(i->begin(), i->end());

    // Make the edge list unique so cycle detection will be reliable.
    RuntimeConflictList::iterator last =
      std::unique(i->begin(), i->end(), cmOrderRuntimeDirectoriesCompare());
    i->erase(last, i->end());
    }
}

//----------------------------------------------------------------------------
void cmOrderRuntimeDirectories::FindDirectoriesForLib(unsigned int lri)
{
  // Search through the runtime directories to find those providing
  // this library.
  LibraryRuntimeEntry& re = this->LibraryRuntimeInfo[lri];
  for(unsigned int i = 0; i < this->RuntimeDirectories.size(); ++i)
    {
    // Skip the directory that is supposed to provide the library.
    if(this->RuntimeDirectories[i] == re.Directory)
      {
      continue;
      }

    // Determine which type of check to do.
    if(!re.SOName.empty())
      {
      // We have the library soname.  Check if it will be found.
      std::string file = this->RuntimeDirectories[i];
      file += "/";
      file += re.SOName;
      std::set<cmStdString> const& files =
        (this->GlobalGenerator
         ->GetDirectoryContent(this->RuntimeDirectories[i], false));
      if((std::set<cmStdString>::const_iterator(files.find(re.SOName)) !=
          files.end()) ||
         cmSystemTools::FileExists(file.c_str(), true))
        {
        // The library will be found in this directory but this is not
        // the directory named for it.  Add an entry to make sure the
        // desired directory comes before this one.
        RuntimeConflictPair p(re.DirectoryIndex, lri);
        this->RuntimeConflictGraph[i].push_back(p);
        }
      }
    else
      {
      // We do not have the soname.  Look for files in the directory
      // that may conflict.
      std::set<cmStdString> const& files =
        (this->GlobalGenerator
         ->GetDirectoryContent(this->RuntimeDirectories[i], true));

      // Get the set of files that might conflict.  Since we do not
      // know the soname just look at all files that start with the
      // file name.  Usually the soname starts with the library name.
      std::string base = re.FileName;
      std::set<cmStdString>::const_iterator first = files.lower_bound(base);
      ++base[base.size()-1];
      std::set<cmStdString>::const_iterator last = files.upper_bound(base);
      bool found = false;
      for(std::set<cmStdString>::const_iterator fi = first;
          !found && fi != last; ++fi)
        {
        found = true;
        }

      if(found)
        {
        // The library may be found in this directory but this is not
        // the directory named for it.  Add an entry to make sure the
        // desired directory comes before this one.
        RuntimeConflictPair p(re.DirectoryIndex, lri);
        this->RuntimeConflictGraph[i].push_back(p);
        }
      }
    }
}

//----------------------------------------------------------------------------
void cmOrderRuntimeDirectories::OrderRuntimeSearchPath()
{
  // Allow a cycle to be diagnosed once.
  this->CycleDiagnosed = false;
  this->WalkId = 0;

  // Iterate through the directories in the original order.
  for(unsigned int i=0; i < this->RuntimeDirectories.size(); ++i)
    {
    // Start a new DFS from this node.
    ++this->WalkId;
    this->VisitRuntimeDirectory(i);
    }
}

//----------------------------------------------------------------------------
void cmOrderRuntimeDirectories::VisitRuntimeDirectory(unsigned int i)
{
  // Skip nodes already visited.
  if(this->RuntimeDirectoryVisited[i])
    {
    if(this->RuntimeDirectoryVisited[i] == this->WalkId)
      {
      // We have reached a node previously visited on this DFS.
      // There is a cycle.
      this->DiagnoseCycle();
      }
    return;
    }

  // We are now visiting this node so mark it.
  this->RuntimeDirectoryVisited[i] = this->WalkId;

  // Visit the neighbors of the node first.
  RuntimeConflictList const& clist = this->RuntimeConflictGraph[i];
  for(RuntimeConflictList::const_iterator j = clist.begin();
      j != clist.end(); ++j)
    {
    this->VisitRuntimeDirectory(j->first);
    }

  // Now that all directories required to come before this one have
  // been emmitted, emit this directory.
  this->RuntimeSearchPath.push_back(this->RuntimeDirectories[i]);
}

//----------------------------------------------------------------------------
void cmOrderRuntimeDirectories::DiagnoseCycle()
{
  // Report the cycle at most once.
  if(this->CycleDiagnosed)
    {
    return;
    }
  this->CycleDiagnosed = true;

  // Construct the message.
  cmOStringStream e;
  e << "WARNING: Cannot generate a safe " << this->Purpose
    << " for target " << this->Name
    << " because there is a cycle in the constraint graph:\n";

  // Display the conflict graph.
  for(unsigned int i=0; i < this->RuntimeConflictGraph.size(); ++i)
    {
    RuntimeConflictList const& clist = this->RuntimeConflictGraph[i];
    e << "dir " << i << " is [" << this->RuntimeDirectories[i] << "]\n";
    for(RuntimeConflictList::const_iterator j = clist.begin();
        j != clist.end(); ++j)
      {
      e << "  dir " << j->first << " must precede it due to [";
      LibraryRuntimeEntry const& re = this->LibraryRuntimeInfo[j->second];
      if(re.SOName.empty())
        {
        e << re.FileName;
        }
      else
        {
        e << re.SOName;
        }
      e << "]\n";
      }
    }
  cmSystemTools::Message(e.str().c_str());
}

Index: CMakeLists.txt
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CMakeLists.txt,v
retrieving revision 1.389
retrieving revision 1.390
diff -u -d -r1.389 -r1.390
--- CMakeLists.txt	28 Jan 2008 13:38:35 -0000	1.389
+++ CMakeLists.txt	1 Feb 2008 13:56:00 -0000	1.390
@@ -161,6 +161,8 @@
   cmMakefileExecutableTargetGenerator.cxx
   cmMakefileLibraryTargetGenerator.cxx
   cmMakefileUtilityTargetGenerator.cxx
+  cmOrderRuntimeDirectories.cxx
+  cmOrderRuntimeDirectories.h
   cmProperty.cxx
   cmProperty.h
   cmPropertyDefinition.cxx

Index: cmExportBuildFileGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportBuildFileGenerator.cxx,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- cmExportBuildFileGenerator.cxx	30 Jan 2008 22:25:52 -0000	1.4
+++ cmExportBuildFileGenerator.cxx	1 Feb 2008 13:56:00 -0000	1.5
@@ -122,7 +122,8 @@
 //----------------------------------------------------------------------------
 void
 cmExportBuildFileGenerator
-::ComplainAboutMissingTarget(cmTarget* target, const char* dep)
+::ComplainAboutMissingTarget(cmTarget* depender,
+                             cmTarget* dependee)
 {
   if(!this->ExportCommand || !this->ExportCommand->ErrorMessage.empty())
     {
@@ -130,13 +131,10 @@
     }
 
   cmOStringStream e;
-  e << "called with target \"" << target->GetName()
-    << "\" which links to target \"" << dep
+  e << "called with target \"" << depender->GetName()
+    << "\" which requires target \"" << dependee->GetName()
     << "\" that is not in the export list.\n"
-    << "If the link dependency is not part of the public interface "
-    << "consider setting the LINK_INTERFACE_LIBRARIES property on \""
-    << target->GetName() << "\".  Otherwise add it to the export list.  "
-    << "If the link dependency is not easy to reference in this call, "
+    << "If the required target is not easy to reference in this call, "
     << "consider using the APPEND option with multiple separate calls.";
   this->ExportCommand->ErrorMessage = e.str();
 }

Index: cmDocumentVariables.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmDocumentVariables.cxx,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- cmDocumentVariables.cxx	31 Jan 2008 20:45:31 -0000	1.14
+++ cmDocumentVariables.cxx	1 Feb 2008 13:56:00 -0000	1.15
@@ -1086,10 +1086,14 @@
                      cmProperty::VARIABLE,0,0);
   cm->DefineProperty("CMAKE_SHARED_LIBRARY_RUNTIME_<LANG>_FLAG_SEP",
                      cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_SHARED_LIBRARY_RPATH_LINK_<LANG>_FLAG",
+                     cmProperty::VARIABLE,0,0);
   cm->DefineProperty("CMAKE_EXECUTABLE_RUNTIME_<LANG>_FLAG",
                      cmProperty::VARIABLE,0,0);
   cm->DefineProperty("CMAKE_EXECUTABLE_RUNTIME_<LANG>_FLAG_SEP",
                      cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_EXECUTABLE_RPATH_LINK_<LANG>_FLAG",
+                     cmProperty::VARIABLE,0,0);
   cm->DefineProperty("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH",
                      cmProperty::VARIABLE,0,0);
   cm->DefineProperty("CMAKE_SHARED_MODULE_CREATE_<LANG>_FLAGS",
@@ -1104,7 +1108,8 @@
                      cmProperty::VARIABLE,0,0);
   cm->DefineProperty("CMAKE_SHARED_MODULE_RUNTIME_<LANG>_FLAG_SEP",
                      cmProperty::VARIABLE,0,0);
-  cm->DefineProperty("CMAKE_DEPENDENT_SHARED_LIBRARY_MODE",
+  cm->DefineProperty("CMAKE_LINK_DEPENDENT_LIBRARY_FILES",
+                     cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_LINK_DEPENDENT_LIBRARY_DIRS",
                      cmProperty::VARIABLE,0,0);
-
 }

--- NEW FILE: cmOrderRuntimeDirectories.h ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmOrderRuntimeDirectories.h,v $
  Language:  C++
  Date:      $Date: 2008/02/01 13:56:00 $
  Version:   $Revision: 1.1 $

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef cmOrderRuntimeDirectories_h
#define cmOrderRuntimeDirectories_h

#include "cmStandardIncludes.h"

class cmGlobalGenerator;

/** \class cmOrderRuntimeDirectories
 * \brief Compute a safe runtime path order for a set of shared libraries.
 */
class cmOrderRuntimeDirectories
{
public:
  cmOrderRuntimeDirectories(cmGlobalGenerator* gg, const char* name,
                            const char* purpose);
  void AddLibrary(std::string const& fullPath, const char* soname = 0);
  void AddDirectories(std::vector<std::string> const& extra);

  std::vector<std::string> const& GetRuntimePath();
private:
  cmGlobalGenerator* GlobalGenerator;
  std::string Name;
  std::string Purpose;

  bool Computed;

  std::vector<std::string> RuntimeSearchPath;

  // Runtime path computation.
  struct LibraryRuntimeEntry
  {
    // The file name of the library.
    std::string FileName;

    // The soname of the shared library if it is known.
    std::string SOName;

    // The directory in which the library is supposed to be found.
    std::string Directory;

    // The index assigned to the directory.
    int DirectoryIndex;
  };
  bool RuntimeSearchPathComputed;
  std::vector<LibraryRuntimeEntry> LibraryRuntimeInfo;
  std::vector<std::string> UserDirectories;
  std::set<cmStdString> LibraryRuntimeInfoEmmitted;
  std::vector<std::string> RuntimeDirectories;
  std::map<cmStdString, int> RuntimeDirectoryIndex;
  std::vector<int> RuntimeDirectoryVisited;
  void CollectRuntimeDirectories();
  int AddRuntimeDirectory(std::string const& dir);
  void FindConflictingLibraries();
  void FindDirectoriesForLib(unsigned int lri);
  void OrderRuntimeSearchPath();
  void VisitRuntimeDirectory(unsigned int i);
  void DiagnoseCycle();
  bool CycleDiagnosed;
  int WalkId;

  // Adjacency-list representation of runtime path ordering graph.
  // This maps from directory to those that must come *before* it.
  // Each entry that must come before is a pair.  The first element is
  // the index of the directory that must come first.  The second
  // element is the index of the runtime library that added the
  // constraint.
  typedef std::pair<int, int> RuntimeConflictPair;
  struct RuntimeConflictList: public std::vector<RuntimeConflictPair> {};
  std::vector<RuntimeConflictList> RuntimeConflictGraph;
};

#endif

Index: cmExportInstallFileGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportInstallFileGenerator.cxx,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cmExportInstallFileGenerator.cxx	30 Jan 2008 22:25:52 -0000	1.5
+++ cmExportInstallFileGenerator.cxx	1 Feb 2008 13:56:00 -0000	1.6
@@ -264,16 +264,12 @@
 //----------------------------------------------------------------------------
 void
 cmExportInstallFileGenerator
-::ComplainAboutMissingTarget(cmTarget* target, const char* dep)
+::ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee)
 {
   cmOStringStream e;
   e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
-    << "includes target \"" << target->GetName()
-    << "\" which links to target \"" << dep
-    << "\" that is not in the export set.  "
-    << "If the link dependency is not part of the public interface "
-    << "consider setting the LINK_INTERFACE_LIBRARIES property on "
-    << "target \"" << target->GetName() << "\".  "
-    << "Otherwise add it to the export set.";
+    << "includes target \"" << depender->GetName()
+    << "\" which requires target \"" << depender->GetName()
+    << "\" that is not in the export set.";
   cmSystemTools::Error(e.str().c_str());
 }

Index: cmTarget.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTarget.cxx,v
retrieving revision 1.189
retrieving revision 1.190
diff -u -d -r1.189 -r1.190
--- cmTarget.cxx	1 Feb 2008 13:55:41 -0000	1.189
+++ cmTarget.cxx	1 Feb 2008 13:56:00 -0000	1.190
@@ -193,13 +193,13 @@
      "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 "
+     "in the link.  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.");
+     "list to add appropriate files or paths to the link command line.  "
+     "Ignored for non-imported targets.");
 
   cm->DefineProperty
     ("IMPORTED_LINK_DEPENDENT_LIBRARIES_<CONFIG>", cmProperty::TARGET,



More information about the Cmake-commits mailing list