Pārlūkot izejas kodu

ENH: add a new library path ordering algorithm to make sure -L paths will pick the correct libraries if possible

Bill Hoffman 20 gadi atpakaļ
vecāks
revīzija
ff812580eb

+ 1 - 0
Source/CMakeLists.txt

@@ -44,6 +44,7 @@ SET(SRCS
   cmMakeDepend.h
   cmMakefile.cxx
   cmMakefile.h
+  cmOrderLinkDirectories.cxx
   cmSourceFile.cxx
   cmSourceFile.h
   cmSourceGroup.cxx

+ 63 - 93
Source/cmLocalGenerator.cxx

@@ -20,6 +20,7 @@
 #include "cmMakefile.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSourceFile.h"
+#include "cmOrderLinkDirectories.h"
 
 cmLocalGenerator::cmLocalGenerator()
 {
@@ -1077,6 +1078,16 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
 }
 
 
+void 
+cmLocalGenerator::DetermineLibraryPathOrder(const cmTarget& target,
+                                            std::vector<std::string>& 
+                                            linkPaths,
+                                            std::vector<std::string>&
+                                            linkLibs)
+{ 
+
+}
+
 /**
  * Output the linking rules on a command line.  For executables,
  * targetLibrary should be a NULL pointer.  For libraries, it should point
@@ -1088,7 +1099,6 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
 {
   // Try to emit each search path once
   std::set<cmStdString> emitted;
-
   // Embed runtime search paths if possible and if required.
   bool outputRuntime = true;
   std::string runtimeFlag;
@@ -1097,12 +1107,21 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
 
   std::string buildType =  m_Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
   buildType = cmSystemTools::UpperCase(buildType);
-
+  cmTarget::LinkLibraryType cmakeBuildType = cmTarget::GENERAL;
+  if(buildType == "DEBUG")
+    {
+    cmakeBuildType = cmTarget::DEBUG;
+    }
+  if(buildType.size())
+    {
+    cmakeBuildType = cmTarget::OPTIMIZED;
+    }
   const char* linkLanguage = tgt.GetLinkerLanguage(this->GetGlobalGenerator());
   if(!linkLanguage)
     {
-    cmSystemTools::Error("CMake can not determine linker language for target:",
-                         tgt.GetName());
+    cmSystemTools::
+      Error("CMake can not determine linker language for target:",
+            tgt.GetName());
     return;
     }
   std::string runTimeFlagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
@@ -1137,8 +1156,32 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
     linkLibs += " ";
     }
   
-  const std::vector<std::string>& libdirs = tgt.GetLinkDirectories();
-  for(std::vector<std::string>::const_iterator libDir = libdirs.begin();
+  cmOrderLinkDirectories orderLibs;
+  std::string ext = 
+    m_Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX");
+  if(ext.size())
+    {
+    orderLibs.AddLinkExtension(ext.c_str());
+    }
+  ext = 
+    m_Makefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_SUFFIX");
+  if(ext.size())
+    {
+    orderLibs.AddLinkExtension(ext.c_str());
+    }
+  ext = 
+    m_Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
+  if(ext.size())
+    {
+    orderLibs.AddLinkExtension(ext.c_str());
+    }
+  // compute the correct order for -L paths
+  orderLibs.SetLinkInformation(tgt, cmakeBuildType, targetLibrary);
+  orderLibs.DetermineLibraryPathOrder();
+  std::vector<cmStdString> libdirs;
+  std::vector<cmStdString> linkItems;
+  orderLibs.GetLinkerInformation(libdirs, linkItems);
+  for(std::vector<cmStdString>::const_iterator libDir = libdirs.begin();
       libDir != libdirs.end(); ++libDir)
     { 
     std::string libpath = this->ConvertToOutputForExisting(libDir->c_str());
@@ -1169,103 +1212,30 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
       }
     }
 
-  std::string linkSuffix = m_Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
+  std::string linkSuffix =
+    m_Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
   std::string regexp = ".*\\";
   regexp += linkSuffix;
   regexp += "$";
   cmsys::RegularExpression hasSuffix(regexp.c_str());
   std::string librariesLinked;
-  const cmTarget::LinkLibraries& libs = tgt.GetLinkLibraries();
-  for(cmTarget::LinkLibraries::const_iterator lib = libs.begin();
-      lib != libs.end(); ++lib)
-    {
-    // Don't link the library against itself!
-    if(targetLibrary && (lib->first == targetLibrary)) continue;
-    // use the correct lib for the current configuration
-    if (lib->second == cmTarget::DEBUG && buildType != "DEBUG")
-      {
-      continue;
-      }
-    if (lib->second == cmTarget::OPTIMIZED && buildType == "DEBUG")
-      {
-      continue;
-      }
-    // skip zero size library entries, this may happen
-    // if a variable expands to nothing.
-    if (lib->first.size() == 0) continue;
-    // if it is a full path break it into -L and -l
+  for(std::vector<cmStdString>::iterator lib = linkItems.begin();
+      lib != linkItems.end(); ++lib)
+    {
+    cmStdString& linkItem = *lib;
+    // check to see if the link item has a -l already
     cmsys::RegularExpression reg("^([ \t]*\\-[lWRB])|([ \t]*\\-framework)|(\\${)|([ \t]*\\-pthread)|([ \t]*`)");
-    if(lib->first.find('/') != std::string::npos
-       && !reg.find(lib->first))
+    if(!reg.find(linkItem))
       {
-      std::string dir, file;
-      cmSystemTools::SplitProgramPath(lib->first.c_str(),
-                                      dir, file);
-      std::string libpath = this->ConvertToOutputForExisting(dir.c_str());
-      if(emitted.insert(libpath).second)
-        {
-        linkLibs += libPathFlag;
-        linkLibs += libpath;
-        linkLibs += " ";
-        if(outputRuntime)
-          {
-          runtimeDirs.push_back( libpath );
-          }
-        }  
-      cmsys::RegularExpression libname("^lib([^/]*)(\\.so|\\.lib|\\.dll|\\.sl|\\.a|\\.dylib).*");
-      cmsys::RegularExpression libname_noprefix("([^/]*)(\\.so|\\.lib|\\.dll|\\.sl|\\.a|\\.dylib).*");
-      if(libname.find(file))
-        {
-        // Library had "lib" prefix.
-        librariesLinked += libLinkFlag;
-        file = libname.match(1);
-        // if ignore libprefix is on,
-        // then add the lib prefix back into the name
-        if(m_IgnoreLibPrefix)
-          {
-          file = "lib" + file;
-          }
-        librariesLinked += file;
-        if(linkSuffix.size() && !hasSuffix.find(file))
-          {
-          librariesLinked += linkSuffix;
-          }
-        librariesLinked += " ";
-        }
-      else if(libname_noprefix.find(file))
-        {
-        // Library had no "lib" prefix.
-        librariesLinked += libLinkFlag;
-        file = libname_noprefix.match(1);
-        librariesLinked += file;
-        if(linkSuffix.size() && !hasSuffix.find(file))
-          {
-          librariesLinked +=  linkSuffix;
-          }
-        librariesLinked += " ";
-        }
-      else
-        {
-        // Error parsing the library name.  Just use the full path.
-        // The linker will give an error if it is invalid.
-        librariesLinked += lib->first;
-        librariesLinked += " ";
-        }
+      librariesLinked += libLinkFlag;
       }
-    // not a full path, so add -l name
-    else
+    librariesLinked += linkItem;
+    
+    if(linkSuffix.size() && !hasSuffix.find(linkItem))
       {
-      if(!reg.find(lib->first))
-        {
-        librariesLinked += libLinkFlag;
-        }
-      librariesLinked += lib->first;
-      if(linkSuffix.size() && !hasSuffix.find(lib->first))
-        {
-        librariesLinked += linkSuffix;
-        }
-      librariesLinked += " ";
+      librariesLinked += linkSuffix;
       }
+    librariesLinked += " ";
     }
 
   linkLibs += librariesLinked;

+ 3 - 1
Source/cmLocalGenerator.h

@@ -103,7 +103,9 @@ public:
   ///! for existing files convert to output path and short path if spaces
   std::string ConvertToOutputForExisting(const char* p);
   
-
+  void DetermineLibraryPathOrder(const cmTarget& target,
+                                 std::vector<std::string>& linkPaths,
+                                 std::vector<std::string>& linkLibs);
 protected:
   /** Construct a script from the given list of command lines.  */
   std::string ConstructScript(const cmCustomCommandLines& commandLines,

+ 356 - 0
Source/cmOrderLinkDirectories.cxx

@@ -0,0 +1,356 @@
+#include "cmOrderLinkDirectories.h"
+#include "cmSystemTools.h"
+#include "cmsys/RegularExpression.hxx"
+
+
+inline void printv(std::vector<cmStdString>& v)
+{
+  for(unsigned int i = 0; i < v.size(); ++i)
+    {
+    std::cerr << "[" << v[i] << "]" << " ";
+    }
+  std::cerr << "\n";
+}
+
+
+//-------------------------------------------------------------------
+bool cmOrderLinkDirectories::LibraryInDirectory(const char* dir, 
+                                                const char* lib)
+{
+  cmStdString path = dir;
+  path += "/";
+  path += lib;
+  // first look for the library as given
+  if(cmSystemTools::FileExists(path.c_str()))
+    {
+    return true;
+    }
+  // next remove the extension (.a, .so ) and look for the library
+  // under a different name as the linker can do either
+  if(m_RemoveLibraryExtension.find(lib))
+    {
+    cmStdString lib = m_RemoveLibraryExtension.match(1);
+    cmStdString ext = m_RemoveLibraryExtension.match(2);
+    for(std::vector<cmStdString>::iterator i = m_LinkExtensions.begin();
+        i != m_LinkExtensions.end(); ++i)
+      {
+      if(ext != *i)
+        {
+        path = dir;
+        path += "/";
+        path += lib + *i;
+        if(cmSystemTools::FileExists(path.c_str()))
+          {
+          return true;
+          } 
+        }
+      }
+    }
+  return false;
+}
+
+//-------------------------------------------------------------------
+void cmOrderLinkDirectories::FindLibrariesInSeachPaths()
+{
+  for(std::set<cmStdString>::iterator dir = m_LinkPathSet.begin();
+      dir != m_LinkPathSet.end(); ++dir)
+    {
+    for(std::map<cmStdString, Library>::iterator lib
+          = m_FullPathLibraries.begin();
+        lib != m_FullPathLibraries.end(); ++lib)
+      {
+      if(lib->second.Path != *dir)
+        {
+        if(LibraryInDirectory(dir->c_str(), lib->second.File.c_str()))
+          {
+          m_LibraryToDirectories[lib->second.FullPath].push_back(*dir);
+          }
+        }
+      }
+    }
+}
+                 
+//-------------------------------------------------------------------
+void cmOrderLinkDirectories::FindIndividualLibraryOrders()
+{
+  for(std::vector<Library>::iterator lib = m_MultiDirectoryLibraries.begin();
+      lib != m_MultiDirectoryLibraries.end(); ++lib)
+    {
+    std::vector<cmStdString>& dirs = m_LibraryToDirectories[lib->FullPath];
+    m_DirectoryToAfterList[lib->Path] = dirs;
+    }
+}
+
+
+//-------------------------------------------------------------------
+void
+cmOrderLinkDirectories::PrintMap(const char* name,
+                       std::map<cmStdString, std::vector<cmStdString> >& m)
+{
+  std::cerr << name << "\n";
+  for(std::map<cmStdString, std::vector<cmStdString> >::iterator i =
+        m.begin(); i != m.end();
+      ++i)
+    {
+    std::cerr << i->first << ":  ";
+    for(std::vector<cmStdString>::iterator l = i->second.begin();
+        l != i->second.end(); ++l)
+      {
+      std::cerr << *l << " ";
+      }
+    std::cerr << "\n";
+    }
+}
+
+//-------------------------------------------------------------------
+void cmOrderLinkDirectories::CreateRegularExpressions()
+{
+  cmStdString libext = "(";
+  bool first = true;
+  for(std::vector<cmStdString>::iterator i = m_LinkExtensions.begin();
+      i != m_LinkExtensions.end(); ++i)
+    {
+    if(!first)
+      {
+      libext += "|";
+      }
+    first = false;
+    libext += "\\";
+    libext += *i;
+    }
+  libext += ").*";
+  cmStdString reg("(.*)");
+  reg += libext;
+  m_RemoveLibraryExtension.compile(reg.c_str());
+  reg = "^lib([^/]*)";
+  reg += libext;
+  m_ExtractBaseLibraryName.compile(reg.c_str());
+  reg = "([^/]*)";
+  reg += libext;
+  m_ExtractBaseLibraryNameNoPrefix.compile(reg.c_str());
+}
+
+
+//-------------------------------------------------------------------
+void cmOrderLinkDirectories::PrepareLinkTargets()
+{
+  for(std::vector<cmStdString>::iterator i = m_LinkItems.begin();
+      i != m_LinkItems.end(); ++i)
+    {
+    // separate the library name from libfoo.a or foo.a
+    if(m_ExtractBaseLibraryName.find(*i))
+      {
+      *i = m_ExtractBaseLibraryName.match(1);
+      }
+    else if(m_ExtractBaseLibraryNameNoPrefix.find(*i))
+      {
+      *i = m_ExtractBaseLibraryNameNoPrefix.match(1);
+      }
+    }
+}
+
+//-------------------------------------------------------------------
+bool cmOrderLinkDirectories::CanBeBefore(const cmStdString& d1,
+                                         const cmStdString& d2)
+{
+  if(m_DirectoryToAfterList.count(d2) == 0)
+    {
+    return true;
+    }
+  std::vector<cmStdString>& d2dirs = m_DirectoryToAfterList[d2];
+  // is d1 in the d2's list of directories that d2 must be before
+  // if so, then d1 can not come before d2
+  for(std::vector<cmStdString>::iterator i = d2dirs.begin();
+      i != d2dirs.end(); ++i)
+    {
+    if(*i == d1)
+      {
+      return false;
+      }
+    }
+  return true;
+}
+
+// This is a stl function object used to sort
+// the vector of library paths.  It returns true
+// if left directory can be before right directory (no swap).
+// It also checks for the impossible case of two libraries and
+// two directories that have both libraries.
+struct cmOrderLinkDirectoriesCompare
+  : public std::binary_function <cmStdString, cmStdString, bool> 
+{
+  cmOrderLinkDirectoriesCompare() 
+  {
+    This = 0;
+  }
+  bool operator()(
+                  const cmStdString& left, 
+                  const cmStdString& right
+                  ) const
+  {
+    bool ret = This->CanBeBefore(left, right);
+    if(!ret)
+      {
+      // check for the case when both libraries have to come
+      // before each other 
+      if(!This->CanBeBefore(right, left))
+        {
+        This->AddImpossible(right, left);
+        }
+      }
+    return ret;
+  }
+  cmOrderLinkDirectories* This;
+};
+
+//-------------------------------------------------------------------
+void cmOrderLinkDirectories::AddImpossible(const cmStdString& d1,
+                                           const cmStdString& d2)
+{
+  m_ImposibleDirectories.insert(d1);
+  m_ImposibleDirectories.insert(d2);
+}
+
+//-------------------------------------------------------------------
+void cmOrderLinkDirectories::OrderPaths(std::vector<cmStdString>&
+                                        orderedPaths)
+{
+  cmOrderLinkDirectoriesCompare comp;
+  comp.This = this;
+  std::sort(orderedPaths.begin(), orderedPaths.end(), comp);
+}
+
+//-------------------------------------------------------------------
+void cmOrderLinkDirectories::SetLinkInformation(const cmTarget& target,
+                                                cmTarget::LinkLibraryType 
+                                                linktype,
+                                                const char* targetLibrary)
+{
+    // collect the search paths from the target into paths set
+  const std::vector<std::string>& searchPaths = target.GetLinkDirectories();
+  for(std::vector<std::string>::const_iterator p = searchPaths.begin();
+      p != searchPaths.end(); ++p)
+    {
+    m_LinkPathSet.insert(*p);
+    }
+  // collect the link items from the target and put it into libs
+  const cmTarget::LinkLibraries& tlibs = target.GetLinkLibraries();
+  std::vector<cmStdString>  libs;
+  for(cmTarget::LinkLibraries::const_iterator lib = tlibs.begin();
+      lib != tlibs.end(); ++lib)
+    {
+    // skip zero size library entries, this may happen
+    // if a variable expands to nothing.
+    if (lib->first.size() == 0)
+      {
+      continue;
+      }
+    // Don't link the library against itself!
+    if(targetLibrary && (lib->first == targetLibrary))
+      {
+      continue;
+      }  
+    // use the correct lib for the current configuration
+    if (lib->second == cmTarget::DEBUG && linktype != cmTarget::DEBUG)
+      {
+      continue;
+      }
+    if (lib->second == cmTarget::OPTIMIZED && 
+        linktype != cmTarget::OPTIMIZED)
+      {
+      continue;
+      }
+    m_RawLinkItems.push_back(lib->first);
+    }
+}
+
+//-------------------------------------------------------------------
+bool cmOrderLinkDirectories::DetermineLibraryPathOrder()
+{
+  // set up all the regular expressions
+  this->CreateRegularExpressions();
+  std::vector<cmStdString> finalOrderPaths;
+  // find all libs that are full paths
+  Library aLib;
+  cmStdString dir;
+  cmStdString file;
+  for(unsigned int i=0; i < m_RawLinkItems.size(); ++i)
+    {
+    if(cmSystemTools::FileIsFullPath(m_RawLinkItems[i].c_str()))
+      {
+      cmSystemTools::SplitProgramPath(m_RawLinkItems[i].c_str(),
+                                      dir, file);
+      m_LinkPathSet.insert(dir);
+      aLib.FullPath = m_RawLinkItems[i];
+      aLib.File = file;
+      aLib.Path = dir;
+      m_FullPathLibraries[aLib.FullPath] = aLib;
+      m_LinkItems.push_back(file);
+      }
+    else
+      {
+      m_LinkItems.push_back(m_RawLinkItems[i]);
+      }
+    }
+  this->FindLibrariesInSeachPaths();
+  for(std::map<cmStdString, std::vector<cmStdString> >::iterator lib =
+        m_LibraryToDirectories.begin(); lib!= m_LibraryToDirectories.end(); 
+      ++lib)
+    {
+    if(lib->second.size() > 0)
+      {
+      m_MultiDirectoryLibraries.push_back(m_FullPathLibraries[lib->first]);
+      }
+    else
+      {
+      m_SingleDirectoryLibraries.push_back(m_FullPathLibraries[lib->first]);
+      }
+    }
+  this->FindIndividualLibraryOrders();
+  m_SortedSearchPaths.clear();
+  for(std::set<cmStdString>::iterator i = m_LinkPathSet.begin();
+      i != m_LinkPathSet.end(); ++i)
+    {
+    m_SortedSearchPaths.push_back(*i);
+    }
+  
+  this->OrderPaths(m_SortedSearchPaths);
+  // now turn libfoo.a into foo and foo.a into foo
+  // This will prepare the link items for -litem 
+  this->PrepareLinkTargets();
+  //  this->PrintMap("m_DirectoryToAfterList", m_DirectoryToAfterList);
+  //this->PrintMap("m_LibraryToDirectories", m_LibraryToDirectories);
+  //std::cerr << "link objects: ";
+  //printv(m_LinkItems);
+  if(m_ImposibleDirectories.size())
+    {
+    return false;
+    }
+  return true;
+}
+
+std::string cmOrderLinkDirectories::GetWarnings()
+{
+  std::string warning = "It is impossible to order the linker search path in such a way that libraries specified as full paths will be picked by the linker.\nDirectories and libraries involvied are:\n";
+  for(std::set<cmStdString>::iterator i = m_ImposibleDirectories.begin();
+      i != m_ImposibleDirectories.end(); ++i)
+    {
+    warning += "Directory: ";
+    warning += *i;
+    warning += " contains ";
+    std::map<cmStdString, std::vector<cmStdString> >::iterator j;
+    for(j = m_LibraryToDirectories.begin(); 
+        j != m_LibraryToDirectories.end(); ++j)
+      {
+      if(std::find(j->second.begin(), j->second.end(), *i)
+         != j->second.end())
+        {
+        warning += "Library: ";
+        warning += j->first;
+        warning += "\n";
+        }
+      }
+    }
+  warning += "\n";
+  return warning;
+}

+ 126 - 0
Source/cmOrderLinkDirectories.h

@@ -0,0 +1,126 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  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 cmOrderLinkDirectories_h
+#define cmOrderLinkDirectories_h
+
+#include <cmStandardIncludes.h>
+#include <map>
+#include <vector>
+#include "cmTarget.h"
+#include "cmsys/RegularExpression.hxx"
+
+
+/** \class cmOrderLinkDirectories
+ * \brief Compute the best -L path order
+ *
+ * This class computes the best order for -L paths.
+ * It tries to make sure full path specified libraries are 
+ * used.  For example if you have /usr/mylib/libfoo.a on as
+ * a link library for a target, and you also have /usr/lib/libbar.a
+ * and you also have /usr/lib/libfoo.a, then you would
+ * want -L/usr/mylib -L/usr/lib to make sure the correct libfoo.a is 
+ * found by the linker.  The algorithm is as follows:
+ * - foreach library create a vector of directories it exists in.
+ * - foreach directory create a vector of directories that must come
+ *   after it, put this in a map<dir, vector<dir>> mapping from a directory
+ *   to the vector of directories that it must be before.
+ * - put all directories into a vector
+ * - sort the vector with a compare function CanBeBefore
+ *   CanBeBefore returns true if a directory is OK to be before
+ *   another directory.  This is determined by looking at the 
+ *   map<dir vector<dir>> and seeing if d1 is in the vector for d2.
+ */
+class cmOrderLinkDirectories
+{
+public:
+  ///! set link information from the target
+  void SetLinkInformation(const cmTarget&, cmTarget::LinkLibraryType,
+                          const char* targetLibrary);
+  ///! Compute the best order for -L paths from GetLinkLibraries
+  bool DetermineLibraryPathOrder();
+  ///! Get the results from DetermineLibraryPathOrder
+  void GetLinkerInformation(std::vector<cmStdString>& searchPaths,
+                            std::vector<cmStdString>& linkItems)
+  {
+    linkItems = m_LinkItems;
+    searchPaths = m_SortedSearchPaths;
+  }
+  // should be set from CMAKE_STATIC_LIBRARY_SUFFIX,
+  // CMAKE_SHARED_LIBRARY_SUFFIX
+  // CMAKE_LINK_LIBRARY_SUFFIX
+  void AddLinkExtension(const char* e)
+  {
+    m_LinkExtensions.push_back(e);
+  }
+  // Return any warnings if the exist
+  std::string GetWarnings();
+
+  // structure to hold a full path library link item
+  struct Library
+  {
+    cmStdString FullPath;
+    cmStdString File;
+    cmStdString Path;
+  };
+  friend struct cmOrderLinkDirectoriesCompare;
+private:
+  void CreateRegularExpressions();
+  void DetermineLibraryPathOrder(std::vector<cmStdString>& searchPaths,
+                                 std::vector<cmStdString>& libs,
+                                 std::vector<cmStdString>& sortedPaths);
+  void PrepareLinkTargets();
+  bool LibraryInDirectory(const char* dir, const char* lib);
+  void FindLibrariesInSeachPaths();
+  void FindIndividualLibraryOrders();
+  void PrintMap(const char* name,
+                std::map<cmStdString, std::vector<cmStdString> >& m);
+  void OrderPaths(std::vector<cmStdString>& paths);
+  bool CanBeBefore(const cmStdString& d1,
+                   const cmStdString& d2);
+  void AddImpossible(const cmStdString& ,
+                     const cmStdString& );
+private:
+  // map from library to directories that it is in other than its full path
+  std::map<cmStdString, std::vector<cmStdString> > m_LibraryToDirectories;
+  // map from directory to vector of directories that must be after it
+  std::map<cmStdString, std::vector<cmStdString> > m_DirectoryToAfterList;
+  // map from full path to a Library struct
+  std::map<cmStdString, Library> m_FullPathLibraries;
+  // libraries that are found in multiple directories
+  std::vector<Library> m_MultiDirectoryLibraries;
+  // libraries that are only found in one directory
+  std::vector<Library> m_SingleDirectoryLibraries;
+  // This is a vector of all the link objects -lm or m
+  std::vector<cmStdString> m_LinkItems;
+  // Unprocessed link items
+  std::vector<cmStdString> m_RawLinkItems;
+  // This vector holds the sorted -L paths
+  std::vector<cmStdString> m_SortedSearchPaths;
+  // This is the set of -L paths unsorted, but unique
+  std::set<cmStdString> m_LinkPathSet;
+  // the names of link extensions
+  std::vector<cmStdString> m_LinkExtensions;
+  // set of directories that can not be put in the correct order
+  std::set<cmStdString> m_ImposibleDirectories;
+  // library regular expressions
+  cmsys::RegularExpression m_RemoveLibraryExtension;
+  cmsys::RegularExpression m_ExtractBaseLibraryName;
+  cmsys::RegularExpression m_ExtractBaseLibraryNameNoPrefix;
+  
+};
+
+#endif

+ 1 - 0
bootstrap

@@ -54,6 +54,7 @@ CMAKE_CXX_SOURCES="\
   cmCustomCommand \
   cmCacheManager \
   cmListFileCache \
+  cmOrderLinkDirectories \
   cmSourceGroup"
 
 CMAKE_C_SOURCES="\