/src/CMake/Source/cmInstallRuntimeDependencySetGenerator.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmInstallRuntimeDependencySetGenerator.h" |
4 | | |
5 | | #include <ostream> |
6 | | #include <string> |
7 | | #include <utility> |
8 | | #include <vector> |
9 | | |
10 | | #include "cmGeneratorExpression.h" |
11 | | #include "cmInstallGenerator.h" |
12 | | #include "cmInstallType.h" |
13 | | #include "cmListFileCache.h" |
14 | | #include "cmLocalGenerator.h" |
15 | | #include "cmMakefile.h" |
16 | | #include "cmMessageType.h" |
17 | | #include "cmOutputConverter.h" |
18 | | #include "cmScriptGenerator.h" |
19 | | #include "cmStringAlgorithms.h" |
20 | | #include "cmake.h" |
21 | | |
22 | | cmInstallRuntimeDependencySetGenerator::cmInstallRuntimeDependencySetGenerator( |
23 | | DependencyType type, cmInstallRuntimeDependencySet* dependencySet, |
24 | | std::vector<std::string> installRPaths, bool noInstallRPath, |
25 | | std::string installNameDir, bool noInstallName, char const* depsVar, |
26 | | char const* rpathPrefix, char const* tmpVarPrefix, std::string destination, |
27 | | std::vector<std::string> const& configurations, std::string component, |
28 | | std::string permissions, MessageLevel message, bool exclude_from_all, |
29 | | cmListFileBacktrace backtrace) |
30 | 0 | : cmInstallGenerator(std::move(destination), configurations, |
31 | 0 | std::move(component), message, exclude_from_all, false, |
32 | 0 | std::move(backtrace)) |
33 | 0 | , Type(type) |
34 | 0 | , DependencySet(dependencySet) |
35 | 0 | , InstallRPaths(std::move(installRPaths)) |
36 | 0 | , NoInstallRPath(noInstallRPath) |
37 | 0 | , InstallNameDir(std::move(installNameDir)) |
38 | 0 | , NoInstallName(noInstallName) |
39 | 0 | , Permissions(std::move(permissions)) |
40 | 0 | , DepsVar(depsVar) |
41 | 0 | , RPathPrefix(rpathPrefix) |
42 | 0 | , TmpVarPrefix(tmpVarPrefix) |
43 | 0 | { |
44 | 0 | this->ActionsPerConfig = true; |
45 | 0 | } |
46 | | |
47 | | bool cmInstallRuntimeDependencySetGenerator::Compute(cmLocalGenerator* lg) |
48 | 0 | { |
49 | 0 | this->LocalGenerator = lg; |
50 | 0 | return true; |
51 | 0 | } |
52 | | |
53 | | void cmInstallRuntimeDependencySetGenerator::GenerateScriptForConfig( |
54 | | std::ostream& os, std::string const& config, Indent indent) |
55 | 0 | { |
56 | 0 | if (!this->LocalGenerator->GetMakefile() |
57 | 0 | ->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL") |
58 | 0 | .empty() && |
59 | 0 | !this->NoInstallName) { |
60 | 0 | std::string installNameDir = "@rpath/"; |
61 | 0 | if (!this->InstallNameDir.empty()) { |
62 | 0 | installNameDir = this->InstallNameDir; |
63 | 0 | cmGeneratorExpression::ReplaceInstallPrefix(installNameDir, |
64 | 0 | "${CMAKE_INSTALL_PREFIX}"); |
65 | 0 | installNameDir = cmGeneratorExpression::Evaluate( |
66 | 0 | installNameDir, this->LocalGenerator, config); |
67 | 0 | if (installNameDir.empty()) { |
68 | 0 | this->LocalGenerator->GetMakefile()->GetCMakeInstance()->IssueMessage( |
69 | 0 | MessageType::FATAL_ERROR, |
70 | 0 | "INSTALL_NAME_DIR argument must not evaluate to an " |
71 | 0 | "empty string", |
72 | 0 | this->Backtrace); |
73 | 0 | return; |
74 | 0 | } |
75 | 0 | if (installNameDir.back() != '/') { |
76 | 0 | installNameDir += '/'; |
77 | 0 | } |
78 | 0 | } |
79 | 0 | os << indent << "set(" << this->TmpVarPrefix << "_install_name_dir \"" |
80 | 0 | << installNameDir << "\")\n"; |
81 | 0 | } |
82 | | |
83 | 0 | os << indent << "foreach(" << this->TmpVarPrefix << "_dep IN LISTS " |
84 | 0 | << this->DepsVar << ")\n"; |
85 | |
|
86 | 0 | if (!this->LocalGenerator->GetMakefile() |
87 | 0 | ->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL") |
88 | 0 | .empty()) { |
89 | 0 | std::vector<std::string> evaluatedRPaths; |
90 | 0 | for (auto const& rpath : this->InstallRPaths) { |
91 | 0 | std::string result = |
92 | 0 | cmGeneratorExpression::Evaluate(rpath, this->LocalGenerator, config); |
93 | 0 | if (!result.empty()) { |
94 | 0 | evaluatedRPaths.push_back(std::move(result)); |
95 | 0 | } |
96 | 0 | } |
97 | |
|
98 | 0 | switch (this->Type) { |
99 | 0 | case DependencyType::Library: |
100 | 0 | this->GenerateAppleLibraryScript(os, config, evaluatedRPaths, |
101 | 0 | indent.Next()); |
102 | 0 | break; |
103 | 0 | case DependencyType::Framework: |
104 | 0 | this->GenerateAppleFrameworkScript(os, config, evaluatedRPaths, |
105 | 0 | indent.Next()); |
106 | 0 | break; |
107 | 0 | } |
108 | 0 | } else { |
109 | 0 | std::string depVar = cmStrCat(this->TmpVarPrefix, "_dep"); |
110 | |
|
111 | 0 | this->AddInstallRule( |
112 | 0 | os, this->GetDestination(config), cmInstallType_SHARED_LIBRARY, {}, |
113 | 0 | false, this->Permissions.c_str(), nullptr, nullptr, |
114 | 0 | " FOLLOW_SYMLINK_CHAIN", indent.Next(), depVar.c_str()); |
115 | |
|
116 | 0 | if (this->LocalGenerator->GetMakefile()->GetSafeDefinition( |
117 | 0 | "CMAKE_SYSTEM_NAME") == "Linux" && |
118 | 0 | !this->NoInstallRPath) { |
119 | 0 | std::string evaluatedRPath; |
120 | 0 | for (auto const& rpath : this->InstallRPaths) { |
121 | 0 | std::string result = |
122 | 0 | cmGeneratorExpression::Evaluate(rpath, this->LocalGenerator, config); |
123 | 0 | if (!result.empty()) { |
124 | 0 | if (evaluatedRPath.empty()) { |
125 | 0 | evaluatedRPath = std::move(result); |
126 | 0 | } else { |
127 | 0 | evaluatedRPath += ':'; |
128 | 0 | evaluatedRPath += result; |
129 | 0 | } |
130 | 0 | } |
131 | 0 | } |
132 | |
|
133 | 0 | os << indent.Next() << "get_filename_component(" << this->TmpVarPrefix |
134 | 0 | << "_dep_name \"${" << this->TmpVarPrefix << "_dep}\" NAME)\n"; |
135 | 0 | if (evaluatedRPath.empty()) { |
136 | 0 | os << indent.Next() << "file(RPATH_REMOVE FILE \"" |
137 | 0 | << GetDestDirPath( |
138 | 0 | ConvertToAbsoluteDestination(this->GetDestination(config))) |
139 | 0 | << "/${" << this->TmpVarPrefix << "_dep_name}\")\n"; |
140 | 0 | } else { |
141 | 0 | os << indent.Next() << "file(RPATH_SET FILE \"" |
142 | 0 | << GetDestDirPath( |
143 | 0 | ConvertToAbsoluteDestination(this->GetDestination(config))) |
144 | 0 | << "/${" << this->TmpVarPrefix << "_dep_name}\" NEW_RPATH " |
145 | 0 | << cmOutputConverter::EscapeForCMake(evaluatedRPath) << ")\n"; |
146 | 0 | } |
147 | 0 | } |
148 | 0 | } |
149 | | |
150 | 0 | os << indent << "endforeach()\n"; |
151 | 0 | } |
152 | | |
153 | | void cmInstallRuntimeDependencySetGenerator::GenerateAppleLibraryScript( |
154 | | std::ostream& os, std::string const& config, |
155 | | std::vector<std::string> const& evaluatedRPaths, Indent indent) |
156 | 0 | { |
157 | 0 | os << indent << "if(NOT " << this->TmpVarPrefix |
158 | 0 | << "_dep MATCHES \"\\\\.framework/\")\n"; |
159 | |
|
160 | 0 | auto depName = cmStrCat(this->TmpVarPrefix, "_dep"); |
161 | 0 | this->AddInstallRule( |
162 | 0 | os, this->GetDestination(config), cmInstallType_SHARED_LIBRARY, {}, false, |
163 | 0 | this->Permissions.c_str(), nullptr, nullptr, " FOLLOW_SYMLINK_CHAIN", |
164 | 0 | indent.Next(), depName.c_str()); |
165 | |
|
166 | 0 | os << indent.Next() << "get_filename_component(" << this->TmpVarPrefix |
167 | 0 | << "_dep_name \"${" << this->TmpVarPrefix << "_dep}\" NAME)\n"; |
168 | 0 | auto depNameVar = cmStrCat("${", this->TmpVarPrefix, "_dep_name}"); |
169 | 0 | this->GenerateInstallNameFixup(os, config, evaluatedRPaths, |
170 | 0 | cmStrCat("${", this->TmpVarPrefix, "_dep}"), |
171 | 0 | depNameVar, indent.Next()); |
172 | |
|
173 | 0 | os << indent << "endif()\n"; |
174 | 0 | } |
175 | | |
176 | | void cmInstallRuntimeDependencySetGenerator::GenerateAppleFrameworkScript( |
177 | | std::ostream& os, std::string const& config, |
178 | | std::vector<std::string> const& evaluatedRPaths, Indent indent) |
179 | 0 | { |
180 | 0 | os << indent << "if(" << this->TmpVarPrefix |
181 | 0 | << "_dep MATCHES \"^(.*/)?([^/]*\\\\.framework)/(.*)$\")\n" |
182 | 0 | << indent.Next() << "set(" << this->TmpVarPrefix |
183 | 0 | << "_dir \"${CMAKE_MATCH_1}\")\n" |
184 | 0 | << indent.Next() << "set(" << this->TmpVarPrefix |
185 | 0 | << "_name \"${CMAKE_MATCH_2}\")\n" |
186 | 0 | << indent.Next() << "set(" << this->TmpVarPrefix |
187 | 0 | << "_file \"${CMAKE_MATCH_3}\")\n" |
188 | 0 | << indent.Next() << "set(" << this->TmpVarPrefix << "_path \"${" |
189 | 0 | << this->TmpVarPrefix << "_dir}${" << this->TmpVarPrefix << "_name}\")\n"; |
190 | |
|
191 | 0 | auto depName = cmStrCat(this->TmpVarPrefix, "_path"); |
192 | 0 | this->AddInstallRule( |
193 | 0 | os, this->GetDestination(config), cmInstallType_DIRECTORY, {}, false, |
194 | 0 | this->Permissions.c_str(), nullptr, nullptr, " USE_SOURCE_PERMISSIONS", |
195 | 0 | indent.Next(), depName.c_str()); |
196 | |
|
197 | 0 | auto depNameVar = cmStrCat("${", this->TmpVarPrefix, "_name}/${", |
198 | 0 | this->TmpVarPrefix, "_file}"); |
199 | 0 | this->GenerateInstallNameFixup(os, config, evaluatedRPaths, |
200 | 0 | cmStrCat("${", this->TmpVarPrefix, "_dep}"), |
201 | 0 | depNameVar, indent.Next()); |
202 | |
|
203 | 0 | os << indent << "endif()\n"; |
204 | 0 | } |
205 | | |
206 | | void cmInstallRuntimeDependencySetGenerator::GenerateInstallNameFixup( |
207 | | std::ostream& os, std::string const& config, |
208 | | std::vector<std::string> const& evaluatedRPaths, std::string const& filename, |
209 | | std::string const& depName, Indent indent) |
210 | 0 | { |
211 | 0 | if (!(this->NoInstallRPath && this->NoInstallName)) { |
212 | 0 | auto indent2 = indent; |
213 | 0 | if (evaluatedRPaths.empty() && this->NoInstallName) { |
214 | 0 | indent2 = indent2.Next(); |
215 | 0 | os << indent << "if(" << this->RPathPrefix << "_" << filename << ")\n"; |
216 | 0 | } |
217 | 0 | os << indent2 << "set(" << this->TmpVarPrefix << "_rpath_args)\n"; |
218 | 0 | if (!this->NoInstallRPath) { |
219 | 0 | os << indent2 << "foreach(" << this->TmpVarPrefix << "_rpath IN LISTS " |
220 | 0 | << this->RPathPrefix << '_' << filename << ")\n" |
221 | 0 | << indent2.Next() << "list(APPEND " << this->TmpVarPrefix |
222 | 0 | << "_rpath_args -delete_rpath \"${" << this->TmpVarPrefix |
223 | 0 | << "_rpath}\")\n" |
224 | 0 | << indent2 << "endforeach()\n"; |
225 | 0 | } |
226 | 0 | os << indent2 << "execute_process(COMMAND \"" |
227 | 0 | << this->LocalGenerator->GetMakefile()->GetSafeDefinition( |
228 | 0 | "CMAKE_INSTALL_NAME_TOOL") |
229 | 0 | << "\" ${" << this->TmpVarPrefix << "_rpath_args}\n"; |
230 | 0 | if (!this->NoInstallRPath) { |
231 | 0 | for (auto const& rpath : evaluatedRPaths) { |
232 | 0 | os << indent2 << " -add_rpath " |
233 | 0 | << cmOutputConverter::EscapeForCMake(rpath) << "\n"; |
234 | 0 | } |
235 | 0 | } |
236 | 0 | if (!this->NoInstallName) { |
237 | 0 | os << indent2 << " -id \"${" << this->TmpVarPrefix |
238 | 0 | << "_install_name_dir}" << depName << "\"\n"; |
239 | 0 | } |
240 | 0 | os << indent2 << " \"" |
241 | 0 | << GetDestDirPath( |
242 | 0 | ConvertToAbsoluteDestination(this->GetDestination(config))) |
243 | 0 | << "/" << depName << "\")\n"; |
244 | 0 | if (evaluatedRPaths.empty() && this->NoInstallName) { |
245 | 0 | os << indent << "endif()\n"; |
246 | 0 | } |
247 | 0 | } |
248 | 0 | } |
249 | | |
250 | | void cmInstallRuntimeDependencySetGenerator::GenerateStripFixup( |
251 | | std::ostream& os, std::string const& config, std::string const& depName, |
252 | | Indent indent) |
253 | 0 | { |
254 | 0 | std::string strip = |
255 | 0 | this->LocalGenerator->GetMakefile()->GetSafeDefinition("CMAKE_STRIP"); |
256 | 0 | if (!strip.empty()) { |
257 | 0 | os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n" |
258 | 0 | << indent.Next() << "execute_process(COMMAND \"" << strip << "\" "; |
259 | 0 | if (this->LocalGenerator->GetMakefile()->IsOn("APPLE")) { |
260 | 0 | os << "-x "; |
261 | 0 | } |
262 | 0 | os << "\"" |
263 | 0 | << GetDestDirPath( |
264 | 0 | ConvertToAbsoluteDestination(this->GetDestination(config))) |
265 | 0 | << "/" << depName << "\")\n" |
266 | 0 | << indent << "endif()\n"; |
267 | 0 | } |
268 | 0 | } |
269 | | |
270 | | std::string cmInstallRuntimeDependencySetGenerator::GetDestination( |
271 | | std::string const& config) const |
272 | 0 | { |
273 | 0 | return cmGeneratorExpression::Evaluate(this->Destination, |
274 | 0 | this->LocalGenerator, config); |
275 | 0 | } |