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/ADT/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 "bridgeOS";
39 case XcodeSDK::Linux:
40 return "Linux";
42 return {};
43 }
44 llvm_unreachable("Unhandled sdk type!");
45}
46
47XcodeSDK::XcodeSDK(XcodeSDK::Info info) : m_name(GetName(info.type).str()) {
48 if (!m_name.empty()) {
49 if (!info.version.empty())
50 m_name += info.version.getAsString();
51 if (info.internal)
52 m_name += ".Internal";
53 m_name += ".sdk";
54 }
55}
56
57XcodeSDK &XcodeSDK::operator=(const XcodeSDK &other) = default;
58
59bool XcodeSDK::operator==(const XcodeSDK &other) {
60 return m_name == other.m_name;
61}
62
63static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) {
64 if (name.consume_front("MacOSX"))
65 return XcodeSDK::MacOSX;
66 if (name.consume_front("iPhoneSimulator"))
68 if (name.consume_front("iPhoneOS"))
69 return XcodeSDK::iPhoneOS;
70 if (name.consume_front("AppleTVSimulator"))
72 if (name.consume_front("AppleTVOS"))
74 if (name.consume_front("WatchSimulator"))
76 if (name.consume_front("WatchOS"))
77 return XcodeSDK::watchOS;
78 if (name.consume_front("bridgeOS"))
79 return XcodeSDK::bridgeOS;
80 if (name.consume_front("Linux"))
81 return XcodeSDK::Linux;
82 static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1,
83 "New SDK type was added, update this list!");
84 return XcodeSDK::unknown;
85}
86
87static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) {
88 unsigned i = 0;
89 while (i < name.size() && name[i] >= '0' && name[i] <= '9')
90 ++i;
91 if (i == name.size() || name[i++] != '.')
92 return {};
93 while (i < name.size() && name[i] >= '0' && name[i] <= '9')
94 ++i;
95 if (i == name.size() || name[i++] != '.')
96 return {};
97
98 llvm::VersionTuple version;
99 version.tryParse(name.slice(0, i - 1));
100 name = name.drop_front(i);
101 return version;
102}
103
104static bool ParseAppleInternalSDK(llvm::StringRef &name) {
105 return name.consume_front("Internal.") || name.consume_front(".Internal.");
106}
107
109 XcodeSDK::Info info;
110 llvm::StringRef input(m_name);
111 info.type = ParseSDKName(input);
112 info.version = ParseSDKVersion(input);
113 info.internal = ParseAppleInternalSDK(input);
114 return info;
115}
116
118 llvm::StringRef input(m_name);
119 ParseSDKName(input);
120 ParseSDKVersion(input);
121 return ParseAppleInternalSDK(input);
122}
123
124llvm::VersionTuple XcodeSDK::GetVersion() const {
125 llvm::StringRef input(m_name);
126 ParseSDKName(input);
127 return ParseSDKVersion(input);
128}
129
131 llvm::StringRef input(m_name);
132 return ParseSDKName(input);
133}
134
135llvm::StringRef XcodeSDK::GetString() const { return m_name; }
136
137bool XcodeSDK::Info::operator<(const Info &other) const {
138 return std::tie(type, version, internal) <
139 std::tie(other.type, other.version, other.internal);
140}
141
142bool XcodeSDK::Info::operator==(const Info &other) const {
143 return std::tie(type, version, internal) ==
144 std::tie(other.type, other.version, other.internal);
145}
146
147void XcodeSDK::Merge(const XcodeSDK &other) {
148 // The "bigger" SDK always wins.
149 auto l = Parse();
150 auto r = other.Parse();
151 if (l < r)
152 *this = other;
153 else {
154 // The Internal flag always wins.
155 if (llvm::StringRef(m_name).endswith(".sdk"))
156 if (!l.internal && r.internal)
157 m_name =
158 m_name.substr(0, m_name.size() - 3) + std::string("Internal.sdk");
159 }
160}
161
163 std::string name;
164 switch (info.type) {
165 case MacOSX:
166 name = "macosx";
167 break;
168 case iPhoneSimulator:
169 name = "iphonesimulator";
170 break;
171 case iPhoneOS:
172 name = "iphoneos";
173 break;
174 case AppleTVSimulator:
175 name = "appletvsimulator";
176 break;
177 case AppleTVOS:
178 name = "appletvos";
179 break;
180 case WatchSimulator:
181 name = "watchsimulator";
182 break;
183 case watchOS:
184 name = "watchos";
185 break;
186 case bridgeOS:
187 name = "bridgeos";
188 break;
189 case Linux:
190 name = "linux";
191 break;
192 case unknown:
193 return {};
194 }
195 if (!info.version.empty())
196 name += info.version.getAsString();
197 if (info.internal)
198 name += ".internal";
199 return name;
200}
201
203 llvm::VersionTuple version) {
204 switch (sdk_type) {
205 case Type::MacOSX:
206 return version >= llvm::VersionTuple(10, 10);
207 case Type::iPhoneOS:
209 case Type::AppleTVOS:
211 return version >= llvm::VersionTuple(8);
212 case Type::watchOS:
214 return version >= llvm::VersionTuple(6);
215 default:
216 return false;
217 }
218
219 return false;
220}
221
223 XcodeSDK::Info info = Parse();
224 switch (info.type) {
225 case Type::MacOSX:
226 return info.version.empty() || info.version >= llvm::VersionTuple(10, 10);
227 case Type::iPhoneOS:
229 return info.version.empty() || info.version >= llvm::VersionTuple(8);
231 case Type::AppleTVOS:
232 return info.version.empty() || info.version >= llvm::VersionTuple(9);
234 case Type::watchOS:
235 return info.version.empty() || info.version >= llvm::VersionTuple(2);
236 case Type::Linux:
237 return true;
238 default:
239 return false;
240 }
241}
242
244 const FileSpec &sdk_path) {
245 ConstString last_path_component = sdk_path.GetLastPathComponent();
246
247 if (!last_path_component)
248 return false;
249
250 XcodeSDK sdk(last_path_component.GetStringRef().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::Linux:
280 return XcodeSDK::Linux;
281 default:
282 return XcodeSDK::unknown;
283 }
284}
285
286std::string XcodeSDK::FindXcodeContentsDirectoryInPath(llvm::StringRef path) {
287 auto begin = llvm::sys::path::begin(path);
288 auto end = llvm::sys::path::end(path);
289
290 // Iterate over the path components until we find something that ends with
291 // .app. If the next component is Contents then we've found the Contents
292 // directory.
293 for (auto it = begin; it != end; ++it) {
294 if (it->endswith(".app")) {
295 auto next = it;
296 if (++next != end && *next == "Contents") {
297 llvm::SmallString<128> buffer;
298 llvm::sys::path::append(buffer, begin, ++next,
299 llvm::sys::path::Style::posix);
300 return buffer.str().str();
301 }
302 }
303 }
304
305 return {};
306}
static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name)
Definition: XcodeSDK.cpp:87
static llvm::StringRef GetName(XcodeSDK::Type type)
Definition: XcodeSDK.cpp:21
static bool ParseAppleInternalSDK(llvm::StringRef &name)
Definition: XcodeSDK.cpp:104
static XcodeSDK::Type ParseSDKName(llvm::StringRef &name)
Definition: XcodeSDK.cpp:63
A uniqued constant string class.
Definition: ConstString.h:39
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:201
A file utility class.
Definition: FileSpec.h:56
ConstString GetLastPathComponent() const
Definition: FileSpec.cpp:433
An abstraction for Xcode-style SDKs that works like ArchSpec.
Definition: XcodeSDK.h:24
static constexpr int numSDKTypes
Definition: XcodeSDK.h:41
bool SupportsSwift() const
Whether this Xcode SDK supports Swift.
Definition: XcodeSDK.cpp:222
bool operator==(const XcodeSDK &other)
Definition: XcodeSDK.cpp:59
Type
Different types of Xcode SDKs.
Definition: XcodeSDK.h:29
static std::string FindXcodeContentsDirectoryInPath(llvm::StringRef path)
Definition: XcodeSDK.cpp:286
Type GetType() const
Definition: XcodeSDK.cpp:130
void Merge(const XcodeSDK &other)
The merge function follows a strict order to maintain monotonicity:
Definition: XcodeSDK.cpp:147
XcodeSDK & operator=(const XcodeSDK &other)
XcodeSDK()=default
Default constructor, constructs an empty string.
std::string m_name
Definition: XcodeSDK.h:25
llvm::VersionTuple GetVersion() const
Definition: XcodeSDK.cpp:124
llvm::StringRef GetString() const
Definition: XcodeSDK.cpp:135
static std::string GetCanonicalName(Info info)
Return the canonical SDK name, such as "macosx" for the macOS SDK.
Definition: XcodeSDK.cpp:162
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:108
bool IsAppleInternalSDK() const
Definition: XcodeSDK.cpp:117
static bool SDKSupportsModules(Type type, llvm::VersionTuple version)
Whether LLDB feels confident importing Clang modules from this SDK.
Definition: XcodeSDK.cpp:202
A class that represents a running process on the host machine.
Definition: SBAddress.h:15
Definition: Debugger.h:51
A parsed SDK directory name.
Definition: XcodeSDK.h:44
llvm::VersionTuple version
Definition: XcodeSDK.h:46
bool operator<(const Info &other) const
Definition: XcodeSDK.cpp:137
bool operator==(const Info &other) const
Definition: XcodeSDK.cpp:142