1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmBinUtilsWindowsPELinker.h"
#include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h"
#include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h"
#include "cmRuntimeDependencyArchive.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include <sstream>
#include <vector>
#include "cm_memory.hxx"
#ifdef _WIN32
# include <windows.h>
#endif
cmBinUtilsWindowsPELinker::cmBinUtilsWindowsPELinker(
cmRuntimeDependencyArchive* archive)
: cmBinUtilsLinker(archive)
{
}
bool cmBinUtilsWindowsPELinker::Prepare()
{
std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
if (tool.empty()) {
std::vector<std::string> command;
if (this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) {
tool = "dumpbin";
} else {
tool = "objdump";
}
}
if (tool == "dumpbin") {
this->Tool =
cm::make_unique<cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool>(
this->Archive);
} else if (tool == "objdump") {
this->Tool =
cm::make_unique<cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool>(
this->Archive);
} else {
std::ostringstream e;
e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
this->SetError(e.str());
return false;
}
return true;
}
bool cmBinUtilsWindowsPELinker::ScanDependencies(
std::string const& file, cmStateEnums::TargetType /* unused */)
{
std::vector<std::string> needed;
if (!this->Tool->GetFileInfo(file, needed)) {
return false;
}
for (auto& n : needed) {
n = cmSystemTools::LowerCase(n);
}
std::string origin = cmSystemTools::GetFilenamePath(file);
for (auto const& lib : needed) {
if (!this->Archive->IsPreExcluded(lib)) {
std::string path;
bool resolved = false;
if (!this->ResolveDependency(lib, origin, path, resolved)) {
return false;
}
if (resolved) {
if (!this->Archive->IsPostExcluded(path)) {
bool unique;
this->Archive->AddResolvedPath(lib, path, unique);
if (unique &&
!this->ScanDependencies(path, cmStateEnums::SHARED_LIBRARY)) {
return false;
}
}
} else {
this->Archive->AddUnresolvedPath(lib);
}
}
}
return true;
}
bool cmBinUtilsWindowsPELinker::ResolveDependency(std::string const& name,
std::string const& origin,
std::string& path,
bool& resolved)
{
auto dirs = this->Archive->GetSearchDirectories();
#ifdef _WIN32
char buf[MAX_PATH];
unsigned int len;
if ((len = GetWindowsDirectoryA(buf, MAX_PATH)) > 0) {
dirs.insert(dirs.begin(), std::string(buf, len));
}
if ((len = GetSystemDirectoryA(buf, MAX_PATH)) > 0) {
dirs.insert(dirs.begin(), std::string(buf, len));
}
#endif
dirs.insert(dirs.begin(), origin);
for (auto const& searchPath : dirs) {
path = cmStrCat(searchPath, '/', name);
if (cmSystemTools::PathExists(path)) {
resolved = true;
return true;
}
}
resolved = false;
return true;
}
|