summaryrefslogtreecommitdiffstats
path: root/Source/cmOrderLinkDirectories.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmOrderLinkDirectories.cxx')
-rw-r--r--Source/cmOrderLinkDirectories.cxx710
1 files changed, 0 insertions, 710 deletions
diff --git a/Source/cmOrderLinkDirectories.cxx b/Source/cmOrderLinkDirectories.cxx
deleted file mode 100644
index 57b7470..0000000
--- a/Source/cmOrderLinkDirectories.cxx
+++ /dev/null
@@ -1,710 +0,0 @@
-#include "cmOrderLinkDirectories.h"
-#include "cmSystemTools.h"
-#include "cmsys/RegularExpression.hxx"
-#include <ctype.h>
-
-//#define CM_ORDER_LINK_DIRECTORIES_DEBUG
-
-//-------------------------------------------------------------------
-cmOrderLinkDirectories::cmOrderLinkDirectories()
-{
- this->StartLinkType = LinkUnknown;
- this->LinkTypeEnabled = false;
- this->Debug = false;
-}
-
-//-------------------------------------------------------------------
-void
-cmOrderLinkDirectories
-::SetLinkTypeInformation(LinkType start_link_type,
- const char* static_link_type_flag,
- const char* shared_link_type_flag)
-{
- // We can support link type switching only if all needed flags are
- // known.
- this->StartLinkType = start_link_type;
- if(static_link_type_flag && *static_link_type_flag &&
- shared_link_type_flag && *shared_link_type_flag)
- {
- this->LinkTypeEnabled = true;
- this->StaticLinkTypeFlag = static_link_type_flag;
- this->SharedLinkTypeFlag = shared_link_type_flag;
- }
- else
- {
- this->LinkTypeEnabled = false;
- this->StaticLinkTypeFlag = "";
- this->SharedLinkTypeFlag = "";
- }
-}
-
-//-------------------------------------------------------------------
-void cmOrderLinkDirectories::SetCurrentLinkType(LinkType lt)
-{
- if(this->CurrentLinkType != lt)
- {
- this->CurrentLinkType = lt;
-
- if(this->LinkTypeEnabled)
- {
- switch(this->CurrentLinkType)
- {
- case LinkStatic:
- this->LinkItems.push_back(this->StaticLinkTypeFlag); break;
- case LinkShared:
- this->LinkItems.push_back(this->SharedLinkTypeFlag); break;
- default: break;
- }
- }
- }
-}
-
-//-------------------------------------------------------------------
-bool cmOrderLinkDirectories::LibraryInDirectory(const char* desiredLib,
- const char* dir,
- const char* libIn)
-{
- // first look for the library as given
- if(this->LibraryMayConflict(desiredLib, dir, libIn))
- {
- return true;
- }
- // next remove the extension (.a, .so ) and look for the library
- // under a different name as the linker can do either
- if(this->RemoveLibraryExtension.find(libIn))
- {
- cmStdString lib = this->RemoveLibraryExtension.match(1);
- cmStdString ext = this->RemoveLibraryExtension.match(2);
- for(std::vector<cmStdString>::iterator i = this->LinkExtensions.begin();
- i != this->LinkExtensions.end(); ++i)
- {
- if(ext != *i)
- {
- std::string fname = lib;
- lib += *i;
- if(this->LibraryMayConflict(desiredLib, dir, fname.c_str()))
- {
- return true;
- }
- }
- }
- }
- return false;
-}
-
-//-------------------------------------------------------------------
-void cmOrderLinkDirectories::FindLibrariesInSearchPaths()
-{
- for(std::set<cmStdString>::iterator dir = this->LinkPathSet.begin();
- dir != this->LinkPathSet.end(); ++dir)
- {
- for(std::map<cmStdString, Library>::iterator lib
- = this->FullPathLibraries.begin();
- lib != this->FullPathLibraries.end(); ++lib)
- {
- if(lib->second.Path != *dir)
- {
- if(this->LibraryInDirectory(lib->second.FullPath.c_str(),
- dir->c_str(), lib->second.File.c_str()))
- {
- this->LibraryToDirectories[lib->second.FullPath].push_back(*dir);
- }
- }
- }
- }
-}
-
-//-------------------------------------------------------------------
-void cmOrderLinkDirectories::FindIndividualLibraryOrders()
-{
- for(std::vector<Library>::iterator lib =
- this->MultiDirectoryLibraries.begin();
- lib != this->MultiDirectoryLibraries.end(); ++lib)
- {
- std::vector<cmStdString>& dirs =
- this->LibraryToDirectories[lib->FullPath];
- std::vector<std::pair<cmStdString, std::vector<cmStdString> >
- >::iterator i;
- for(i = this->DirectoryToAfterList.begin();
- i != this->DirectoryToAfterList.end(); ++i)
- {
- if(i->first == lib->Path)
- {
- break;
- }
- }
- if(i == this->DirectoryToAfterList.end())
- {
- std::cerr << "ERROR: should not happen\n";
- }
- else
- {
- for(std::vector<cmStdString>::iterator d = dirs.begin();
- d != dirs.end(); ++d)
- {
- i->second.push_back(*d);
- }
- }
- }
-}
-
-//-------------------------------------------------------------------
-std::string cmOrderLinkDirectories::NoCaseExpression(const char* str)
-{
- std::string ret;
- const char* s = str;
- while(*s)
- {
- if(*s == '.')
- {
- ret += *s;
- }
- else
- {
- ret += "[";
- ret += tolower(*s);
- ret += toupper(*s);
- ret += "]";
- }
- s++;
- }
- return ret;
-}
-
-//-------------------------------------------------------------------
-void cmOrderLinkDirectories::CreateRegularExpressions()
-{
- this->SplitFramework.compile("(.*)/(.*)\\.framework$");
-
- // Compute a regex to match link extensions.
- cmStdString libext = this->CreateExtensionRegex(this->LinkExtensions);
-
- // Create regex to remove any library extension.
- cmStdString reg("(.*)");
- reg += libext;
- this->RemoveLibraryExtension.compile(reg.c_str());
-
- // Create a regex to match a library name. Match index 1 will be
- // the prefix if it exists and empty otherwise. Match index 2 will
- // be the library name. Match index 3 will be the library
- // extension.
- reg = "^(";
- for(std::set<cmStdString>::iterator p = this->LinkPrefixes.begin();
- p != this->LinkPrefixes.end(); ++p)
- {
- reg += *p;
- reg += "|";
- }
- reg += ")";
- reg += "([^/]*)";
-
- // Create a regex to match any library name.
- cmStdString reg_any = reg;
- reg_any += libext;
-#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
- fprintf(stderr, "any regex [%s]\n", reg_any.c_str());
-#endif
- this->ExtractAnyLibraryName.compile(reg_any.c_str());
-
- // Create a regex to match static library names.
- if(!this->StaticLinkExtensions.empty())
- {
- cmStdString reg_static = reg;
- reg_static += this->CreateExtensionRegex(this->StaticLinkExtensions);
-#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
- fprintf(stderr, "static regex [%s]\n", reg_static.c_str());
-#endif
- this->ExtractStaticLibraryName.compile(reg_static.c_str());
- }
-
- // Create a regex to match shared library names.
- if(!this->SharedLinkExtensions.empty())
- {
- cmStdString reg_shared = reg;
- reg_shared += this->CreateExtensionRegex(this->SharedLinkExtensions);
-#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
- fprintf(stderr, "shared regex [%s]\n", reg_shared.c_str());
-#endif
- this->ExtractSharedLibraryName.compile(reg_shared.c_str());
- }
-}
-
-//-------------------------------------------------------------------
-std::string
-cmOrderLinkDirectories::CreateExtensionRegex(
- std::vector<cmStdString> const& exts)
-{
- // Build a list of extension choices.
- cmStdString libext = "(";
- const char* sep = "";
- for(std::vector<cmStdString>::const_iterator i = exts.begin();
- i != exts.end(); ++i)
- {
- // Separate this choice from the previous one.
- libext += sep;
- sep = "|";
-
- // Store this extension choice with the "." escaped.
- libext += "\\";
-#if defined(_WIN32) && !defined(__CYGWIN__)
- libext += this->NoCaseExpression(i->c_str());
-#else
- libext += *i;
-#endif
- }
-
- // Finish the list.
- libext += ").*";
- return libext;
-}
-
-//-------------------------------------------------------------------
-void cmOrderLinkDirectories::PrepareLinkTargets()
-{
- std::vector<cmStdString> originalLinkItems = this->LinkItems;
- this->LinkItems.clear();
- this->CurrentLinkType = this->StartLinkType;
- for(std::vector<cmStdString>::iterator i = originalLinkItems.begin();
- i != originalLinkItems.end(); ++i)
- {
- // Parse out the prefix, base, and suffix components of the
- // library name. If the name matches that of a shared or static
- // library then set the link type accordingly.
- //
- // Search for shared library names first because some platforms
- // have shared libraries with names that match the static library
- // pattern. For example cygwin and msys use the convention
- // libfoo.dll.a for import libraries and libfoo.a for static
- // libraries. On AIX a library with the name libfoo.a can be
- // shared!
- if(this->ExtractSharedLibraryName.find(*i))
- {
-#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
- fprintf(stderr, "shared regex matched [%s] [%s] [%s]\n",
- this->ExtractSharedLibraryName.match(1).c_str(),
- this->ExtractSharedLibraryName.match(2).c_str(),
- this->ExtractSharedLibraryName.match(3).c_str());
-#endif
- this->SetCurrentLinkType(LinkShared);
- this->LinkItems.push_back(this->ExtractSharedLibraryName.match(2));
- }
- else if(this->ExtractStaticLibraryName.find(*i))
- {
-#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
- fprintf(stderr, "static regex matched [%s] [%s] [%s]\n",
- this->ExtractStaticLibraryName.match(1).c_str(),
- this->ExtractStaticLibraryName.match(2).c_str(),
- this->ExtractStaticLibraryName.match(3).c_str());
-#endif
- this->SetCurrentLinkType(LinkStatic);
- this->LinkItems.push_back(this->ExtractStaticLibraryName.match(2));
- }
- else if(this->ExtractAnyLibraryName.find(*i))
- {
-#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
- fprintf(stderr, "any regex matched [%s] [%s] [%s]\n",
- this->ExtractAnyLibraryName.match(1).c_str(),
- this->ExtractAnyLibraryName.match(2).c_str(),
- this->ExtractAnyLibraryName.match(3).c_str());
-#endif
- this->SetCurrentLinkType(this->StartLinkType);
- this->LinkItems.push_back(this->ExtractAnyLibraryName.match(2));
- }
- else
- {
- this->SetCurrentLinkType(this->StartLinkType);
- this->LinkItems.push_back(*i);
- }
- }
-
- // Restore the original linking type so system runtime libraries are
- // linked properly.
- this->SetCurrentLinkType(this->StartLinkType);
-}
-
-//-------------------------------------------------------------------
-bool cmOrderLinkDirectories::FindPathNotInDirectoryToAfterList(
- cmStdString& path)
-{
- for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
- >::iterator i = this->DirectoryToAfterList.begin();
- i != this->DirectoryToAfterList.end(); ++i)
- {
- const cmStdString& p = i->first;
- bool found = false;
- for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
- >::iterator j = this->DirectoryToAfterList.begin();
- j != this->DirectoryToAfterList.end() && !found; ++j)
- {
- if(j != i)
- {
- found = (std::find(j->second.begin(), j->second.end(), p)
- != j->second.end());
- }
- }
- if(!found)
- {
- path = p;
- this->DirectoryToAfterList.erase(i);
- return true;
- }
- }
- path = "";
- return false;
-}
-
-
-//-------------------------------------------------------------------
-void cmOrderLinkDirectories::OrderPaths(std::vector<cmStdString>&
- orderedPaths)
-{
- cmStdString path;
- // This is a topological sort implementation
- // One at a time find paths that are not in any other paths after list
- // and put them into the orderedPaths vector in that order
- // FindPathNotInDirectoryToAfterList removes the path from the
- // this->DirectoryToAfterList once it is found
- while(this->FindPathNotInDirectoryToAfterList(path))
- {
- orderedPaths.push_back(path);
- }
- // at this point if there are still paths in this->DirectoryToAfterList
- // then there is a cycle and we are stuck
- if(this->DirectoryToAfterList.size())
- {
- for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
- >::iterator i = this->DirectoryToAfterList.begin();
- i != this->DirectoryToAfterList.end(); ++i)
- {
- this->ImpossibleDirectories.insert(i->first);
- // still put it in the path list in the order we find them
- orderedPaths.push_back(i->first);
- }
-
- }
-}
-
-//-------------------------------------------------------------------
-void cmOrderLinkDirectories::SetLinkInformation(
- const char* targetName,
- const std::vector<std::string>& linkLibraries,
- const std::vector<std::string>& linkDirectories,
- const cmTargetManifest& manifest,
- const char* configSubdir
- )
-{
- // Save the target name.
- this->TargetName = targetName;
-
- // Save the subdirectory used for linking in this configuration.
- this->ConfigSubdir = configSubdir? configSubdir : "";
-
- // Merge the link directory search path given into our path set.
- std::vector<cmStdString> empty;
- for(std::vector<std::string>::const_iterator p = linkDirectories.begin();
- p != linkDirectories.end(); ++p)
- {
- std::string dir = *p;
-#ifdef _WIN32
- // Avoid case problems for windows paths.
- if(dir.size() > 2 && dir[1] == ':')
- {
- if(dir[0] >= 'A' && dir[0] <= 'Z')
- {
- dir[0] += 'a' - 'A';
- }
- }
- dir = cmSystemTools::GetActualCaseForPath(dir.c_str());
-#endif
- if(this->DirectoryToAfterListEmitted.insert(dir).second)
- {
- std::pair<cmStdString, std::vector<cmStdString> > dp;
- dp.first = dir;
- this->DirectoryToAfterList.push_back(dp);
- this->LinkPathSet.insert(dir);
- }
- }
-
- // Append the link library list into our raw list.
- for(std::vector<std::string>::const_iterator l = linkLibraries.begin();
- l != linkLibraries.end(); ++l)
- {
- this->RawLinkItems.push_back(*l);
- }
-
- // Construct a set of files that will exist after building.
- for(cmTargetManifest::const_iterator i = manifest.begin();
- i != manifest.end(); ++i)
- {
- for(cmTargetSet::const_iterator j = i->second.begin();
- j != i->second.end(); ++j)
- {
- this->ManifestFiles.insert(*j);
- }
- }
-}
-
-//-------------------------------------------------------------------
-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;
- std::vector<cmStdString> empty;
- // do not add a -F for the system frameworks
- this->EmittedFrameworkPaths.insert("/System/Library/Frameworks");
- for(unsigned int i=0; i < this->RawLinkItems.size(); ++i)
- {
- bool framework = false;
-#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
- fprintf(stderr, "Raw link item [%s]\n", this->RawLinkItems[i].c_str());
-#endif
- // if it is a full path to an item then separate it from the path
- // this only works with files and paths
- cmStdString& item = this->RawLinkItems[i];
-
- if(cmSystemTools::FileIsFullPath(item.c_str()))
- {
- if(cmSystemTools::IsPathToFramework(item.c_str()))
- {
- this->SplitFramework.find(item.c_str());
- cmStdString path = this->SplitFramework.match(1);
- // Add the -F path if we have not yet done so
- if(this->EmittedFrameworkPaths.insert(path).second)
- {
- std::string fpath = "-F";
- fpath += cmSystemTools::ConvertToOutputPath(path.c_str());
- this->LinkItems.push_back(fpath);
- }
- // now add the -framework option
- std::string frame = "-framework ";
- frame += this->SplitFramework.match(2);
- this->LinkItems.push_back(frame);
- framework = true;
- }
- if(cmSystemTools::FileIsDirectory(item.c_str()))
- {
- if(!framework)
- {
- // A full path to a directory was found as a link item
- // warn user
- std::string message =
- "Warning: Ignoring path found in link libraries for target: ";
- message += this->TargetName;
- message += ", path is: ";
- message += this->RawLinkItems[i];
- message +=
- ". Expected a library name or a full path to a library name.";
- cmSystemTools::Message(message.c_str());
- continue;
- }
- } // is it a directory
- if(!framework)
- {
- dir = cmSystemTools::GetFilenamePath(this->RawLinkItems[i]);
- file = cmSystemTools::GetFilenameName(this->RawLinkItems[i]);
-#ifdef _WIN32
- // Avoid case problems for windows paths.
- if(dir.size() > 2 && dir[1] == ':')
- {
- if(dir[0] >= 'A' && dir[0] <= 'Z')
- {
- dir[0] += 'a' - 'A';
- }
- }
- dir = cmSystemTools::GetActualCaseForPath(dir.c_str());
-#endif
- if(this->DirectoryToAfterListEmitted.insert(dir).second)
- {
- std::pair<cmStdString, std::vector<cmStdString> > dp;
- dp.first = dir;
- this->DirectoryToAfterList.push_back(dp);
- }
- this->LinkPathSet.insert(dir);
- aLib.FullPath = this->RawLinkItems[i];
- aLib.File = file;
- aLib.Path = dir;
- this->FullPathLibraries[aLib.FullPath] = aLib;
-#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
- fprintf(stderr, "Storing item [%s]\n", file.c_str());
-#endif
- this->LinkItems.push_back(file);
- }
- }
- else
- {
- this->LinkItems.push_back(this->RawLinkItems[i]);
- }
- }
- this->FindLibrariesInSearchPaths();
- for(std::map<cmStdString, std::vector<cmStdString> >::iterator lib =
- this->LibraryToDirectories.begin();
- lib!= this->LibraryToDirectories.end();
- ++lib)
- {
- if(lib->second.size() > 0)
- {
- this->MultiDirectoryLibraries.push_back
- (this->FullPathLibraries[lib->first]);
- }
- else
- {
- this->SingleDirectoryLibraries.push_back
- (this->FullPathLibraries[lib->first]);
- }
- }
- this->FindIndividualLibraryOrders();
- this->SortedSearchPaths.clear();
- if(this->Debug)
- {
- this->PrintMap("this->LibraryToDirectories", this->LibraryToDirectories);
- this->PrintVector("this->DirectoryToAfterList",
- this->DirectoryToAfterList);
- }
- this->OrderPaths(this->SortedSearchPaths);
- // now turn libfoo.a into foo and foo.a into foo
- // This will prepare the link items for -litem
- this->PrepareLinkTargets();
- if(this->ImpossibleDirectories.size())
- {
- cmSystemTools::Message(this->GetWarnings().c_str());
- 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 involved are:\n";
-
- for(std::set<cmStdString>::iterator i = this->ImpossibleDirectories.begin();
- i != this->ImpossibleDirectories.end(); ++i)
- {
- warning += "Directory: ";
- warning += *i;
- warning += " contains:\n";
- std::map<cmStdString, std::vector<cmStdString> >::iterator j;
- for(j = this->LibraryToDirectories.begin();
- j != this->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";
- }
- warning += "\n";
- return warning;
-}
-
-//-------------------------------------------------------------------
-void
-cmOrderLinkDirectories::PrintMap(const char* name,
- std::map<cmStdString, std::vector<cmStdString> >& m)
-{
- std::cout << name << "\n";
- for(std::map<cmStdString, std::vector<cmStdString> >::iterator i =
- m.begin(); i != m.end();
- ++i)
- {
- std::cout << i->first << ": ";
- for(std::vector<cmStdString>::iterator l = i->second.begin();
- l != i->second.end(); ++l)
- {
- std::cout << *l << " ";
- }
- std::cout << "\n";
- }
-}
-//-------------------------------------------------------------------
-void
-cmOrderLinkDirectories::PrintVector(const char* name,
- std::vector<std::pair<cmStdString,
- std::vector<cmStdString> > >& m)
-{
- std::cout << name << "\n";
- for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
- >::iterator i = m.begin(); i != m.end(); ++i)
- {
- std::cout << i->first << ": ";
- for(std::vector<cmStdString>::iterator l = i->second.begin();
- l != i->second.end(); ++l)
- {
- std::cout << *l << " ";
- }
- std::cout << "\n";
- }
-}
-
-void cmOrderLinkDirectories::GetFullPathLibraries(std::vector<cmStdString>&
- libs)
-{
- for(std::map<cmStdString, Library>::iterator i =
- this->FullPathLibraries.begin();
- i != this->FullPathLibraries.end(); ++i)
- {
- libs.push_back(i->first);
- }
-
-}
-
-//----------------------------------------------------------------------------
-bool cmOrderLinkDirectories::LibraryMayConflict(const char* desiredLib,
- const char* dir,
- const char* fname)
-{
- // We need to check whether the given file may be picked up by the
- // linker. This will occur if it exists as given or may be built
- // using the name given.
- bool found = false;
- std::string path = dir;
- path += "/";
- path += fname;
- if(this->ManifestFiles.find(path) != this->ManifestFiles.end())
- {
- found = true;
- }
- else if(cmSystemTools::FileExists(path.c_str()))
- {
- found = true;
- }
-
- // When linking with a multi-configuration build tool the
- // per-configuration subdirectory is added to each link path. Check
- // this subdirectory too.
- if(!found && !this->ConfigSubdir.empty())
- {
- path = dir;
- path += "/";
- path += this->ConfigSubdir;
- path += "/";
- path += fname;
- if(this->ManifestFiles.find(path) != this->ManifestFiles.end())
- {
- found = true;
- }
- else if(cmSystemTools::FileExists(path.c_str()))
- {
- found = true;
- }
- }
-
- // A library conflicts if it is found and is not a symlink back to
- // the desired library.
- if(found)
- {
- return !cmSystemTools::SameFile(desiredLib, path.c_str());
- }
- return false;
-}