summaryrefslogtreecommitdiff
path: root/Source/cmBinUtilsWindowsPELinker.cxx
diff options
context:
space:
mode:
authorChristian Heimlich <chris@pcserenity.com>2023-03-06 13:48:24 -0500
committerChristian Heimlich <chris@pcserenity.com>2023-03-23 15:19:26 -0400
commitfa45594407c2650e9d350e04a534dd17314bf40a (patch)
treeece7462b15067412385c43b771f58c1ffc00a549 /Source/cmBinUtilsWindowsPELinker.cxx
parent14cfd6a1ebf12c043aa4b5031bf9621bde068eb3 (diff)
downloadcmake-fa45594407c2650e9d350e04a534dd17314bf40a.tar.gz
file(GET_RUNTIME_DEPENDENCIES): Preserve casing for Windows PE binaries
For Windows PE files the `file(GET_RUNTIME_DEPENDENCIES)` command converts the name of all DLLs found during binary scanning to lowercase in order to simplify the syntax requirements of its regex filters; however, this has the side-effect of causing all DLL paths returned via RESOLVED_DEPENDENCIES_VAR to be in lowercase, regardless of their actual casing. Instead, respect the original casing as closely as possible when returning resolved dependencies after all filters have been passed: When evaluating a Windows PE format binary on a non-Windows host the casing of dependencies recorded within the binary are used. When the host is running Windows, the actual casing of the dependencies on-disk are used instead. Fixes: #23091
Diffstat (limited to 'Source/cmBinUtilsWindowsPELinker.cxx')
-rw-r--r--Source/cmBinUtilsWindowsPELinker.cxx58
1 files changed, 50 insertions, 8 deletions
diff --git a/Source/cmBinUtilsWindowsPELinker.cxx b/Source/cmBinUtilsWindowsPELinker.cxx
index 79e39e9c52..918f563387 100644
--- a/Source/cmBinUtilsWindowsPELinker.cxx
+++ b/Source/cmBinUtilsWindowsPELinker.cxx
@@ -3,7 +3,10 @@
#include "cmBinUtilsWindowsPELinker.h"
+#include <algorithm>
+#include <iterator>
#include <sstream>
+#include <utility>
#include <vector>
#include <cm/memory>
@@ -16,6 +19,27 @@
#ifdef _WIN32
# include <windows.h>
+
+# include "cmsys/Encoding.hxx"
+#endif
+
+#ifdef _WIN32
+namespace {
+
+void ReplaceWithActualNameCasing(std::string& path)
+{
+ WIN32_FIND_DATAW findData;
+ HANDLE hFind = ::FindFirstFileW(
+ cmsys::Encoding::ToWindowsExtendedPath(path).c_str(), &findData);
+
+ if (hFind != INVALID_HANDLE_VALUE) {
+ auto onDiskName = cmsys::Encoding::ToNarrow(findData.cFileName);
+ ::FindClose(hFind);
+ path.replace(path.end() - onDiskName.size(), path.end(), onDiskName);
+ }
+}
+
+}
#endif
cmBinUtilsWindowsPELinker::cmBinUtilsWindowsPELinker(
@@ -60,29 +84,47 @@ bool cmBinUtilsWindowsPELinker::ScanDependencies(
if (!this->Tool->GetFileInfo(file, needed)) {
return false;
}
- for (auto& n : needed) {
- n = cmSystemTools::LowerCase(n);
- }
+
+ struct WinPEDependency
+ {
+ WinPEDependency(std::string o)
+ : Original(std::move(o))
+ , LowerCase(cmSystemTools::LowerCase(Original))
+ {
+ }
+ std::string const Original;
+ std::string const LowerCase;
+ };
+
+ std::vector<WinPEDependency> depends;
+ depends.reserve(needed.size());
+ std::move(needed.begin(), needed.end(), std::back_inserter(depends));
std::string origin = cmSystemTools::GetFilenamePath(file);
- for (auto const& lib : needed) {
- if (!this->Archive->IsPreExcluded(lib)) {
+ for (auto const& lib : depends) {
+ if (!this->Archive->IsPreExcluded(lib.LowerCase)) {
std::string path;
bool resolved = false;
- if (!this->ResolveDependency(lib, origin, path, resolved)) {
+ if (!this->ResolveDependency(lib.LowerCase, origin, path, resolved)) {
return false;
}
if (resolved) {
if (!this->Archive->IsPostExcluded(path)) {
+#ifdef _WIN32
+ ReplaceWithActualNameCasing(path);
+#else
+ path.replace(path.end() - lib.Original.size(), path.end(),
+ lib.Original);
+#endif
bool unique;
- this->Archive->AddResolvedPath(lib, path, unique);
+ this->Archive->AddResolvedPath(lib.Original, path, unique);
if (unique &&
!this->ScanDependencies(path, cmStateEnums::SHARED_LIBRARY)) {
return false;
}
}
} else {
- this->Archive->AddUnresolvedPath(lib);
+ this->Archive->AddUnresolvedPath(lib.Original);
}
}
}