1 //===-- XcodeSDK.cpp ------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Utility/XcodeSDK.h"
10 #include "lldb/Utility/FileSpec.h"
12 #include "lldb/lldb-types.h"
14 #include "llvm/TargetParser/Triple.h"
19 using namespace lldb_private
;
21 static llvm::StringRef
GetName(XcodeSDK::Type type
) {
23 case XcodeSDK::MacOSX
:
25 case XcodeSDK::iPhoneSimulator
:
26 return "iPhoneSimulator";
27 case XcodeSDK::iPhoneOS
:
29 case XcodeSDK::AppleTVSimulator
:
30 return "AppleTVSimulator";
31 case XcodeSDK::AppleTVOS
:
33 case XcodeSDK::WatchSimulator
:
34 return "WatchSimulator";
35 case XcodeSDK::watchOS
:
37 case XcodeSDK::XRSimulator
:
41 case XcodeSDK::bridgeOS
:
45 case XcodeSDK::unknown
:
48 llvm_unreachable("Unhandled sdk type!");
51 XcodeSDK::XcodeSDK(XcodeSDK::Info info
) : m_name(GetName(info
.type
).str()) {
52 if (!m_name
.empty()) {
53 if (!info
.version
.empty())
54 m_name
+= info
.version
.getAsString();
56 m_name
+= ".Internal";
61 XcodeSDK
&XcodeSDK::operator=(const XcodeSDK
&other
) = default;
63 bool XcodeSDK::operator==(const XcodeSDK
&other
) const {
64 return m_name
== other
.m_name
;
67 static XcodeSDK::Type
ParseSDKName(llvm::StringRef
&name
) {
68 if (name
.consume_front("MacOSX"))
69 return XcodeSDK::MacOSX
;
70 if (name
.consume_front("iPhoneSimulator"))
71 return XcodeSDK::iPhoneSimulator
;
72 if (name
.consume_front("iPhoneOS"))
73 return XcodeSDK::iPhoneOS
;
74 if (name
.consume_front("AppleTVSimulator"))
75 return XcodeSDK::AppleTVSimulator
;
76 if (name
.consume_front("AppleTVOS"))
77 return XcodeSDK::AppleTVOS
;
78 if (name
.consume_front("WatchSimulator"))
79 return XcodeSDK::WatchSimulator
;
80 if (name
.consume_front("WatchOS"))
81 return XcodeSDK::watchOS
;
82 if (name
.consume_front("XRSimulator"))
83 return XcodeSDK::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
;
95 static llvm::VersionTuple
ParseSDKVersion(llvm::StringRef
&name
) {
97 while (i
< name
.size() && name
[i
] >= '0' && name
[i
] <= '9')
99 if (i
== name
.size() || name
[i
++] != '.')
101 while (i
< name
.size() && name
[i
] >= '0' && name
[i
] <= '9')
103 if (i
== name
.size() || name
[i
++] != '.')
106 llvm::VersionTuple version
;
107 version
.tryParse(name
.slice(0, i
- 1));
108 name
= name
.drop_front(i
);
112 static bool ParseAppleInternalSDK(llvm::StringRef
&name
) {
113 return name
.consume_front("Internal.") || name
.consume_front(".Internal.");
116 XcodeSDK::Info
XcodeSDK::Parse() const {
118 llvm::StringRef
input(m_name
);
119 info
.type
= ParseSDKName(input
);
120 info
.version
= ParseSDKVersion(input
);
121 info
.internal
= ParseAppleInternalSDK(input
);
125 bool XcodeSDK::IsAppleInternalSDK() const {
126 llvm::StringRef
input(m_name
);
128 ParseSDKVersion(input
);
129 return ParseAppleInternalSDK(input
);
132 llvm::VersionTuple
XcodeSDK::GetVersion() const {
133 llvm::StringRef
input(m_name
);
135 return ParseSDKVersion(input
);
138 XcodeSDK::Type
XcodeSDK::GetType() const {
139 llvm::StringRef
input(m_name
);
140 return ParseSDKName(input
);
143 llvm::StringRef
XcodeSDK::GetString() const { return m_name
; }
145 bool XcodeSDK::Info::operator<(const Info
&other
) const {
146 return std::tie(type
, version
, internal
) <
147 std::tie(other
.type
, other
.version
, other
.internal
);
150 bool XcodeSDK::Info::operator==(const Info
&other
) const {
151 return std::tie(type
, version
, internal
) ==
152 std::tie(other
.type
, other
.version
, other
.internal
);
155 void XcodeSDK::Merge(const XcodeSDK
&other
) {
156 // The "bigger" SDK always wins.
158 auto r
= other
.Parse();
162 // The Internal flag always wins.
163 if (llvm::StringRef(m_name
).ends_with(".sdk"))
164 if (!l
.internal
&& r
.internal
)
166 m_name
.substr(0, m_name
.size() - 3) + std::string("Internal.sdk");
170 std::string
XcodeSDK::GetCanonicalName(XcodeSDK::Info info
) {
176 case iPhoneSimulator
:
177 name
= "iphonesimulator";
182 case AppleTVSimulator
:
183 name
= "appletvsimulator";
189 name
= "watchsimulator";
195 name
= "xrsimulator";
209 if (!info
.version
.empty())
210 name
+= info
.version
.getAsString();
216 bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type sdk_type
,
217 llvm::VersionTuple version
) {
220 return version
>= llvm::VersionTuple(10, 10);
222 case Type::iPhoneSimulator
:
223 case Type::AppleTVOS
:
224 case Type::AppleTVSimulator
:
225 return version
>= llvm::VersionTuple(8);
227 case Type::WatchSimulator
:
228 return version
>= llvm::VersionTuple(6);
230 case Type::XRSimulator
:
239 bool XcodeSDK::SupportsSwift() const {
240 XcodeSDK::Info info
= Parse();
243 return info
.version
.empty() || info
.version
>= llvm::VersionTuple(10, 10);
245 case Type::iPhoneSimulator
:
246 return info
.version
.empty() || info
.version
>= llvm::VersionTuple(8);
247 case Type::AppleTVSimulator
:
248 case Type::AppleTVOS
:
249 return info
.version
.empty() || info
.version
>= llvm::VersionTuple(9);
250 case Type::WatchSimulator
:
252 return info
.version
.empty() || info
.version
>= llvm::VersionTuple(2);
254 case Type::XRSimulator
:
262 bool XcodeSDK::SDKSupportsBuiltinModules(const llvm::Triple
&target_triple
,
263 llvm::VersionTuple sdk_version
) {
264 using namespace llvm
;
266 switch (target_triple
.getOS()) {
267 case Triple::OSType::MacOSX
:
268 return sdk_version
>= VersionTuple(15U);
269 case Triple::OSType::IOS
:
270 return sdk_version
>= VersionTuple(18U);
271 case Triple::OSType::TvOS
:
272 return sdk_version
>= VersionTuple(18U);
273 case Triple::OSType::WatchOS
:
274 return sdk_version
>= VersionTuple(11U);
275 case Triple::OSType::XROS
:
276 return sdk_version
>= VersionTuple(2U);
278 // New SDKs support builtin modules from the start.
283 bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type desired_type
,
284 const FileSpec
&sdk_path
) {
285 ConstString last_path_component
= sdk_path
.GetFilename();
287 if (!last_path_component
)
290 XcodeSDK
sdk(last_path_component
.GetStringRef().str());
291 if (sdk
.GetType() != desired_type
)
293 return SDKSupportsModules(sdk
.GetType(), sdk
.GetVersion());
296 XcodeSDK::Type
XcodeSDK::GetSDKTypeForTriple(const llvm::Triple
&triple
) {
297 using namespace llvm
;
298 switch (triple
.getOS()) {
301 return XcodeSDK::MacOSX
;
303 switch (triple
.getEnvironment()) {
305 return XcodeSDK::MacOSX
;
306 case Triple::Simulator
:
307 return XcodeSDK::iPhoneSimulator
;
309 return XcodeSDK::iPhoneOS
;
312 if (triple
.getEnvironment() == Triple::Simulator
)
313 return XcodeSDK::AppleTVSimulator
;
314 return XcodeSDK::AppleTVOS
;
315 case Triple::WatchOS
:
316 if (triple
.getEnvironment() == Triple::Simulator
)
317 return XcodeSDK::WatchSimulator
;
318 return XcodeSDK::watchOS
;
320 if (triple
.getEnvironment() == Triple::Simulator
)
321 return XcodeSDK::XRSimulator
;
322 return XcodeSDK::XROS
;
324 return XcodeSDK::Linux
;
326 return XcodeSDK::unknown
;
330 std::string
XcodeSDK::FindXcodeContentsDirectoryInPath(llvm::StringRef path
) {
331 auto begin
= llvm::sys::path::begin(path
);
332 auto end
= llvm::sys::path::end(path
);
334 // Iterate over the path components until we find something that ends with
335 // .app. If the next component is Contents then we've found the Contents
337 for (auto it
= begin
; it
!= end
; ++it
) {
338 if (it
->ends_with(".app")) {
340 if (++next
!= end
&& *next
== "Contents") {
341 llvm::SmallString
<128> buffer
;
342 llvm::sys::path::append(buffer
, begin
, ++next
,
343 llvm::sys::path::Style::posix
);
344 return buffer
.str().str();