summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Hoffman <bill.hoffman@kitware.com>2005-02-24 18:16:41 (GMT)
committerBill Hoffman <bill.hoffman@kitware.com>2005-02-24 18:16:41 (GMT)
commitff812580ebec0b7ff908feeb256ad263bfc0c41a (patch)
tree0d99dfaa7a1790bd9435481d0ff8fdbe215a99c9
parent9c4997bf06361b05ddad6d23388086b012d381fb (diff)
downloadCMake-ff812580ebec0b7ff908feeb256ad263bfc0c41a.zip
CMake-ff812580ebec0b7ff908feeb256ad263bfc0c41a.tar.gz
CMake-ff812580ebec0b7ff908feeb256ad263bfc0c41a.tar.bz2
ENH: add a new library path ordering algorithm to make sure -L paths will pick the correct libraries if possible
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/cmLocalGenerator.cxx156
-rw-r--r--Source/cmLocalGenerator.h4
-rw-r--r--Source/cmOrderLinkDirectories.cxx356
-rw-r--r--Source/cmOrderLinkDirectories.h126
-rwxr-xr-xbootstrap1
6 files changed, 550 insertions, 94 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 8e09cfd..6ded4e8 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -44,6 +44,7 @@ SET(SRCS
cmMakeDepend.h
cmMakefile.cxx
cmMakefile.h
+ cmOrderLinkDirectories.cxx
cmSourceFile.cxx
cmSourceFile.h
cmSourceGroup.cxx
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 0943c0c..3b91dc8 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/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;
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 8dea2d5..88dba50 100644
--- a/Source/cmLocalGenerator.h
+++ b/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,
diff --git a/Source/cmOrderLinkDirectories.cxx b/Source/cmOrderLinkDirectories.cxx
new file mode 100644
index 0000000..7697aaa
--- /dev/null
+++ b/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;
+}
diff --git a/Source/cmOrderLinkDirectories.h b/Source/cmOrderLinkDirectories.h
new file mode 100644
index 0000000..234a343
--- /dev/null
+++ b/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
diff --git a/bootstrap b/bootstrap
index afc23c6..1a614bf 100755
--- a/bootstrap
+++ b/bootstrap
@@ -54,6 +54,7 @@ CMAKE_CXX_SOURCES="\
cmCustomCommand \
cmCacheManager \
cmListFileCache \
+ cmOrderLinkDirectories \
cmSourceGroup"
CMAKE_C_SOURCES="\