diff options
Diffstat (limited to 'Source/cmFindLibraryCommand.cxx')
-rw-r--r-- | Source/cmFindLibraryCommand.cxx | 339 |
1 files changed, 214 insertions, 125 deletions
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 2fa2cca..4af7e11 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -15,8 +15,9 @@ #include <cmsys/stl/algorithm> cmFindLibraryCommand::cmFindLibraryCommand() -{ +{ this->EnvironmentPath = "LIB"; + this->NamesPerDirAllowed = true; } //---------------------------------------------------------------------------- @@ -44,6 +45,9 @@ void cmFindLibraryCommand::GenerateDocumentation() "SEARCH_XXX", "library"); cmSystemTools::ReplaceString(this->GenericDocumentation, "XXX_SUBDIR", "lib"); + cmSystemTools::ReplaceString(this->GenericDocumentation, + "NAMES name1 [name2 ...]", + "NAMES name1 [name2 ...] [NAMES_PER_DIR]"); cmSystemTools::ReplaceString( this->GenericDocumentation, "XXX_EXTRA_PREFIX_ENTRY", @@ -53,11 +57,23 @@ void cmFindLibraryCommand::GenerateDocumentation() "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY"); this->GenericDocumentation += "\n" + "When more than one value is given to the NAMES option this command " + "by default will consider one name at a time and search every directory " + "for it. " + "The NAMES_PER_DIR option tells this command to consider one directory " + "at a time and search for all names in it." + "\n" "If the library found is a framework, then VAR will be set to " "the full path to the framework <fullPath>/A.framework. " "When a full path to a framework is used as a library, " "CMake will use a -framework A, and a -F<fullPath> to " - "link the framework to the target. "; + "link the framework to the target." + "\n" + "If the global property FIND_LIBRARY_USE_LIB64_PATHS is set all search " + "paths will be tested as normal, with \"64/\" appended, and with all " + "matches of \"lib/\" replaced with \"lib64/\". This property is " + "automatically set for the platforms that are known to need it if at " + "least one of the languages supported by the PROJECT command is enabled."; } // cmFindLibraryCommand @@ -99,7 +115,10 @@ bool cmFindLibraryCommand ->GetPropertyAsBool("FIND_LIBRARY_USE_LIB64_PATHS")) { // add special 64 bit paths if this is a 64 bit compile. - this->AddLib64Paths(); + if(this->Makefile->PlatformIs64Bit()) + { + this->AddArchitecturePaths("64"); + } } std::string library = this->FindLibrary(); @@ -123,90 +142,55 @@ bool cmFindLibraryCommand //---------------------------------------------------------------------------- void cmFindLibraryCommand::AddArchitecturePaths(const char* suffix) { - std::vector<std::string> newPaths; - bool found = false; - std::string subpath = "lib"; - subpath += suffix; - subpath += "/"; - for(std::vector<std::string>::iterator i = this->SearchPaths.begin(); - i != this->SearchPaths.end(); ++i) + std::vector<std::string> original; + original.swap(this->SearchPaths); + for(std::vector<std::string>::iterator i = original.begin(); + i != original.end(); ++i) { - // Try replacing lib/ with lib<suffix>/ - std::string s = *i; - cmSystemTools::ReplaceString(s, "lib/", subpath.c_str()); - if((s != *i) && cmSystemTools::FileIsDirectory(s.c_str())) - { - found = true; - newPaths.push_back(s); - } + this->AddArchitecturePath(*i, 0, suffix); + } +} + +//---------------------------------------------------------------------------- +void cmFindLibraryCommand::AddArchitecturePath( + std::string const& dir, std::string::size_type start_pos, + const char* suffix, bool fresh) +{ + std::string::size_type pos = dir.find("lib/", start_pos); + if(pos != std::string::npos) + { + std::string cur_dir = dir.substr(0,pos+3); - // Now look for lib<suffix> - s = *i; - s += suffix; - if(cmSystemTools::FileIsDirectory(s.c_str())) + // Follow "lib<suffix>". + std::string next_dir = cur_dir + suffix; + if(cmSystemTools::FileIsDirectory(next_dir.c_str())) { - found = true; - newPaths.push_back(s); + next_dir += dir.substr(pos+3); + std::string::size_type next_pos = pos+3+strlen(suffix)+1; + this->AddArchitecturePath(next_dir, next_pos, suffix); } - // now add the original unchanged path - if(cmSystemTools::FileIsDirectory(i->c_str())) + + // Follow "lib". + if(cmSystemTools::FileIsDirectory(cur_dir.c_str())) { - newPaths.push_back(*i); + this->AddArchitecturePath(dir, pos+3+1, suffix, false); } } - - // If any new paths were found replace the original set. - if(found) - { - this->SearchPaths = newPaths; - } -} - -void cmFindLibraryCommand::AddLib64Paths() -{ - std::string voidsize = - this->Makefile->GetSafeDefinition("CMAKE_SIZEOF_VOID_P"); - int size = atoi(voidsize.c_str()); - if(size != 8) - { - return; - } - std::vector<std::string> path64; - bool found64 = false; - for(std::vector<std::string>::iterator i = this->SearchPaths.begin(); - i != this->SearchPaths.end(); ++i) + if(fresh) { - std::string s = *i; - std::string s2 = *i; - cmSystemTools::ReplaceString(s, "lib/", "lib64/"); - // try to replace lib with lib64 and see if it is there, - // then prepend it to the path - // Note that all paths have trailing slashes. - if((s != *i) && cmSystemTools::FileIsDirectory(s.c_str())) - { - path64.push_back(s); - found64 = true; - } - // now just add a 64 to the path name and if it is there, - // add it to the path - s2 += "64/"; - if(cmSystemTools::FileIsDirectory(s2.c_str())) + // Check for <dir><suffix>/. + std::string cur_dir = dir + suffix + "/"; + if(cmSystemTools::FileIsDirectory(cur_dir.c_str())) { - found64 = true; - path64.push_back(s2); - } - // now add the original unchanged path - if(cmSystemTools::FileIsDirectory(i->c_str())) + this->SearchPaths.push_back(cur_dir); + } + + // Now add the original unchanged path + if(cmSystemTools::FileIsDirectory(dir.c_str())) { - path64.push_back(*i); + this->SearchPaths.push_back(dir); } } - // now replace the SearchPaths with the 64 bit converted path - // if any 64 bit paths were discovered - if(found64) - { - this->SearchPaths = path64; - } } //---------------------------------------------------------------------------- @@ -246,18 +230,19 @@ struct cmFindLibraryHelper // Keep track of the best library file found so far. typedef std::vector<std::string>::size_type size_type; std::string BestPath; - size_type BestPrefix; - size_type BestSuffix; // Support for OpenBSD shared library naming: lib<name>.so.<major>.<minor> bool OpenBSD; - unsigned int BestMajor; - unsigned int BestMinor; - // Current name under consideration. - cmsys::RegularExpression NameRegex; - bool TryRawName; - std::string RawName; + // Current names under consideration. + struct Name + { + bool TryRaw; + std::string Raw; + cmsys::RegularExpression Regex; + Name(): TryRaw(false) {} + }; + std::vector<Name> Names; // Current full path under consideration. std::string TestPath; @@ -275,8 +260,9 @@ struct cmFindLibraryHelper suffix) - this->Suffixes.begin(); } bool HasValidSuffix(std::string const& name); - void SetName(std::string const& name); + void AddName(std::string const& name); bool CheckDirectory(std::string const& path); + bool CheckDirectoryForName(std::string const& path, Name& name); }; //---------------------------------------------------------------------------- @@ -299,14 +285,6 @@ cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf): this->OpenBSD = this->Makefile->GetCMakeInstance() ->GetPropertyAsBool("FIND_LIBRARY_USE_OPENBSD_VERSIONING"); - - this->TryRawName = false; - - // No library file has yet been found. - this->BestPrefix = this->Prefixes.size(); - this->BestSuffix = this->Suffixes.size(); - this->BestMajor = 0; - this->BestMinor = 0; } //---------------------------------------------------------------------------- @@ -354,13 +332,23 @@ void cmFindLibraryHelper::RegexFromList(std::string& out, //---------------------------------------------------------------------------- bool cmFindLibraryHelper::HasValidSuffix(std::string const& name) { - // Check if the given name ends in a valid library suffix. for(std::vector<std::string>::const_iterator si = this->Suffixes.begin(); si != this->Suffixes.end(); ++si) { - std::string const& suffix = *si; - if(name.length() > suffix.length() && - name.substr(name.size()-suffix.length()) == suffix) + std::string suffix = *si; + if(name.length() <= suffix.length()) + { + continue; + } + // Check if the given name ends in a valid library suffix. + if(name.substr(name.size()-suffix.length()) == suffix) + { + return true; + } + // Check if a valid library suffix is somewhere in the name, + // this may happen e.g. for versioned shared libraries: libfoo.so.2 + suffix += "."; + if(name.find(suffix) != name.npos) { return true; } @@ -369,11 +357,13 @@ bool cmFindLibraryHelper::HasValidSuffix(std::string const& name) } //---------------------------------------------------------------------------- -void cmFindLibraryHelper::SetName(std::string const& name) +void cmFindLibraryHelper::AddName(std::string const& name) { + Name entry; + // Consider checking the raw name too. - this->TryRawName = this->HasValidSuffix(name); - this->RawName = name; + entry.TryRaw = this->HasValidSuffix(name); + entry.Raw = name; // Build a regular expression to match library names. std::string regex = "^"; @@ -385,21 +375,37 @@ void cmFindLibraryHelper::SetName(std::string const& name) regex += "(\\.[0-9]+\\.[0-9]+)?"; } regex += "$"; - this->NameRegex.compile(regex.c_str()); + entry.Regex.compile(regex.c_str()); + this->Names.push_back(entry); } //---------------------------------------------------------------------------- bool cmFindLibraryHelper::CheckDirectory(std::string const& path) { + for(std::vector<Name>::iterator i = this->Names.begin(); + i != this->Names.end(); ++i) + { + if(this->CheckDirectoryForName(path, *i)) + { + return true; + } + } + return false; +} + +//---------------------------------------------------------------------------- +bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path, + Name& name) +{ // If the original library name provided by the user matches one of // the suffixes, try it first. This allows users to search // specifically for a static library on some platforms (on MS tools // one cannot tell just from the library name whether it is a static // library or an import library). - if(this->TryRawName) + if(name.TryRaw) { this->TestPath = path; - this->TestPath += this->RawName; + this->TestPath += name.Raw; if(cmSystemTools::FileExists(this->TestPath.c_str(), true)) { this->BestPath = @@ -409,6 +415,12 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path) } } + // No library file has yet been found. + size_type bestPrefix = this->Prefixes.size(); + size_type bestSuffix = this->Suffixes.size(); + unsigned int bestMajor = 0; + unsigned int bestMinor = 0; + // Search for a file matching the library name regex. std::string dir = path; cmSystemTools::ConvertToUnixSlashes(dir); @@ -422,7 +434,7 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path) #else std::string const& testName = origName; #endif - if(this->NameRegex.find(testName)) + if(name.Regex.find(testName)) { this->TestPath = path; this->TestPath += origName; @@ -432,25 +444,25 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path) // best name found so far. Earlier prefixes are preferred, // followed by earlier suffixes. For OpenBSD, shared library // version extensions are compared. - size_type prefix = this->GetPrefixIndex(this->NameRegex.match(1)); - size_type suffix = this->GetSuffixIndex(this->NameRegex.match(2)); + size_type prefix = this->GetPrefixIndex(name.Regex.match(1)); + size_type suffix = this->GetSuffixIndex(name.Regex.match(2)); unsigned int major = 0; unsigned int minor = 0; if(this->OpenBSD) { - sscanf(this->NameRegex.match(3).c_str(), ".%u.%u", &major, &minor); + sscanf(name.Regex.match(3).c_str(), ".%u.%u", &major, &minor); } - if(this->BestPath.empty() || prefix < this->BestPrefix || - (prefix == this->BestPrefix && suffix < this->BestSuffix) || - (prefix == this->BestPrefix && suffix == this->BestSuffix && - (major > this->BestMajor || - (major == this->BestMajor && minor > this->BestMinor)))) + if(this->BestPath.empty() || prefix < bestPrefix || + (prefix == bestPrefix && suffix < bestSuffix) || + (prefix == bestPrefix && suffix == bestSuffix && + (major > bestMajor || + (major == bestMajor && minor > bestMinor)))) { this->BestPath = this->TestPath; - this->BestPrefix = prefix; - this->BestSuffix = suffix; - this->BestMajor = major; - this->BestMinor = minor; + bestPrefix = prefix; + bestSuffix = suffix; + bestMajor = major; + bestMinor = minor; } } } @@ -463,6 +475,42 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path) //---------------------------------------------------------------------------- std::string cmFindLibraryCommand::FindNormalLibrary() { + if(this->NamesPerDir) + { + return this->FindNormalLibraryNamesPerDir(); + } + else + { + return this->FindNormalLibraryDirsPerName(); + } +} + +//---------------------------------------------------------------------------- +std::string cmFindLibraryCommand::FindNormalLibraryNamesPerDir() +{ + // Search for all names in each directory. + cmFindLibraryHelper helper(this->Makefile); + for(std::vector<std::string>::const_iterator ni = this->Names.begin(); + ni != this->Names.end() ; ++ni) + { + helper.AddName(*ni); + } + // Search every directory. + for(std::vector<std::string>::const_iterator + p = this->SearchPaths.begin(); p != this->SearchPaths.end(); ++p) + { + if(helper.CheckDirectory(*p)) + { + return helper.BestPath; + } + } + // Couldn't find the library. + return ""; +} + +//---------------------------------------------------------------------------- +std::string cmFindLibraryCommand::FindNormalLibraryDirsPerName() +{ // Search the entire path for each name. cmFindLibraryHelper helper(this->Makefile); for(std::vector<std::string>::const_iterator ni = this->Names.begin(); @@ -470,7 +518,7 @@ std::string cmFindLibraryCommand::FindNormalLibrary() { // Switch to searching for this name. std::string const& name = *ni; - helper.SetName(name); + helper.AddName(name); // Search every directory. for(std::vector<std::string>::const_iterator @@ -490,19 +538,60 @@ std::string cmFindLibraryCommand::FindNormalLibrary() //---------------------------------------------------------------------------- std::string cmFindLibraryCommand::FindFrameworkLibrary() { - // Search for a framework of each name in the entire search path. + if(this->NamesPerDir) + { + return this->FindFrameworkLibraryNamesPerDir(); + } + else + { + return this->FindFrameworkLibraryDirsPerName(); + } +} + +//---------------------------------------------------------------------------- +std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir() +{ + std::string fwPath; + // Search for all names in each search path. + for(std::vector<std::string>::const_iterator di = this->SearchPaths.begin(); + di != this->SearchPaths.end(); ++di) + { + for(std::vector<std::string>::const_iterator ni = this->Names.begin(); + ni != this->Names.end() ; ++ni) + { + fwPath = *di; + fwPath += *ni; + fwPath += ".framework"; + if(cmSystemTools::FileIsDirectory(fwPath.c_str())) + { + return cmSystemTools::CollapseFullPath(fwPath.c_str()); + } + } + } + + // No framework found. + return ""; +} + +//---------------------------------------------------------------------------- +std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName() +{ + std::string fwPath; + // Search for each name in all search paths. for(std::vector<std::string>::const_iterator ni = this->Names.begin(); ni != this->Names.end() ; ++ni) { - // Search the paths for a framework with this name. - std::string fwName = *ni; - fwName += ".framework"; - std::string fwPath = cmSystemTools::FindDirectory(fwName.c_str(), - this->SearchPaths, - true); - if(!fwPath.empty()) + for(std::vector<std::string>::const_iterator + di = this->SearchPaths.begin(); + di != this->SearchPaths.end(); ++di) { - return fwPath; + fwPath = *di; + fwPath += *ni; + fwPath += ".framework"; + if(cmSystemTools::FileIsDirectory(fwPath.c_str())) + { + return cmSystemTools::CollapseFullPath(fwPath.c_str()); + } } } |