diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index c72dbe45f0..6826b67585 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -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 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, diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index 6f6374c0da..35877f366e 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -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;