LLDB mainline
XcodeSDK.cpp
Go to the documentation of this file.
1//===-- XcodeSDK.cpp ------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11
12#include "lldb/lldb-types.h"
13
14#include "llvm/TargetParser/Triple.h"
15
16#include <string>
17
18using namespace lldb;
19using namespace lldb_private;
20
21static llvm::StringRef GetName(XcodeSDK::Type type) {
22 switch (type) {
24 return "MacOSX";
26 return "iPhoneSimulator";
28 return "iPhoneOS";
30 return "AppleTVSimulator";
32 return "AppleTVOS";
34 return "WatchSimulator";
36 return "WatchOS";
38 return "XRSimulator";
39 case XcodeSDK::XROS:
40 return "XROS";
42 return "BridgeOS";
43 case XcodeSDK::Linux:
44 return "Linux";
46 return {};
47 }
48 llvm_unreachable("Unhandled sdk type!");
49}
50
52 if (!m_name.empty()) {
53 if (!info.version.empty())
54 m_name += info.version.getAsString();
55 if (info.internal)
56 m_name += ".Internal";
57 m_name += ".sdk";
58 }
59}
60
61XcodeSDK &XcodeSDK::operator=(const XcodeSDK &other) = default;
62
63bool XcodeSDK::operator==(const XcodeSDK &other) const {
64 return m_name == other.m_name;
65}
66
67static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) {
68 if (name.consume_front("MacOSX"))
69 return XcodeSDK::MacOSX;
70 if (name.consume_front("iPhoneSimulator"))
72 if (name.consume_front("iPhoneOS"))
73 return XcodeSDK::iPhoneOS;
74 if (name.consume_front("AppleTVSimulator"))
76 if (name.consume_front("AppleTVOS"))
78 if (name.consume_front("WatchSimulator"))
80 if (name.consume_front("WatchOS"))
81 return XcodeSDK::watchOS;
82 if (name.consume_front("XRSimulator"))
84 if (name.consume_front("XROS"))
85 return XcodeSDK::XROS;
86 if (name.consume_front("BridgeOS"))
87 return XcodeSDK::BridgeOS;
88 if (name.consume_front("Linux"))
89 return XcodeSDK::Linux;
90 static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1,
91 "New SDK type was added, update this list!");
92 return XcodeSDK::unknown;
93}
94
95static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) {
96 unsigned i = 0;
97 while (i < name.size() && name[i] >= '0' && name[i] <= '9')
98 ++i;
99 if (i == name.size() || name[i++] != '.')
100 return {};
101 while (i < name.size() && name[i] >= '0' && name[i] <= '9')
102 ++i;
103 if (i == name.size() || name[i++] != '.')
104 return {};
105
106 llvm::VersionTuple version;
107 version.tryParse(name.slice(0, i - 1));
108 name = name.drop_front(i);
109 return version;
110}
111
112static bool ParseAppleInternalSDK(llvm::StringRef &name) {
113 return name.consume_front("Internal.") || name.consume_front(".Internal.");
114}
115
117 XcodeSDK::Info info;
118 llvm::StringRef input(m_name);
119 info.type = ParseSDKName(input);
120 info.version = ParseSDKVersion(input);
121 info.internal = ParseAppleInternalSDK(input);
122 return info;
123}
124
126 llvm::StringRef input(m_name);
127 ParseSDKName(input);
128 ParseSDKVersion(input);
129 return ParseAppleInternalSDK(input);
130}
131
132llvm::VersionTuple XcodeSDK::GetVersion() const {
133 llvm::StringRef input(m_name);
134 ParseSDKName(input);
135 return ParseSDKVersion(input);
136}
137
139 llvm::StringRef input(m_name);
140 return ParseSDKName(input);
141}
142
143llvm::StringRef XcodeSDK::GetString() const { return m_name; }
144
145bool XcodeSDK::Info::operator<(const Info &other) const {
146 return std::tie(type, version, internal) <
147 std::tie(other.type, other.version, other.internal);
148}
149
150bool XcodeSDK::Info::operator==(const Info &other) const {
151 return std::tie(type, version, internal) ==
152 std::tie(other.type, other.version, other.internal);
153}
154
155void XcodeSDK::Merge(const XcodeSDK &other) {
156 auto add_internal_sdk_suffix = [](llvm::StringRef sdk) {
157 return (sdk.substr(0, sdk.size() - 3) + "Internal.sdk").str();
158 };
159
160 // The "bigger" SDK always wins.
161 auto l = Parse();
162 auto r = other.Parse();
163 if (l < r)
164 *this = other;
165 else {
166 // The Internal flag always wins.
167 if (!l.internal && r.internal) {
168 if (llvm::StringRef(m_name).ends_with(".sdk"))
169 m_name = add_internal_sdk_suffix(m_name);
170 }
171 }
172}
173
175 std::string name;
176 switch (info.type) {
177 case MacOSX:
178 name = "macosx";
179 break;
180 case iPhoneSimulator:
181 name = "iphonesimulator";
182 break;
183 case iPhoneOS:
184 name = "iphoneos";
185 break;
186 case AppleTVSimulator:
187 name = "appletvsimulator";
188 break;
189 case AppleTVOS:
190 name = "appletvos";
191 break;
192 case WatchSimulator:
193 name = "watchsimulator";
194 break;
195 case watchOS:
196 name = "watchos";
197 break;
198 case XRSimulator:
199 name = "xrsimulator";
200 break;
201 case XROS:
202 name = "xros";
203 break;
204 case BridgeOS:
205 name = "bridgeos";
206 break;
207 case Linux:
208 name = "linux";
209 break;
210 case unknown:
211 return {};
212 }
213 if (!info.version.empty())
214 name += info.version.getAsString();
215 if (info.internal)
216 name += ".internal";
217 return name;
218}
219
221 llvm::VersionTuple version) {
222 switch (sdk_type) {
223 case Type::MacOSX:
224 return version >= llvm::VersionTuple(10, 10);
225 case Type::iPhoneOS:
227 case Type::AppleTVOS:
229 return version >= llvm::VersionTuple(8);
230 case Type::watchOS:
232 return version >= llvm::VersionTuple(6);
233 case Type::XROS:
235 return true;
236 default:
237 return false;
238 }
239
240 return false;
241}
242
244 const FileSpec &sdk_path) {
245 llvm::StringRef last_path_component = sdk_path.GetFilename();
246
247 if (last_path_component.empty())
248 return false;
249
250 XcodeSDK sdk(last_path_component.str());
251 if (sdk.GetType() != desired_type)
252 return false;
253 return SDKSupportsModules(sdk.GetType(), sdk.GetVersion());
254}
255
257 using namespace llvm;
258 switch (triple.getOS()) {
259 case Triple::MacOSX:
260 case Triple::Darwin:
261 return XcodeSDK::MacOSX;
262 case Triple::IOS:
263 switch (triple.getEnvironment()) {
264 case Triple::MacABI:
265 return XcodeSDK::MacOSX;
266 case Triple::Simulator:
268 default:
269 return XcodeSDK::iPhoneOS;
270 }
271 case Triple::TvOS:
272 if (triple.getEnvironment() == Triple::Simulator)
274 return XcodeSDK::AppleTVOS;
275 case Triple::WatchOS:
276 if (triple.getEnvironment() == Triple::Simulator)
278 return XcodeSDK::watchOS;
279 case Triple::XROS:
280 if (triple.getEnvironment() == Triple::Simulator)
282 return XcodeSDK::XROS;
283 case Triple::Linux:
284 return XcodeSDK::Linux;
285 default:
286 return XcodeSDK::unknown;
287 }
288}
289
290std::string XcodeSDK::FindXcodeContentsDirectoryInPath(llvm::StringRef path) {
291 auto begin = llvm::sys::path::begin(path);
292 auto end = llvm::sys::path::end(path);
293
294 // Iterate over the path components until we find something that ends with
295 // .app. If the next component is Contents then we've found the Contents
296 // directory.
297 for (auto it = begin; it != end; ++it) {
298 if (it->ends_with(".app")) {
299 auto next = it;
300 if (++next != end && *next == "Contents") {
301 llvm::SmallString<128> buffer;
302 llvm::sys::path::append(buffer, begin, ++next,
303 llvm::sys::path::Style::posix);
304 return buffer.str().str();
305 }
306 }
307 }
308
309 return {};
310}
311
313 std::string old_name = m_sdk.GetString().str();
314 m_sdk.Merge(other.m_sdk);
315 llvm::StringRef new_name = m_sdk.GetString();
316 if (old_name == new_name)
317 return;
318
319 // The other SDK won outright, so its sysroot comes along with it.
320 if (new_name == other.m_sdk.GetString()) {
321 m_sysroot = other.m_sysroot;
322 return;
323 }
324
325 // Otherwise merging only added the Internal suffix to our own SDK name. The
326 // internal SDK is a sibling of the public one, so the sysroot can be renamed
327 // along with it.
328 if (m_sysroot.GetFileNameExtension() == ".sdk")
329 m_sysroot.SetFilename(new_name);
330}
331
333 return m_sdk == other.m_sdk && m_sysroot == other.m_sysroot;
334}
335
337 return !(*this == other);
338}
static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name)
Definition XcodeSDK.cpp:95
static llvm::StringRef GetName(XcodeSDK::Type type)
Definition XcodeSDK.cpp:21
static bool ParseAppleInternalSDK(llvm::StringRef &name)
Definition XcodeSDK.cpp:112
static XcodeSDK::Type ParseSDKName(llvm::StringRef &name)
Definition XcodeSDK.cpp:67
A file utility class.
Definition FileSpec.h:56
llvm::StringRef GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:248
XcodeSDKAndSysroot()=default
Constructs an empty SDK with no sysroot.
bool operator==(const XcodeSDKAndSysroot &other) const
Definition XcodeSDK.cpp:332
bool operator!=(const XcodeSDKAndSysroot &other) const
Definition XcodeSDK.cpp:336
void Merge(const XcodeSDKAndSysroot &other)
Definition XcodeSDK.cpp:312
An abstraction for Xcode-style SDKs that works like ArchSpec.
Definition XcodeSDK.h:25
static constexpr int numSDKTypes
Definition XcodeSDK.h:44
Type
Different types of Xcode SDKs.
Definition XcodeSDK.h:30
static std::string FindXcodeContentsDirectoryInPath(llvm::StringRef path)
Definition XcodeSDK.cpp:290
void Merge(const XcodeSDK &other)
The merge function follows a strict order to maintain monotonicity:
Definition XcodeSDK.cpp:155
XcodeSDK & operator=(const XcodeSDK &other)
XcodeSDK()=default
Default constructor, constructs an empty string.
std::string m_name
Definition XcodeSDK.h:26
llvm::VersionTuple GetVersion() const
Definition XcodeSDK.cpp:132
llvm::StringRef GetString() const
Definition XcodeSDK.cpp:143
static std::string GetCanonicalName(Info info)
Return the canonical SDK name, such as "macosx" for the macOS SDK.
Definition XcodeSDK.cpp:174
static XcodeSDK::Type GetSDKTypeForTriple(const llvm::Triple &triple)
Return the best-matching SDK type for a specific triple.
Definition XcodeSDK.cpp:256
Info Parse() const
Return parsed SDK type and version number.
Definition XcodeSDK.cpp:116
bool operator==(const XcodeSDK &other) const
Definition XcodeSDK.cpp:63
bool IsAppleInternalSDK() const
Definition XcodeSDK.cpp:125
static bool SDKSupportsModules(Type type, llvm::VersionTuple version)
Whether LLDB feels confident importing Clang modules from this SDK.
Definition XcodeSDK.cpp:220
A class that represents a running process on the host machine.
A parsed SDK directory name.
Definition XcodeSDK.h:47
llvm::VersionTuple version
Definition XcodeSDK.h:49
bool operator<(const Info &other) const
Definition XcodeSDK.cpp:145
bool operator==(const Info &other) const
Definition XcodeSDK.cpp:150