cmOutputConverter: Reduce string copies in ConvertToOutputForExisting

Allocate only when actually converting to a short path.
This commit is contained in:
Brad King
2026-02-20 12:19:59 -05:00
parent b368f0617d
commit 3d51b027eb
2 changed files with 21 additions and 29 deletions
+20 -28
View File
@@ -155,44 +155,36 @@ std::string cmOutputConverter::MaybeRelativeToCurBinDir(
}
std::string cmOutputConverter::ConvertToOutputForExisting(
std::string const& remote, OutputFormat format, bool useWatcomQuote) const
cm::string_view path, OutputFormat format, bool useWatcomQuote) const
{
#ifdef _WIN32
// Cache the Short Paths since we only convert the same few paths anyway and
// calling `GetShortPathNameW` is really expensive.
// Cache the short paths since `GetShortPathNameW` is really expensive.
static std::unordered_map<std::string, std::string> shortPathCache{};
// If this is a windows shell, the result has a space, and the path
// already exists, we can use a short-path to reference it without a
// space.
// If this is a windows shell, the path has a space, and the path already
// exists, we can use a short-path to reference it without a space.
if (this->GetState()->UseWindowsShell() &&
remote.find_first_of(" #") != std::string::npos &&
cmSystemTools::FileExists(remote)) {
std::string shortPath = [&]() {
auto cachedShortPathIt = shortPathCache.find(remote);
if (cachedShortPathIt != shortPathCache.end()) {
return cachedShortPathIt->second;
path.find_first_of(" #") != std::string::npos) {
auto origPath = std::string(path);
if (cmSystemTools::FileExists(origPath)) {
auto i = shortPathCache.find(origPath);
if (i == shortPathCache.end()) {
std::string shortPath;
if (!cmSystemTools::GetShortPath(origPath, shortPath)) {
// Fallback for cases when Windows refuses to resolve
// the short path, like for `C:\Program Files\WindowsApps\...`.
shortPath = origPath;
}
i = shortPathCache.emplace(std::move(origPath), std::move(shortPath))
.first;
}
std::string tmp{};
cmsys::Status status = cmSystemTools::GetShortPath(remote, tmp);
if (!status) {
// Fallback for cases when Windows refuses to resolve the short path,
// like for C:\Program Files\WindowsApps\...
tmp = remote;
}
shortPathCache[remote] = tmp;
return tmp;
}();
return this->ConvertToOutputFormat(shortPath, format, useWatcomQuote);
path = i->second;
}
}
#endif
// Otherwise, perform standard conversion.
return this->ConvertToOutputFormat(remote, format, useWatcomQuote);
return this->ConvertToOutputFormat(path, format, useWatcomQuote);
}
std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source,
+1 -1
View File
@@ -54,7 +54,7 @@ public:
std::string ConvertDirectorySeparatorsForShell(cm::string_view source) const;
//! for existing files convert to output path and short path if spaces
std::string ConvertToOutputForExisting(std::string const& remote,
std::string ConvertToOutputForExisting(cm::string_view path,
OutputFormat format = SHELL,
bool useWatcomQuote = false) const;