1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
4 #include "cmBinUtilsWindowsPELinker.h"
14 #include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h"
15 #include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h"
16 #include "cmRuntimeDependencyArchive.h"
17 #include "cmStringAlgorithms.h"
18 #include "cmSystemTools.h"
23 # include "cmsys/Encoding.hxx"
29 void ReplaceWithActualNameCasing(std::string
& path
)
31 WIN32_FIND_DATAW findData
;
32 HANDLE hFind
= ::FindFirstFileW(
33 cmsys::Encoding::ToWindowsExtendedPath(path
).c_str(), &findData
);
35 if (hFind
!= INVALID_HANDLE_VALUE
) {
36 auto onDiskName
= cmsys::Encoding::ToNarrow(findData
.cFileName
);
38 path
.replace(path
.end() - onDiskName
.size(), path
.end(), onDiskName
);
45 cmBinUtilsWindowsPELinker::cmBinUtilsWindowsPELinker(
46 cmRuntimeDependencyArchive
* archive
)
47 : cmBinUtilsLinker(archive
)
51 bool cmBinUtilsWindowsPELinker::Prepare()
53 std::string tool
= this->Archive
->GetGetRuntimeDependenciesTool();
55 std::vector
<std::string
> command
;
56 if (this->Archive
->GetGetRuntimeDependenciesCommand("dumpbin", command
)) {
62 if (tool
== "dumpbin") {
64 cm::make_unique
<cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool
>(
66 } else if (tool
== "objdump") {
68 cm::make_unique
<cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool
>(
72 e
<< "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool
;
73 this->SetError(e
.str());
80 bool cmBinUtilsWindowsPELinker::ScanDependencies(
81 std::string
const& file
, cmStateEnums::TargetType
/* unused */)
83 std::vector
<std::string
> needed
;
84 if (!this->Tool
->GetFileInfo(file
, needed
)) {
88 struct WinPEDependency
90 WinPEDependency(std::string o
)
91 : Original(std::move(o
))
92 , LowerCase(cmSystemTools::LowerCase(Original
))
95 std::string
const Original
;
96 std::string
const LowerCase
;
99 std::vector
<WinPEDependency
> depends
;
100 depends
.reserve(needed
.size());
101 std::move(needed
.begin(), needed
.end(), std::back_inserter(depends
));
102 std::string origin
= cmSystemTools::GetFilenamePath(file
);
104 for (auto const& lib
: depends
) {
105 if (!this->Archive
->IsPreExcluded(lib
.LowerCase
)) {
107 bool resolved
= false;
108 if (!this->ResolveDependency(lib
.LowerCase
, origin
, path
, resolved
)) {
112 if (!this->Archive
->IsPostExcluded(path
)) {
114 ReplaceWithActualNameCasing(path
);
116 path
.replace(path
.end() - lib
.Original
.size(), path
.end(),
120 this->Archive
->AddResolvedPath(lib
.Original
, path
, unique
);
122 !this->ScanDependencies(path
, cmStateEnums::SHARED_LIBRARY
)) {
127 this->Archive
->AddUnresolvedPath(lib
.Original
);
135 bool cmBinUtilsWindowsPELinker::ResolveDependency(std::string
const& name
,
136 std::string
const& origin
,
140 auto dirs
= this->Archive
->GetSearchDirectories();
145 if ((len
= GetWindowsDirectoryA(buf
, MAX_PATH
)) > 0) {
146 dirs
.insert(dirs
.begin(), std::string(buf
, len
));
148 if ((len
= GetSystemDirectoryA(buf
, MAX_PATH
)) > 0) {
149 dirs
.insert(dirs
.begin(), std::string(buf
, len
));
153 dirs
.insert(dirs
.begin(), origin
);
155 for (auto const& searchPath
: dirs
) {
156 path
= cmStrCat(searchPath
, '/', name
);
157 if (cmSystemTools::PathExists(path
)) {