diff options
Diffstat (limited to 'Source/cmOrderLinkDirectories.cxx')
-rw-r--r-- | Source/cmOrderLinkDirectories.cxx | 710 |
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; -} |