diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index c5a60383f8..15f2d9d6b6 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -3,11 +3,14 @@ #include "cmFindLibraryCommand.h" #include +#include #include #include #include #include +#include + #include "cmsys/RegularExpression.hxx" #include "cmGlobalGenerator.h" @@ -200,7 +203,9 @@ struct cmFindLibraryHelper cmList Prefixes; cmList Suffixes; std::string PrefixRegexStr; + std::string ICasePrefixRegexStr; // case insensitive std::string SuffixRegexStr; + std::string ICaseSuffixRegexStr; // case insensitive // Keep track of the best library file found so far. using size_type = std::vector::size_type; @@ -217,11 +222,14 @@ struct cmFindLibraryHelper bool TryRaw = false; std::string Raw; cmsys::RegularExpression Regex; + cmsys::RegularExpression ICaseRegex; // case insensitive }; std::vector Names; - void RegexFromLiteral(std::string& out, std::string const& in); - void RegexFromList(std::string& out, cmList const& in); + void RegexFromLiteral(std::string& out, std::string const& in, + cmSystemTools::DirCase dirCase); + void RegexFromList(std::string& out, cmList const& in, + cmSystemTools::DirCase dirCase); size_type GetPrefixIndex(std::string const& prefix) { return std::find(this->Prefixes.begin(), this->Prefixes.end(), prefix) - @@ -313,8 +321,14 @@ cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf, this->Prefixes.assign(prefixes_list, cmList::EmptyElements::Yes); this->Suffixes.assign(suffixes_list, cmList::EmptyElements::Yes); - this->RegexFromList(this->PrefixRegexStr, this->Prefixes); - this->RegexFromList(this->SuffixRegexStr, this->Suffixes); + this->RegexFromList(this->PrefixRegexStr, this->Prefixes, + cmSystemTools::DirCase::Sensitive); + this->RegexFromList(this->ICasePrefixRegexStr, this->Prefixes, + cmSystemTools::DirCase::Insensitive); + this->RegexFromList(this->SuffixRegexStr, this->Suffixes, + cmSystemTools::DirCase::Sensitive); + this->RegexFromList(this->ICaseSuffixRegexStr, this->Suffixes, + cmSystemTools::DirCase::Insensitive); // Check whether to use OpenBSD-style library version comparisons. this->IsOpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool( @@ -322,7 +336,8 @@ cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf, } void cmFindLibraryHelper::RegexFromLiteral(std::string& out, - std::string const& in) + std::string const& in, + cmSystemTools::DirCase dirCase) { for (char ch : in) { if (ch == '[' || ch == ']' || ch == '(' || ch == ')' || ch == '\\' || @@ -330,15 +345,16 @@ void cmFindLibraryHelper::RegexFromLiteral(std::string& out, ch == '^' || ch == '$') { out += "\\"; } -#if defined(_WIN32) || defined(__APPLE__) - out += static_cast(tolower(ch)); -#else - out += ch; -#endif + if (dirCase == cmSystemTools::DirCase::Insensitive) { + out += static_cast(tolower(ch)); + } else { + out += ch; + } } } -void cmFindLibraryHelper::RegexFromList(std::string& out, cmList const& in) +void cmFindLibraryHelper::RegexFromList(std::string& out, cmList const& in, + cmSystemTools::DirCase dirCase) { // Surround the list in parens so the '|' does not apply to anything // else and the result can be checked after matching. @@ -350,7 +366,7 @@ void cmFindLibraryHelper::RegexFromList(std::string& out, cmList const& in) sep = "|"; // Append this item. - this->RegexFromLiteral(out, s); + this->RegexFromLiteral(out, s, dirCase); } out += ")"; } @@ -384,14 +400,29 @@ void cmFindLibraryHelper::AddName(std::string const& name) entry.Raw = name; // Build a regular expression to match library names. - std::string regex = cmStrCat('^', this->PrefixRegexStr); - this->RegexFromLiteral(regex, name); - regex += this->SuffixRegexStr; - if (this->IsOpenBSD) { - regex += "(\\.[0-9]+\\.[0-9]+)?"; + { + std::string regex = cmStrCat('^', this->PrefixRegexStr); + this->RegexFromLiteral(regex, name, cmSystemTools::DirCase::Sensitive); + regex += this->SuffixRegexStr; + if (this->IsOpenBSD) { + regex += "(\\.[0-9]+\\.[0-9]+)?"; + } + regex += "$"; + entry.Regex.compile(regex); } - regex += "$"; - entry.Regex.compile(regex); + + // case insensitive version + { + std::string regex = cmStrCat('^', this->ICasePrefixRegexStr); + this->RegexFromLiteral(regex, name, cmSystemTools::DirCase::Insensitive); + regex += this->ICaseSuffixRegexStr; + if (this->IsOpenBSD) { + regex += "(\\.[0-9]+\\.[0-9]+)?"; + } + regex += "$"; + entry.ICaseRegex.compile(regex); + } + this->Names.push_back(std::move(entry)); } @@ -440,14 +471,19 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path, unsigned int bestMinor = 0; // Search for a file matching the library name regex. + cm::optional dirCase = + cmSystemTools::GetDirCase(path).value_or( + cmSystemTools::DirCase::Sensitive); + cmsys::RegularExpression& regex = + dirCase == cmSystemTools::DirCase::Insensitive ? name.ICaseRegex + : name.Regex; std::set const& files = this->GG->GetDirectoryContent(path); for (std::string const& origName : files) { -#if defined(_WIN32) || defined(__APPLE__) - std::string testName = cmSystemTools::LowerCase(origName); -#else - std::string const& testName = origName; -#endif - if (name.Regex.find(testName)) { + std::string testName = dirCase == cmSystemTools::DirCase::Insensitive + ? cmSystemTools::LowerCase(origName) + : origName; + + if (regex.find(testName)) { std::string testPath = cmStrCat(path, origName); // Make sure the path is readable and is not a directory. if (cmSystemTools::FileExists(testPath, true)) { @@ -461,12 +497,12 @@ bool cmFindLibraryHelper::CheckDirectoryForName(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(name.Regex.match(1)); - size_type suffix = this->GetSuffixIndex(name.Regex.match(2)); + size_type prefix = this->GetPrefixIndex(regex.match(1)); + size_type suffix = this->GetSuffixIndex(regex.match(2)); unsigned int major = 0; unsigned int minor = 0; if (this->IsOpenBSD) { - sscanf(name.Regex.match(3).c_str(), ".%u.%u", &major, &minor); + sscanf(regex.match(3).c_str(), ".%u.%u", &major, &minor); } if (this->BestPath.empty() || prefix < bestPrefix || (prefix == bestPrefix && suffix < bestSuffix) ||