mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-19 19:43:23 +08:00
cmake: Look up on-disk case of input paths on macOS
Follow up commit 1a6015e5fc
(PathResolver: Add helper to compute
normalized paths, 2024-10-30) to cover on-disk case lookup on macOS.
Fixes: #26333
This commit is contained in:
@@ -396,7 +396,7 @@ Control Impl<Policy>::ResolveComponent(Root root,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
bool exists = false;
|
bool exists = false;
|
||||||
if (Policy::ActualCase == Options::ActualCase::Yes) {
|
if (Policy::ActualCase == Options::ActualCase::Yes) {
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -418,7 +418,7 @@ Control Impl<Policy>::ResolveComponent(Root root,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Policy::Existence == Options::Existence::Required
|
if (Policy::Existence == Options::Existence::Required
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
&& !exists
|
&& !exists
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
@@ -486,7 +486,7 @@ cmsys::Status Impl<Policy>::Resolve(std::string in, std::string& out)
|
|||||||
namespace Policies {
|
namespace Policies {
|
||||||
struct NaivePath
|
struct NaivePath
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
static constexpr Options::ActualCase ActualCase = Options::ActualCase::No;
|
static constexpr Options::ActualCase ActualCase = Options::ActualCase::No;
|
||||||
#endif
|
#endif
|
||||||
static constexpr Options::Symlinks Symlinks = Options::Symlinks::None;
|
static constexpr Options::Symlinks Symlinks = Options::Symlinks::None;
|
||||||
@@ -494,7 +494,7 @@ struct NaivePath
|
|||||||
};
|
};
|
||||||
struct RealPath
|
struct RealPath
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
static constexpr Options::ActualCase ActualCase = Options::ActualCase::Yes;
|
static constexpr Options::ActualCase ActualCase = Options::ActualCase::Yes;
|
||||||
#endif
|
#endif
|
||||||
static constexpr Options::Symlinks Symlinks = Options::Symlinks::Eager;
|
static constexpr Options::Symlinks Symlinks = Options::Symlinks::Eager;
|
||||||
@@ -502,7 +502,7 @@ struct RealPath
|
|||||||
};
|
};
|
||||||
struct LogicalPath
|
struct LogicalPath
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
static constexpr Options::ActualCase ActualCase = Options::ActualCase::Yes;
|
static constexpr Options::ActualCase ActualCase = Options::ActualCase::Yes;
|
||||||
#endif
|
#endif
|
||||||
static constexpr Options::Symlinks Symlinks = Options::Symlinks::Lazy;
|
static constexpr Options::Symlinks Symlinks = Options::Symlinks::Lazy;
|
||||||
|
@@ -64,7 +64,9 @@ public:
|
|||||||
/** Get the process's working directory on a Windows drive letter.
|
/** Get the process's working directory on a Windows drive letter.
|
||||||
This is a legacy DOS concept supported by 'cmd' shells. */
|
This is a legacy DOS concept supported by 'cmd' shells. */
|
||||||
virtual std::string GetWorkingDirectoryOnDrive(char drive_letter) = 0;
|
virtual std::string GetWorkingDirectoryOnDrive(char drive_letter) = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
/** Read the on-disk spelling of the last component of a file path. */
|
/** Read the on-disk spelling of the last component of a file path. */
|
||||||
virtual cmsys::Status ReadName(std::string const& path,
|
virtual cmsys::Status ReadName(std::string const& path,
|
||||||
std::string& name) = 0;
|
std::string& name) = 0;
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
# include <unordered_map>
|
# include <unordered_map>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -191,6 +191,61 @@ cmsys::Status ReadNameOnDisk(std::string const& path, std::string& name)
|
|||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
return cmsys::Status::Success();
|
return cmsys::Status::Success();
|
||||||
}
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
cmsys::Status ReadNameOnDiskIterateDir(std::string const& path,
|
||||||
|
std::string& name)
|
||||||
|
{
|
||||||
|
// Read contents of the parent directory to find the
|
||||||
|
// entry matching the given path.
|
||||||
|
std::string const bn = cmSystemTools::GetFilenameName(path);
|
||||||
|
std::string const dn = cmSystemTools::GetFilenamePath(path);
|
||||||
|
DIR* d = opendir(dn.c_str());
|
||||||
|
while (struct dirent* dr = readdir(d)) {
|
||||||
|
if (strcasecmp(dr->d_name, bn.c_str()) == 0) {
|
||||||
|
name = dr->d_name;
|
||||||
|
closedir(d);
|
||||||
|
return cmsys::Status::Success();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(d);
|
||||||
|
return cmsys::Status::POSIX(ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsys::Status ReadNameOnDiskFcntlGetPath(std::string const& path,
|
||||||
|
std::string& name)
|
||||||
|
{
|
||||||
|
// macOS (and *BSD) offer a syscall to get an on-disk path to
|
||||||
|
// a descriptor's file.
|
||||||
|
int fd = open(path.c_str(), O_SYMLINK | O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
return cmsys::Status::POSIX(errno);
|
||||||
|
}
|
||||||
|
char out[MAXPATHLEN + 1];
|
||||||
|
if (fcntl(fd, F_GETPATH, out) == -1) {
|
||||||
|
int e = errno;
|
||||||
|
close(fd);
|
||||||
|
return cmsys::Status::POSIX(e);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
name = cmSystemTools::GetFilenameName(out);
|
||||||
|
return cmsys::Status::Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsys::Status ReadNameOnDisk(std::string const& path, std::string& name)
|
||||||
|
{
|
||||||
|
struct stat stat_path;
|
||||||
|
if (lstat(path.c_str(), &stat_path) != 0) {
|
||||||
|
return cmsys::Status::POSIX(errno);
|
||||||
|
}
|
||||||
|
// macOS (and *BSD) use namei(9) to cache file paths. Use it unless
|
||||||
|
// the inode has multiple hardlinks: if it is opened through multiple
|
||||||
|
// paths, the results may be unpredictable.
|
||||||
|
if (S_ISDIR(stat_path.st_mode) || stat_path.st_nlink < 2) {
|
||||||
|
return ReadNameOnDiskFcntlGetPath(path, name);
|
||||||
|
}
|
||||||
|
// Fall back to reading the parent directory.
|
||||||
|
return ReadNameOnDiskIterateDir(path, name);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class RealSystem : public cm::PathResolver::System
|
class RealSystem : public cm::PathResolver::System
|
||||||
@@ -215,7 +270,9 @@ public:
|
|||||||
{
|
{
|
||||||
return GetDosDriveWorkingDirectory(letter);
|
return GetDosDriveWorkingDirectory(letter);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
struct NameOnDisk
|
struct NameOnDisk
|
||||||
{
|
{
|
||||||
cmsys::Status Status;
|
cmsys::Status Status;
|
||||||
|
@@ -8,13 +8,15 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <cctype>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <cmsys/Status.hxx>
|
#include <cmsys/Status.hxx>
|
||||||
|
|
||||||
#include "cmPathResolver.h"
|
#include "cmPathResolver.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
# include <cctype>
|
|
||||||
|
|
||||||
# include "cmSystemTools.h"
|
# include "cmSystemTools.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -46,7 +48,7 @@ public:
|
|||||||
|
|
||||||
static std::string AdjustCase(std::string const& path)
|
static std::string AdjustCase(std::string const& path)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
return cmSystemTools::LowerCase(path);
|
return cmSystemTools::LowerCase(path);
|
||||||
#else
|
#else
|
||||||
return path;
|
return path;
|
||||||
@@ -95,7 +97,9 @@ public:
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
cmsys::Status ReadName(std::string const& path, std::string& name) override
|
cmsys::Status ReadName(std::string const& path, std::string& name) override
|
||||||
{
|
{
|
||||||
auto i = this->Paths.find(AdjustCase(path));
|
auto i = this->Paths.find(AdjustCase(path));
|
||||||
@@ -242,6 +246,47 @@ bool posixSymlink()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
bool macosActualCase()
|
||||||
|
{
|
||||||
|
std::cout << "macosActualCase()\n";
|
||||||
|
MockSystem os;
|
||||||
|
os.SetPaths({
|
||||||
|
{ "/", { {}, {} } },
|
||||||
|
{ "/mixed", { "MiXeD", {} } },
|
||||||
|
{ "/mixed/link-mixed", { "LiNk-MiXeD", "mixed" } },
|
||||||
|
{ "/mixed/mixed", { "MiXeD", {} } },
|
||||||
|
{ "/mixed/link-c-mixed", { "LiNk-C-MiXeD", "/mIxEd" } },
|
||||||
|
{ "/upper", { "UPPER", {} } },
|
||||||
|
{ "/upper/link-upper", { "LINK-UPPER", "upper" } },
|
||||||
|
{ "/upper/upper", { "UPPER", {} } },
|
||||||
|
{ "/upper/link-c-upper", { "LINK-C-UPPER", "/upper" } },
|
||||||
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
Resolver<Policies::LogicalPath> const r(os);
|
||||||
|
EXPECT_RESOLVE("/mIxEd/MiSsInG", "/MiXeD/MiSsInG");
|
||||||
|
EXPECT_RESOLVE("/mIxEd/link-MiXeD", "/MiXeD/LiNk-MiXeD");
|
||||||
|
EXPECT_RESOLVE("/mIxEd/link-c-MiXeD", "/MiXeD/LiNk-C-MiXeD");
|
||||||
|
EXPECT_RESOLVE("/upper/mIsSiNg", "/UPPER/mIsSiNg");
|
||||||
|
EXPECT_RESOLVE("/upper/link-upper", "/UPPER/LINK-UPPER");
|
||||||
|
EXPECT_RESOLVE("/upper/link-c-upper", "/UPPER/LINK-C-UPPER");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Resolver<Policies::RealPath> const r(os);
|
||||||
|
EXPECT_ENOENT("/mIxEd/MiSsInG", "/MiXeD/MiSsInG");
|
||||||
|
EXPECT_RESOLVE("/mIxEd/link-MiXeD", "/MiXeD/MiXeD");
|
||||||
|
EXPECT_RESOLVE("/mIxEd/link-c-MiXeD", "/MiXeD");
|
||||||
|
EXPECT_ENOENT("/upper/mIsSiNg", "/UPPER/mIsSiNg");
|
||||||
|
EXPECT_RESOLVE("/upper/link-upper", "/UPPER/UPPER");
|
||||||
|
EXPECT_RESOLVE("/upper/link-c-upper", "/UPPER");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
bool windowsRoot()
|
bool windowsRoot()
|
||||||
{
|
{
|
||||||
@@ -464,6 +509,9 @@ int testPathResolver(int /*unused*/, char* /*unused*/[])
|
|||||||
posixAbsolutePath,
|
posixAbsolutePath,
|
||||||
posixWorkingDirectory,
|
posixWorkingDirectory,
|
||||||
posixSymlink,
|
posixSymlink,
|
||||||
|
#ifdef __APPLE__
|
||||||
|
macosActualCase,
|
||||||
|
#endif
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
windowsRoot,
|
windowsRoot,
|
||||||
windowsAbsolutePath,
|
windowsAbsolutePath,
|
||||||
|
Reference in New Issue
Block a user