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 
10 #include "lldb/Utility/FileSpec.h"
11 
12 #include "lldb/lldb-types.h"
13 
14 #include "llvm/ADT/Triple.h"
15 
16 #include <string>
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 static llvm::StringRef GetName(XcodeSDK::Type type) {
22  switch (type) {
23  case XcodeSDK::MacOSX:
24  return "MacOSX";
25  case XcodeSDK::iPhoneSimulator:
26  return "iPhoneSimulator";
27  case XcodeSDK::iPhoneOS:
28  return "iPhoneOS";
29  case XcodeSDK::AppleTVSimulator:
30  return "AppleTVSimulator";
31  case XcodeSDK::AppleTVOS:
32  return "AppleTVOS";
33  case XcodeSDK::WatchSimulator:
34  return "WatchSimulator";
35  case XcodeSDK::watchOS:
36  return "WatchOS";
37  case XcodeSDK::bridgeOS:
38  return "bridgeOS";
39  case XcodeSDK::Linux:
40  return "Linux";
41  case XcodeSDK::unknown:
42  return {};
43  }
44  llvm_unreachable("Unhandled sdk type!");
45 }
46 
47 XcodeSDK::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 
58  m_name = other.m_name;
59  return *this;
60 }
61 
62 bool XcodeSDK::operator==(const XcodeSDK &other) {
63  return m_name == other.m_name;
64 }
65 
66 static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) {
67  if (name.consume_front("MacOSX"))
68  return XcodeSDK::MacOSX;
69  if (name.consume_front("iPhoneSimulator"))
71  if (name.consume_front("iPhoneOS"))
72  return XcodeSDK::iPhoneOS;
73  if (name.consume_front("AppleTVSimulator"))
75  if (name.consume_front("AppleTVOS"))
76  return XcodeSDK::AppleTVOS;
77  if (name.consume_front("WatchSimulator"))
79  if (name.consume_front("WatchOS"))
80  return XcodeSDK::watchOS;
81  if (name.consume_front("bridgeOS"))
82  return XcodeSDK::bridgeOS;
83  if (name.consume_front("Linux"))
84  return XcodeSDK::Linux;
85  static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1,
86  "New SDK type was added, update this list!");
87  return XcodeSDK::unknown;
88 }
89 
90 static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) {
91  unsigned i = 0;
92  while (i < name.size() && name[i] >= '0' && name[i] <= '9')
93  ++i;
94  if (i == name.size() || name[i++] != '.')
95  return {};
96  while (i < name.size() && name[i] >= '0' && name[i] <= '9')
97  ++i;
98  if (i == name.size() || name[i++] != '.')
99  return {};
100 
101  llvm::VersionTuple version;
102  version.tryParse(name.slice(0, i - 1));
103  name = name.drop_front(i);
104  return version;
105 }
106 
107 static bool ParseAppleInternalSDK(llvm::StringRef &name) {
108  return name.consume_front("Internal.") || name.consume_front(".Internal.");
109 }
110 
112  XcodeSDK::Info info;
113  llvm::StringRef input(m_name);
114  info.type = ParseSDKName(input);
115  info.version = ParseSDKVersion(input);
116  info.internal = ParseAppleInternalSDK(input);
117  return info;
118 }
119 
121  llvm::StringRef input(m_name);
122  ParseSDKName(input);
123  ParseSDKVersion(input);
124  return ParseAppleInternalSDK(input);
125 }
126 
127 llvm::VersionTuple XcodeSDK::GetVersion() const {
128  llvm::StringRef input(m_name);
129  ParseSDKName(input);
130  return ParseSDKVersion(input);
131 }
132 
134  llvm::StringRef input(m_name);
135  return ParseSDKName(input);
136 }
137 
138 llvm::StringRef XcodeSDK::GetString() const { return m_name; }
139 
140 bool XcodeSDK::Info::operator<(const Info &other) const {
141  return std::tie(type, version, internal) <
142  std::tie(other.type, other.version, other.internal);
143 }
144 
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);
148 }
149 
150 void XcodeSDK::Merge(const XcodeSDK &other) {
151  // The "bigger" SDK always wins.
152  auto l = Parse();
153  auto r = other.Parse();
154  if (l < r)
155  *this = other;
156  else {
157  // The Internal flag always wins.
158  if (llvm::StringRef(m_name).endswith(".sdk"))
159  if (!l.internal && r.internal)
160  m_name =
161  m_name.substr(0, m_name.size() - 3) + std::string("Internal.sdk");
162  }
163 }
164 
166  std::string name;
167  switch (info.type) {
168  case MacOSX:
169  name = "macosx";
170  break;
171  case iPhoneSimulator:
172  name = "iphonesimulator";
173  break;
174  case iPhoneOS:
175  name = "iphoneos";
176  break;
177  case AppleTVSimulator:
178  name = "appletvsimulator";
179  break;
180  case AppleTVOS:
181  name = "appletvos";
182  break;
183  case WatchSimulator:
184  name = "watchsimulator";
185  break;
186  case watchOS:
187  name = "watchos";
188  break;
189  case bridgeOS:
190  name = "bridgeos";
191  break;
192  case Linux:
193  name = "linux";
194  break;
195  case unknown:
196  return {};
197  }
198  if (!info.version.empty())
199  name += info.version.getAsString();
200  if (info.internal)
201  name += ".internal";
202  return name;
203 }
204 
206  llvm::VersionTuple version) {
207  switch (sdk_type) {
208  case Type::MacOSX:
209  return version >= llvm::VersionTuple(10, 10);
210  case Type::iPhoneOS:
211  case Type::iPhoneSimulator:
212  case Type::AppleTVOS:
213  case Type::AppleTVSimulator:
214  return version >= llvm::VersionTuple(8);
215  case Type::watchOS:
216  case Type::WatchSimulator:
217  return version >= llvm::VersionTuple(6);
218  default:
219  return false;
220  }
221 
222  return false;
223 }
224 
226  XcodeSDK::Info info = Parse();
227  switch (info.type) {
228  case Type::MacOSX:
229  return info.version.empty() || info.version >= llvm::VersionTuple(10, 10);
230  case Type::iPhoneOS:
231  case Type::iPhoneSimulator:
232  return info.version.empty() || info.version >= llvm::VersionTuple(8);
233  case Type::AppleTVSimulator:
234  case Type::AppleTVOS:
235  return info.version.empty() || info.version >= llvm::VersionTuple(9);
236  case Type::WatchSimulator:
237  case Type::watchOS:
238  return info.version.empty() || info.version >= llvm::VersionTuple(2);
239  case Type::Linux:
240  return true;
241  default:
242  return false;
243  }
244 }
245 
247  const FileSpec &sdk_path) {
248  ConstString last_path_component = sdk_path.GetLastPathComponent();
249 
250  if (!last_path_component)
251  return false;
252 
253  XcodeSDK sdk(last_path_component.GetStringRef().str());
254  if (sdk.GetType() != desired_type)
255  return false;
256  return SDKSupportsModules(sdk.GetType(), sdk.GetVersion());
257 }
258 
259 XcodeSDK::Type XcodeSDK::GetSDKTypeForTriple(const llvm::Triple &triple) {
260  using namespace llvm;
261  switch (triple.getOS()) {
262  case Triple::MacOSX:
263  case Triple::Darwin:
264  return XcodeSDK::MacOSX;
265  case Triple::IOS:
266  switch (triple.getEnvironment()) {
267  case Triple::MacABI:
268  return XcodeSDK::MacOSX;
269  case Triple::Simulator:
271  default:
272  return XcodeSDK::iPhoneOS;
273  }
274  case Triple::TvOS:
275  if (triple.getEnvironment() == Triple::Simulator)
277  return XcodeSDK::AppleTVOS;
278  case Triple::WatchOS:
279  if (triple.getEnvironment() == Triple::Simulator)
281  return XcodeSDK::watchOS;
282  case Triple::Linux:
283  return XcodeSDK::Linux;
284  default:
285  return XcodeSDK::unknown;
286  }
287 }
288 
290  auto begin = llvm::sys::path::begin(path);
291  auto end = llvm::sys::path::end(path);
292 
293  // Iterate over the path components until we find something that ends with
294  // .app. If the next component is Contents then we've found the Contents
295  // directory.
296  for (auto it = begin; it != end; ++it) {
297  if (it->endswith(".app")) {
298  auto next = it;
299  if (++next != end && *next == "Contents") {
300  llvm::SmallString<128> buffer;
301  llvm::sys::path::append(buffer, begin, ++next,
302  llvm::sys::path::Style::posix);
303  return buffer.str().str();
304  }
305  }
306  }
307 
308  return {};
309 }
lldb_private::XcodeSDK::SupportsSwift
bool SupportsSwift() const
Whether this Xcode SDK supports Swift.
Definition: XcodeSDK.cpp:225
lldb_private::FileSpec::GetLastPathComponent
ConstString GetLastPathComponent() const
Definition: FileSpec.cpp:415
llvm
Definition: Debugger.h:49
lldb_private::XcodeSDK::AppleTVSimulator
@ AppleTVSimulator
Definition: XcodeSDK.h:33
lldb_private::XcodeSDK::GetSDKTypeForTriple
static XcodeSDK::Type GetSDKTypeForTriple(const llvm::Triple &triple)
Return the best-matching SDK type for a specific triple.
Definition: XcodeSDK.cpp:259
lldb_private::XcodeSDK::Merge
void Merge(const XcodeSDK &other)
The merge function follows a strict order to maintain monotonicity:
Definition: XcodeSDK.cpp:150
lldb_private::XcodeSDK::AppleTVOS
@ AppleTVOS
Definition: XcodeSDK.h:34
ParseSDKName
static XcodeSDK::Type ParseSDKName(llvm::StringRef &name)
Definition: XcodeSDK.cpp:66
lldb_private::XcodeSDK::MacOSX
@ MacOSX
Definition: XcodeSDK.h:30
lldb_private::XcodeSDK::iPhoneSimulator
@ iPhoneSimulator
Definition: XcodeSDK.h:31
lldb_private::XcodeSDK
An abstraction for Xcode-style SDKs that works like ArchSpec.
Definition: XcodeSDK.h:24
lldb_private::XcodeSDK::SDKSupportsModules
static bool SDKSupportsModules(Type type, llvm::VersionTuple version)
Whether LLDB feels confident importing Clang modules from this SDK.
Definition: XcodeSDK.cpp:205
lldb_private::XcodeSDK::Parse
Info Parse() const
Return parsed SDK type and version number.
Definition: XcodeSDK.cpp:111
lldb_private::XcodeSDK::GetString
llvm::StringRef GetString() const
Definition: XcodeSDK.cpp:138
lldb_private::XcodeSDK::Info
A parsed SDK directory name.
Definition: XcodeSDK.h:44
lldb_private::XcodeSDK::WatchSimulator
@ WatchSimulator
Definition: XcodeSDK.h:35
lldb_private::XcodeSDK::watchOS
@ watchOS
Definition: XcodeSDK.h:36
XcodeSDK.h
lldb_private::XcodeSDK::unknown
@ unknown
Definition: XcodeSDK.h:39
lldb_private::FileSpec
Definition: FileSpec.h:56
lldb_private::XcodeSDK::IsAppleInternalSDK
bool IsAppleInternalSDK() const
Definition: XcodeSDK.cpp:120
lldb_private::XcodeSDK::numSDKTypes
static constexpr int numSDKTypes
Definition: XcodeSDK.h:41
lldb_private::ConstString::GetStringRef
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:202
GetName
static llvm::StringRef GetName(XcodeSDK::Type type)
Definition: XcodeSDK.cpp:21
lldb_private::XcodeSDK::FindXcodeContentsDirectoryInPath
static std::string FindXcodeContentsDirectoryInPath(llvm::StringRef path)
Definition: XcodeSDK.cpp:289
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::XcodeSDK::Linux
@ Linux
Definition: XcodeSDK.h:38
lldb_private::XcodeSDK::operator=
XcodeSDK & operator=(const XcodeSDK &other)
Definition: XcodeSDK.cpp:57
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:38
lldb-types.h
ParseAppleInternalSDK
static bool ParseAppleInternalSDK(llvm::StringRef &name)
Definition: XcodeSDK.cpp:107
lldb_private::XcodeSDK::GetVersion
llvm::VersionTuple GetVersion() const
Definition: XcodeSDK.cpp:127
lldb_private::XcodeSDK::bridgeOS
@ bridgeOS
Definition: XcodeSDK.h:37
lldb_private::XcodeSDK::Info::version
llvm::VersionTuple version
Definition: XcodeSDK.h:46
lldb_private::XcodeSDK::operator==
bool operator==(const XcodeSDK &other)
Definition: XcodeSDK.cpp:62
lldb_private::XcodeSDK::Type
Type
Different types of Xcode SDKs.
Definition: XcodeSDK.h:29
lldb_private::XcodeSDK::Info::operator<
bool operator<(const Info &other) const
Definition: XcodeSDK.cpp:140
lldb_private::XcodeSDK::GetCanonicalName
static std::string GetCanonicalName(Info info)
Return the canonical SDK name, such as "macosx" for the macOS SDK.
Definition: XcodeSDK.cpp:165
lldb_private::XcodeSDK::m_name
std::string m_name
Definition: XcodeSDK.h:25
lldb_private::XcodeSDK::Info::type
Type type
Definition: XcodeSDK.h:45
lldb_private::XcodeSDK::Info::operator==
bool operator==(const Info &other) const
Definition: XcodeSDK.cpp:145
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
FileSpec.h
lldb_private::XcodeSDK::GetType
Type GetType() const
Definition: XcodeSDK.cpp:133
ParseSDKVersion
static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name)
Definition: XcodeSDK.cpp:90
lldb
Definition: SBAddress.h:15
lldb_private::XcodeSDK::iPhoneOS
@ iPhoneOS
Definition: XcodeSDK.h:32
lldb_private::XcodeSDK::Info::internal
bool internal
Definition: XcodeSDK.h:47