diff options
Diffstat (limited to 'Source/cmOrderRuntimeDirectories.cxx')
-rw-r--r-- | Source/cmOrderRuntimeDirectories.cxx | 325 |
1 files changed, 0 insertions, 325 deletions
diff --git a/Source/cmOrderRuntimeDirectories.cxx b/Source/cmOrderRuntimeDirectories.cxx deleted file mode 100644 index b0fe337..0000000 --- a/Source/cmOrderRuntimeDirectories.cxx +++ /dev/null @@ -1,325 +0,0 @@ -/*========================================================================= - - 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. - -=========================================================================*/ -#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()); -} |