cmake: Explicitly normalize input paths as they exist on disk

`CollapseFullPath` has two use cases:

1.  Normalize input paths from command-line arguments and environment
    variables.  On Windows, load their on-disk capitalization.

2.  Simplify paths constructed internally.  These should already have
    the correct capitalization.

Audit all `CollapseFullPath` call sites and code paths leading to them.
Replace those calls that normalize input paths with calls to
`ToNormalizedPathOnDisk` to express that they need the on-disk case.

By making this distinction we will later be able to remove the on-disk
capitalization lookup `CollapseFullPath`, thus eliminating disk accesses
from internal path processing.

Issue: #20214
This commit is contained in:
Brad King
2024-10-22 13:26:19 -04:00
parent 9d44a77454
commit ee83165923
7 changed files with 51 additions and 67 deletions
+1 -1
View File
@@ -2380,7 +2380,7 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName,
dep = cmStrCat(this->GetCurrentBinaryDirectory(), '/', inName);
}
dep = cmSystemTools::CollapseFullPath(dep, this->GetBinaryDirectory());
dep = cmSystemTools::CollapseFullPath(dep);
return true;
}
+1 -1
View File
@@ -2088,7 +2088,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, cmValue value,
cmList files(value);
for (auto& file : files) {
if (!cmIsOff(file)) {
file = cmSystemTools::CollapseFullPath(file);
file = cmSystemTools::ToNormalizedPathOnDisk(file);
}
}
nvalue = files.to_string();
+1 -1
View File
@@ -2778,7 +2778,7 @@ cm::optional<std::string> cmSystemTools::GetCMakeConfigDirectory()
std::string cmSystemTools::GetCurrentWorkingDirectory()
{
return cmSystemTools::CollapseFullPath(
return cmSystemTools::ToNormalizedPathOnDisk(
cmsys::SystemTools::GetCurrentWorkingDirectory());
}
+35 -45
View File
@@ -689,7 +689,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
cmSystemTools::Stdout("loading initial cache file " + value + "\n");
// Resolve script path specified on command line
// relative to $PWD.
auto path = cmSystemTools::CollapseFullPath(value);
auto path = cmSystemTools::ToNormalizedPathOnDisk(value);
state->ReadListFile(args, path);
return true;
} },
@@ -778,10 +778,7 @@ void cmake::ReadListFile(const std::vector<std::string>& args,
snapshot.SetDefaultDefinitions();
cmMakefile mf(gg, snapshot);
if (this->GetWorkingMode() != NORMAL_MODE) {
std::string file(cmSystemTools::CollapseFullPath(path));
cmSystemTools::ConvertToUnixSlashes(file);
mf.SetScriptModeFile(file);
mf.SetScriptModeFile(cmSystemTools::ToNormalizedPathOnDisk(path));
mf.SetArgcArgv(args);
}
if (!cmSystemTools::FileExists(path, true)) {
@@ -955,10 +952,8 @@ void cmake::SetArgs(const std::vector<std::string>& args)
cmSystemTools::Error("No source directory specified for -S");
return false;
}
std::string path = cmSystemTools::CollapseFullPath(value);
cmSystemTools::ConvertToUnixSlashes(path);
state->SetHomeDirectoryViaCommandLine(path);
state->SetHomeDirectoryViaCommandLine(
cmSystemTools::ToNormalizedPathOnDisk(value));
return true;
};
@@ -967,9 +962,8 @@ void cmake::SetArgs(const std::vector<std::string>& args)
cmSystemTools::Error("No build directory specified for -B");
return false;
}
std::string path = cmSystemTools::CollapseFullPath(value);
cmSystemTools::ConvertToUnixSlashes(path);
state->SetHomeOutputDirectory(path);
state->SetHomeOutputDirectory(
cmSystemTools::ToNormalizedPathOnDisk(value));
haveBArg = true;
return true;
};
@@ -1073,7 +1067,8 @@ void cmake::SetArgs(const std::vector<std::string>& args)
CommandArgument{ "--graphviz", "No file specified for --graphviz",
CommandArgument::Values::One,
[](std::string const& value, cmake* state) -> bool {
state->SetGraphVizFile(value);
state->SetGraphVizFile(
cmSystemTools::ToNormalizedPathOnDisk(value));
return true;
} },
@@ -1277,23 +1272,22 @@ void cmake::SetArgs(const std::vector<std::string>& args)
return false;
#endif
} },
CommandArgument{
"--debugger-dap-log", "No file specified for --debugger-dap-log",
CommandArgument::Values::One,
[](std::string const& value, cmake* state) -> bool {
CommandArgument{ "--debugger-dap-log",
"No file specified for --debugger-dap-log",
CommandArgument::Values::One,
[](std::string const& value, cmake* state) -> bool {
#ifdef CMake_ENABLE_DEBUGGER
std::string path = cmSystemTools::CollapseFullPath(value);
cmSystemTools::ConvertToUnixSlashes(path);
state->DebuggerDapLogFile = path;
return true;
state->DebuggerDapLogFile =
cmSystemTools::ToNormalizedPathOnDisk(value);
return true;
#else
static_cast<void>(value);
static_cast<void>(state);
cmSystemTools::Error(
"CMake was not built with support for --debugger-dap-log");
return false;
static_cast<void>(value);
static_cast<void>(state);
cmSystemTools::Error("CMake was not built with support "
"for --debugger-dap-log");
return false;
#endif
} },
} },
};
#if defined(CMAKE_HAVE_VS_GENERATORS)
@@ -1315,9 +1309,8 @@ void cmake::SetArgs(const std::vector<std::string>& args)
arguments.emplace_back(
"--profiling-output", "No path specified for --profiling-output",
CommandArgument::Values::One,
[&](std::string const& value, cmake*) -> bool {
profilingOutput = cmSystemTools::CollapseFullPath(value);
cmSystemTools::ConvertToUnixSlashes(profilingOutput);
[&profilingOutput](std::string const& value, cmake*) -> bool {
profilingOutput = cmSystemTools::ToNormalizedPathOnDisk(value);
return true;
});
arguments.emplace_back("--preset", "No preset specified for --preset",
@@ -1587,7 +1580,8 @@ void cmake::SetArgs(const std::vector<std::string>& args)
if (!expandedPreset->GraphVizFile.empty()) {
if (this->GraphVizFile.empty()) {
this->SetGraphVizFile(expandedPreset->GraphVizFile);
this->SetGraphVizFile(
cmSystemTools::CollapseFullPath(expandedPreset->GraphVizFile));
}
}
@@ -1778,8 +1772,7 @@ bool cmake::SetDirectoriesFromFile(const std::string& arg)
bool is_source_dir = false;
bool is_empty_directory = false;
if (cmSystemTools::FileIsDirectory(arg)) {
std::string path = cmSystemTools::CollapseFullPath(arg);
cmSystemTools::ConvertToUnixSlashes(path);
std::string path = cmSystemTools::ToNormalizedPathOnDisk(arg);
std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
std::string listFile = cmStrCat(path, "/CMakeLists.txt");
@@ -1794,7 +1787,7 @@ bool cmake::SetDirectoriesFromFile(const std::string& arg)
is_source_dir = true;
}
} else if (cmSystemTools::FileExists(arg)) {
std::string fullPath = cmSystemTools::CollapseFullPath(arg);
std::string fullPath = cmSystemTools::ToNormalizedPathOnDisk(arg);
std::string name = cmSystemTools::GetFilenameName(fullPath);
name = cmSystemTools::LowerCase(name);
if (name == "cmakecache.txt"_s) {
@@ -1845,14 +1838,13 @@ bool cmake::SetDirectoriesFromFile(const std::string& arg)
if (is_source_dir) {
this->SetHomeDirectoryViaCommandLine(listPath);
if (no_build_tree) {
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
this->SetHomeOutputDirectory(cwd);
this->SetHomeOutputDirectory(
cmSystemTools::GetCurrentWorkingDirectory());
}
} else if (no_source_tree && no_build_tree) {
this->SetHomeDirectory(listPath);
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
this->SetHomeOutputDirectory(cwd);
this->SetHomeOutputDirectory(
cmSystemTools::GetCurrentWorkingDirectory());
} else if (no_build_tree) {
this->SetHomeOutputDirectory(listPath);
}
@@ -1860,18 +1852,16 @@ bool cmake::SetDirectoriesFromFile(const std::string& arg)
if (no_source_tree) {
// We didn't find a CMakeLists.txt and it wasn't specified
// with -S. Assume it is the path to the source tree
std::string full = cmSystemTools::CollapseFullPath(arg);
this->SetHomeDirectory(full);
this->SetHomeDirectory(cmSystemTools::ToNormalizedPathOnDisk(arg));
}
if (no_build_tree && !no_source_tree && is_empty_directory) {
// passed `-S <path> <build_dir> when build_dir is an empty directory
std::string full = cmSystemTools::CollapseFullPath(arg);
this->SetHomeOutputDirectory(full);
this->SetHomeOutputDirectory(cmSystemTools::ToNormalizedPathOnDisk(arg));
} else if (no_build_tree) {
// We didn't find a CMakeCache.txt and it wasn't specified
// with -B. Assume the current working directory as the build tree.
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
this->SetHomeOutputDirectory(cwd);
this->SetHomeOutputDirectory(
cmSystemTools::GetCurrentWorkingDirectory());
used_provided_path = false;
}
}
+1 -7
View File
@@ -26,7 +26,6 @@
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#if !defined(CMAKE_BOOTSTRAP)
@@ -300,12 +299,7 @@ public:
}
//! Set the name of the graphviz file.
void SetGraphVizFile(std::string const& ts)
{
std::string path = cmSystemTools::CollapseFullPath(ts);
cmSystemTools::ConvertToUnixSlashes(path);
this->GraphVizFile = path;
}
void SetGraphVizFile(std::string const& ts) { this->GraphVizFile = ts; }
bool IsAKnownSourceExtension(cm::string_view ext) const
{
+3 -3
View File
@@ -601,7 +601,7 @@ int do_build(int ac, char const* const* av)
}
}
if (!matched && i == 0) {
dir = cmSystemTools::CollapseFullPath(arg);
dir = cmSystemTools::ToNormalizedPathOnDisk(arg);
matched = true;
parsed = true;
}
@@ -873,7 +873,7 @@ int do_install(int ac, char const* const* av)
};
if (ac >= 3) {
dir = cmSystemTools::CollapseFullPath(av[2]);
dir = cmSystemTools::ToNormalizedPathOnDisk(av[2]);
std::vector<std::string> inputArgs;
inputArgs.reserve(ac - 3);
@@ -1098,7 +1098,7 @@ int do_open(int ac, char const* const* av)
for (int i = 2; i < ac; ++i) {
switch (doing) {
case DoingDir:
dir = cmSystemTools::CollapseFullPath(av[i]);
dir = cmSystemTools::ToNormalizedPathOnDisk(av[i]);
doing = DoingNone;
break;
default:
+9 -9
View File
@@ -1347,10 +1347,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
// Create a local generator configured for the directory in
// which dependencies will be scanned.
homeDir = cmSystemTools::CollapseFullPath(homeDir);
startDir = cmSystemTools::CollapseFullPath(startDir);
homeOutDir = cmSystemTools::CollapseFullPath(homeOutDir);
startOutDir = cmSystemTools::CollapseFullPath(startOutDir);
homeDir = cmSystemTools::ToNormalizedPathOnDisk(homeDir);
startDir = cmSystemTools::ToNormalizedPathOnDisk(startDir);
homeOutDir = cmSystemTools::ToNormalizedPathOnDisk(homeOutDir);
startOutDir = cmSystemTools::ToNormalizedPathOnDisk(startOutDir);
cm.SetHomeDirectory(homeDir);
cm.SetHomeOutputDirectory(homeOutDir);
cm.GetCurrentSnapshot().SetDefaultDefinitions();
@@ -1643,10 +1643,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
std::string startDir;
std::string homeOutDir;
std::string startOutDir;
homeDir = cmSystemTools::CollapseFullPath(args[4]);
startDir = cmSystemTools::CollapseFullPath(args[5]);
homeOutDir = cmSystemTools::CollapseFullPath(args[6]);
startOutDir = cmSystemTools::CollapseFullPath(args[7]);
homeDir = cmSystemTools::ToNormalizedPathOnDisk(args[4]);
startDir = cmSystemTools::ToNormalizedPathOnDisk(args[5]);
homeOutDir = cmSystemTools::ToNormalizedPathOnDisk(args[6]);
startOutDir = cmSystemTools::ToNormalizedPathOnDisk(args[7]);
cm.SetHomeDirectory(homeDir);
cm.SetHomeOutputDirectory(homeOutDir);
cm.GetCurrentSnapshot().SetDefaultDefinitions();
@@ -2413,7 +2413,7 @@ int cmVSLink::LinkIncremental()
// Create a resource file referencing the manifest.
std::string absManifestFile =
cmSystemTools::CollapseFullPath(this->ManifestFile);
cmSystemTools::ToNormalizedPathOnDisk(this->ManifestFile);
if (this->Verbose) {
std::cout << "Create " << this->ManifestFileRC << '\n';
}