mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-01 03:29:18 -05:00
find_library: Handle case-insensitive filesystems on Linux
Linux 5.2+ supports case-insensitive ext4 filesystems. Teach `find_library` pattern matching to account for this. Fixes: #26526
This commit is contained in:
@@ -3,11 +3,14 @@
|
|||||||
#include "cmFindLibraryCommand.h"
|
#include "cmFindLibraryCommand.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <cm/optional>
|
||||||
|
|
||||||
#include "cmsys/RegularExpression.hxx"
|
#include "cmsys/RegularExpression.hxx"
|
||||||
|
|
||||||
#include "cmGlobalGenerator.h"
|
#include "cmGlobalGenerator.h"
|
||||||
@@ -200,7 +203,9 @@ struct cmFindLibraryHelper
|
|||||||
cmList Prefixes;
|
cmList Prefixes;
|
||||||
cmList Suffixes;
|
cmList Suffixes;
|
||||||
std::string PrefixRegexStr;
|
std::string PrefixRegexStr;
|
||||||
|
std::string ICasePrefixRegexStr; // case insensitive
|
||||||
std::string SuffixRegexStr;
|
std::string SuffixRegexStr;
|
||||||
|
std::string ICaseSuffixRegexStr; // case insensitive
|
||||||
|
|
||||||
// Keep track of the best library file found so far.
|
// Keep track of the best library file found so far.
|
||||||
using size_type = std::vector<std::string>::size_type;
|
using size_type = std::vector<std::string>::size_type;
|
||||||
@@ -217,11 +222,14 @@ struct cmFindLibraryHelper
|
|||||||
bool TryRaw = false;
|
bool TryRaw = false;
|
||||||
std::string Raw;
|
std::string Raw;
|
||||||
cmsys::RegularExpression Regex;
|
cmsys::RegularExpression Regex;
|
||||||
|
cmsys::RegularExpression ICaseRegex; // case insensitive
|
||||||
};
|
};
|
||||||
std::vector<Name> Names;
|
std::vector<Name> Names;
|
||||||
|
|
||||||
void RegexFromLiteral(std::string& out, std::string const& in);
|
void RegexFromLiteral(std::string& out, std::string const& in,
|
||||||
void RegexFromList(std::string& out, cmList const& in);
|
cmSystemTools::DirCase dirCase);
|
||||||
|
void RegexFromList(std::string& out, cmList const& in,
|
||||||
|
cmSystemTools::DirCase dirCase);
|
||||||
size_type GetPrefixIndex(std::string const& prefix)
|
size_type GetPrefixIndex(std::string const& prefix)
|
||||||
{
|
{
|
||||||
return std::find(this->Prefixes.begin(), this->Prefixes.end(), 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->Prefixes.assign(prefixes_list, cmList::EmptyElements::Yes);
|
||||||
this->Suffixes.assign(suffixes_list, cmList::EmptyElements::Yes);
|
this->Suffixes.assign(suffixes_list, cmList::EmptyElements::Yes);
|
||||||
this->RegexFromList(this->PrefixRegexStr, this->Prefixes);
|
this->RegexFromList(this->PrefixRegexStr, this->Prefixes,
|
||||||
this->RegexFromList(this->SuffixRegexStr, this->Suffixes);
|
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.
|
// Check whether to use OpenBSD-style library version comparisons.
|
||||||
this->IsOpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool(
|
this->IsOpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool(
|
||||||
@@ -322,7 +336,8 @@ cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cmFindLibraryHelper::RegexFromLiteral(std::string& out,
|
void cmFindLibraryHelper::RegexFromLiteral(std::string& out,
|
||||||
std::string const& in)
|
std::string const& in,
|
||||||
|
cmSystemTools::DirCase dirCase)
|
||||||
{
|
{
|
||||||
for (char ch : in) {
|
for (char ch : in) {
|
||||||
if (ch == '[' || ch == ']' || ch == '(' || ch == ')' || ch == '\\' ||
|
if (ch == '[' || ch == ']' || ch == '(' || ch == ')' || ch == '\\' ||
|
||||||
@@ -330,15 +345,16 @@ void cmFindLibraryHelper::RegexFromLiteral(std::string& out,
|
|||||||
ch == '^' || ch == '$') {
|
ch == '^' || ch == '$') {
|
||||||
out += "\\";
|
out += "\\";
|
||||||
}
|
}
|
||||||
#if defined(_WIN32) || defined(__APPLE__)
|
if (dirCase == cmSystemTools::DirCase::Insensitive) {
|
||||||
out += static_cast<char>(tolower(ch));
|
out += static_cast<char>(tolower(ch));
|
||||||
#else
|
} else {
|
||||||
out += ch;
|
out += ch;
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// Surround the list in parens so the '|' does not apply to anything
|
||||||
// else and the result can be checked after matching.
|
// else and the result can be checked after matching.
|
||||||
@@ -350,7 +366,7 @@ void cmFindLibraryHelper::RegexFromList(std::string& out, cmList const& in)
|
|||||||
sep = "|";
|
sep = "|";
|
||||||
|
|
||||||
// Append this item.
|
// Append this item.
|
||||||
this->RegexFromLiteral(out, s);
|
this->RegexFromLiteral(out, s, dirCase);
|
||||||
}
|
}
|
||||||
out += ")";
|
out += ")";
|
||||||
}
|
}
|
||||||
@@ -384,14 +400,29 @@ void cmFindLibraryHelper::AddName(std::string const& name)
|
|||||||
entry.Raw = name;
|
entry.Raw = name;
|
||||||
|
|
||||||
// Build a regular expression to match library names.
|
// Build a regular expression to match library names.
|
||||||
std::string regex = cmStrCat('^', this->PrefixRegexStr);
|
{
|
||||||
this->RegexFromLiteral(regex, name);
|
std::string regex = cmStrCat('^', this->PrefixRegexStr);
|
||||||
regex += this->SuffixRegexStr;
|
this->RegexFromLiteral(regex, name, cmSystemTools::DirCase::Sensitive);
|
||||||
if (this->IsOpenBSD) {
|
regex += this->SuffixRegexStr;
|
||||||
regex += "(\\.[0-9]+\\.[0-9]+)?";
|
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));
|
this->Names.push_back(std::move(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,14 +471,19 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
|
|||||||
unsigned int bestMinor = 0;
|
unsigned int bestMinor = 0;
|
||||||
|
|
||||||
// Search for a file matching the library name regex.
|
// Search for a file matching the library name regex.
|
||||||
|
cm::optional<cmSystemTools::DirCase> dirCase =
|
||||||
|
cmSystemTools::GetDirCase(path).value_or(
|
||||||
|
cmSystemTools::DirCase::Sensitive);
|
||||||
|
cmsys::RegularExpression& regex =
|
||||||
|
dirCase == cmSystemTools::DirCase::Insensitive ? name.ICaseRegex
|
||||||
|
: name.Regex;
|
||||||
std::set<std::string> const& files = this->GG->GetDirectoryContent(path);
|
std::set<std::string> const& files = this->GG->GetDirectoryContent(path);
|
||||||
for (std::string const& origName : files) {
|
for (std::string const& origName : files) {
|
||||||
#if defined(_WIN32) || defined(__APPLE__)
|
std::string testName = dirCase == cmSystemTools::DirCase::Insensitive
|
||||||
std::string testName = cmSystemTools::LowerCase(origName);
|
? cmSystemTools::LowerCase(origName)
|
||||||
#else
|
: origName;
|
||||||
std::string const& testName = origName;
|
|
||||||
#endif
|
if (regex.find(testName)) {
|
||||||
if (name.Regex.find(testName)) {
|
|
||||||
std::string testPath = cmStrCat(path, origName);
|
std::string testPath = cmStrCat(path, origName);
|
||||||
// Make sure the path is readable and is not a directory.
|
// Make sure the path is readable and is not a directory.
|
||||||
if (cmSystemTools::FileExists(testPath, true)) {
|
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,
|
// best name found so far. Earlier prefixes are preferred,
|
||||||
// followed by earlier suffixes. For OpenBSD, shared library
|
// followed by earlier suffixes. For OpenBSD, shared library
|
||||||
// version extensions are compared.
|
// version extensions are compared.
|
||||||
size_type prefix = this->GetPrefixIndex(name.Regex.match(1));
|
size_type prefix = this->GetPrefixIndex(regex.match(1));
|
||||||
size_type suffix = this->GetSuffixIndex(name.Regex.match(2));
|
size_type suffix = this->GetSuffixIndex(regex.match(2));
|
||||||
unsigned int major = 0;
|
unsigned int major = 0;
|
||||||
unsigned int minor = 0;
|
unsigned int minor = 0;
|
||||||
if (this->IsOpenBSD) {
|
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 ||
|
if (this->BestPath.empty() || prefix < bestPrefix ||
|
||||||
(prefix == bestPrefix && suffix < bestSuffix) ||
|
(prefix == bestPrefix && suffix < bestSuffix) ||
|
||||||
|
|||||||
Reference in New Issue
Block a user