11e05d7b3SAdrian Prantl //===-- XcodeSDK.cpp ------------------------------------------------------===//
21e05d7b3SAdrian Prantl //
31e05d7b3SAdrian Prantl // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41e05d7b3SAdrian Prantl // See https://llvm.org/LICENSE.txt for license information.
51e05d7b3SAdrian Prantl // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61e05d7b3SAdrian Prantl //
71e05d7b3SAdrian Prantl //===----------------------------------------------------------------------===//
81e05d7b3SAdrian Prantl 
91e05d7b3SAdrian Prantl #include "lldb/Utility/XcodeSDK.h"
106e95d51eSAdrian Prantl #include "lldb/Utility/FileSpec.h"
111e05d7b3SAdrian Prantl 
121e05d7b3SAdrian Prantl #include "lldb/lldb-types.h"
136e95d51eSAdrian Prantl 
146e95d51eSAdrian Prantl #include "llvm/ADT/Triple.h"
156e95d51eSAdrian Prantl 
166a9edce2SEric Christopher #include <string>
171e05d7b3SAdrian Prantl 
181e05d7b3SAdrian Prantl using namespace lldb;
191e05d7b3SAdrian Prantl using namespace lldb_private;
201e05d7b3SAdrian Prantl 
211e05d7b3SAdrian Prantl XcodeSDK &XcodeSDK::operator=(XcodeSDK other) {
221e05d7b3SAdrian Prantl   m_name = other.m_name;
231e05d7b3SAdrian Prantl   return *this;
241e05d7b3SAdrian Prantl }
251e05d7b3SAdrian Prantl 
261e05d7b3SAdrian Prantl bool XcodeSDK::operator==(XcodeSDK other) {
271e05d7b3SAdrian Prantl   return m_name == other.m_name;
281e05d7b3SAdrian Prantl }
291e05d7b3SAdrian Prantl 
301e05d7b3SAdrian Prantl static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) {
311e05d7b3SAdrian Prantl   if (name.consume_front("MacOSX"))
321e05d7b3SAdrian Prantl     return XcodeSDK::MacOSX;
331e05d7b3SAdrian Prantl   if (name.consume_front("iPhoneSimulator"))
341e05d7b3SAdrian Prantl     return XcodeSDK::iPhoneSimulator;
351e05d7b3SAdrian Prantl   if (name.consume_front("iPhoneOS"))
361e05d7b3SAdrian Prantl     return XcodeSDK::iPhoneOS;
371e05d7b3SAdrian Prantl   if (name.consume_front("AppleTVSimulator"))
381e05d7b3SAdrian Prantl     return XcodeSDK::AppleTVSimulator;
391e05d7b3SAdrian Prantl   if (name.consume_front("AppleTVOS"))
401e05d7b3SAdrian Prantl     return XcodeSDK::AppleTVOS;
411e05d7b3SAdrian Prantl   if (name.consume_front("WatchSimulator"))
421e05d7b3SAdrian Prantl     return XcodeSDK::WatchSimulator;
431e05d7b3SAdrian Prantl   if (name.consume_front("WatchOS"))
441e05d7b3SAdrian Prantl     return XcodeSDK::watchOS;
451e05d7b3SAdrian Prantl   if (name.consume_front("bridgeOS"))
461e05d7b3SAdrian Prantl     return XcodeSDK::bridgeOS;
471e05d7b3SAdrian Prantl   if (name.consume_front("Linux"))
481e05d7b3SAdrian Prantl     return XcodeSDK::Linux;
491e05d7b3SAdrian Prantl   static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1,
501e05d7b3SAdrian Prantl                 "New SDK type was added, update this list!");
511e05d7b3SAdrian Prantl   return XcodeSDK::unknown;
521e05d7b3SAdrian Prantl }
531e05d7b3SAdrian Prantl 
541e05d7b3SAdrian Prantl static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) {
551e05d7b3SAdrian Prantl   unsigned i = 0;
561e05d7b3SAdrian Prantl   while (i < name.size() && name[i] >= '0' && name[i] <= '9')
571e05d7b3SAdrian Prantl     ++i;
581e05d7b3SAdrian Prantl   if (i == name.size() || name[i++] != '.')
591e05d7b3SAdrian Prantl     return {};
601e05d7b3SAdrian Prantl   while (i < name.size() && name[i] >= '0' && name[i] <= '9')
611e05d7b3SAdrian Prantl     ++i;
621e05d7b3SAdrian Prantl   if (i == name.size() || name[i++] != '.')
631e05d7b3SAdrian Prantl     return {};
641e05d7b3SAdrian Prantl 
651e05d7b3SAdrian Prantl   llvm::VersionTuple version;
661e05d7b3SAdrian Prantl   version.tryParse(name.slice(0, i - 1));
671e05d7b3SAdrian Prantl   name = name.drop_front(i);
681e05d7b3SAdrian Prantl   return version;
691e05d7b3SAdrian Prantl }
701e05d7b3SAdrian Prantl 
7179feafa5SAdrian Prantl static bool ParseAppleInternalSDK(llvm::StringRef &name) {
7279feafa5SAdrian Prantl   return name.consume_front("Internal.");
7379feafa5SAdrian Prantl }
741e05d7b3SAdrian Prantl 
7579feafa5SAdrian Prantl XcodeSDK::Info XcodeSDK::Parse() const {
7679feafa5SAdrian Prantl   XcodeSDK::Info info;
771e05d7b3SAdrian Prantl   llvm::StringRef input(m_name);
7879feafa5SAdrian Prantl   info.type = ParseSDKName(input);
7979feafa5SAdrian Prantl   info.version = ParseSDKVersion(input);
8079feafa5SAdrian Prantl   info.internal = ParseAppleInternalSDK(input);
8179feafa5SAdrian Prantl   return info;
8279feafa5SAdrian Prantl }
8379feafa5SAdrian Prantl 
8479feafa5SAdrian Prantl bool XcodeSDK::IsAppleInternalSDK() const {
8579feafa5SAdrian Prantl   llvm::StringRef input(m_name);
8679feafa5SAdrian Prantl   ParseSDKName(input);
8779feafa5SAdrian Prantl   ParseSDKVersion(input);
8879feafa5SAdrian Prantl   return ParseAppleInternalSDK(input);
891e05d7b3SAdrian Prantl }
901e05d7b3SAdrian Prantl 
911e05d7b3SAdrian Prantl llvm::VersionTuple XcodeSDK::GetVersion() const {
921e05d7b3SAdrian Prantl   llvm::StringRef input(m_name);
931e05d7b3SAdrian Prantl   ParseSDKName(input);
941e05d7b3SAdrian Prantl   return ParseSDKVersion(input);
951e05d7b3SAdrian Prantl }
961e05d7b3SAdrian Prantl 
971e05d7b3SAdrian Prantl XcodeSDK::Type XcodeSDK::GetType() const {
981e05d7b3SAdrian Prantl   llvm::StringRef input(m_name);
991e05d7b3SAdrian Prantl   return ParseSDKName(input);
1001e05d7b3SAdrian Prantl }
1011e05d7b3SAdrian Prantl 
1021e05d7b3SAdrian Prantl llvm::StringRef XcodeSDK::GetString() const { return m_name; }
1031e05d7b3SAdrian Prantl 
10479feafa5SAdrian Prantl bool XcodeSDK::Info::operator<(const Info &other) const {
10579feafa5SAdrian Prantl   return std::tie(type, version, internal) <
10679feafa5SAdrian Prantl          std::tie(other.type, other.version, other.internal);
10779feafa5SAdrian Prantl }
1081e05d7b3SAdrian Prantl void XcodeSDK::Merge(XcodeSDK other) {
1091e05d7b3SAdrian Prantl   // The "bigger" SDK always wins.
11079feafa5SAdrian Prantl   auto l = Parse();
11179feafa5SAdrian Prantl   auto r = other.Parse();
11279feafa5SAdrian Prantl   if (l < r)
1131e05d7b3SAdrian Prantl     *this = other;
11479feafa5SAdrian Prantl   else {
11579feafa5SAdrian Prantl     // The Internal flag always wins.
11679feafa5SAdrian Prantl     if (llvm::StringRef(m_name).endswith(".sdk"))
11779feafa5SAdrian Prantl       if (!l.internal && r.internal)
11879feafa5SAdrian Prantl         m_name =
11979feafa5SAdrian Prantl             m_name.substr(0, m_name.size() - 3) + std::string("Internal.sdk");
12079feafa5SAdrian Prantl   }
1211e05d7b3SAdrian Prantl }
1221e05d7b3SAdrian Prantl 
12379feafa5SAdrian Prantl std::string XcodeSDK::GetCanonicalName(XcodeSDK::Info info) {
12479feafa5SAdrian Prantl   std::string name;
12579feafa5SAdrian Prantl   switch (info.type) {
1261e05d7b3SAdrian Prantl   case MacOSX:
12779feafa5SAdrian Prantl     name = "macosx";
12879feafa5SAdrian Prantl     break;
1291e05d7b3SAdrian Prantl   case iPhoneSimulator:
13079feafa5SAdrian Prantl     name = "iphonesimulator";
13179feafa5SAdrian Prantl     break;
1321e05d7b3SAdrian Prantl   case iPhoneOS:
13379feafa5SAdrian Prantl     name = "iphoneos";
13479feafa5SAdrian Prantl     break;
1351e05d7b3SAdrian Prantl   case AppleTVSimulator:
13679feafa5SAdrian Prantl     name = "appletvsimulator";
13779feafa5SAdrian Prantl     break;
1381e05d7b3SAdrian Prantl   case AppleTVOS:
13979feafa5SAdrian Prantl     name = "appletvos";
14079feafa5SAdrian Prantl     break;
1411e05d7b3SAdrian Prantl   case WatchSimulator:
14279feafa5SAdrian Prantl     name = "watchsimulator";
14379feafa5SAdrian Prantl     break;
1441e05d7b3SAdrian Prantl   case watchOS:
14579feafa5SAdrian Prantl     name = "watchos";
14679feafa5SAdrian Prantl     break;
1471e05d7b3SAdrian Prantl   case bridgeOS:
14879feafa5SAdrian Prantl     name = "bridgeos";
14979feafa5SAdrian Prantl     break;
1501e05d7b3SAdrian Prantl   case Linux:
15179feafa5SAdrian Prantl     name = "linux";
15279feafa5SAdrian Prantl     break;
1531e05d7b3SAdrian Prantl   case numSDKTypes:
1541e05d7b3SAdrian Prantl   case unknown:
15579feafa5SAdrian Prantl     return {};
1561e05d7b3SAdrian Prantl   }
15779feafa5SAdrian Prantl   if (!info.version.empty())
15879feafa5SAdrian Prantl     name += info.version.getAsString();
15979feafa5SAdrian Prantl   if (info.internal)
16079feafa5SAdrian Prantl     name += ".internal";
16179feafa5SAdrian Prantl   return name;
1621e05d7b3SAdrian Prantl }
1631e05d7b3SAdrian Prantl 
1641e05d7b3SAdrian Prantl bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type sdk_type,
1651e05d7b3SAdrian Prantl                                   llvm::VersionTuple version) {
1661e05d7b3SAdrian Prantl   switch (sdk_type) {
1671e05d7b3SAdrian Prantl   case Type::MacOSX:
1681e05d7b3SAdrian Prantl     return version >= llvm::VersionTuple(10, 10);
1691e05d7b3SAdrian Prantl   case Type::iPhoneOS:
1701e05d7b3SAdrian Prantl   case Type::iPhoneSimulator:
1711e05d7b3SAdrian Prantl   case Type::AppleTVOS:
1721e05d7b3SAdrian Prantl   case Type::AppleTVSimulator:
1731e05d7b3SAdrian Prantl     return version >= llvm::VersionTuple(8);
1741e05d7b3SAdrian Prantl   case Type::watchOS:
1751e05d7b3SAdrian Prantl   case Type::WatchSimulator:
1761e05d7b3SAdrian Prantl     return version >= llvm::VersionTuple(6);
1771e05d7b3SAdrian Prantl   default:
1781e05d7b3SAdrian Prantl     return false;
1791e05d7b3SAdrian Prantl   }
1801e05d7b3SAdrian Prantl 
1811e05d7b3SAdrian Prantl   return false;
1821e05d7b3SAdrian Prantl }
1831e05d7b3SAdrian Prantl 
184*dec1c94eSAdrian Prantl bool XcodeSDK::SupportsSwift() const {
185*dec1c94eSAdrian Prantl   XcodeSDK::Info info = Parse();
186*dec1c94eSAdrian Prantl   switch (info.type) {
187*dec1c94eSAdrian Prantl   case Type::MacOSX:
188*dec1c94eSAdrian Prantl     return info.version.empty() || info.version >= llvm::VersionTuple(10, 10);
189*dec1c94eSAdrian Prantl   case Type::iPhoneOS:
190*dec1c94eSAdrian Prantl   case Type::iPhoneSimulator:
191*dec1c94eSAdrian Prantl     return info.version.empty() || info.version >= llvm::VersionTuple(8);
192*dec1c94eSAdrian Prantl   case Type::AppleTVSimulator:
193*dec1c94eSAdrian Prantl   case Type::AppleTVOS:
194*dec1c94eSAdrian Prantl     return info.version.empty() || info.version >= llvm::VersionTuple(9);
195*dec1c94eSAdrian Prantl   case Type::WatchSimulator:
196*dec1c94eSAdrian Prantl   case Type::watchOS:
197*dec1c94eSAdrian Prantl     return info.version.empty() || info.version >= llvm::VersionTuple(2);
198*dec1c94eSAdrian Prantl   case Type::Linux:
199*dec1c94eSAdrian Prantl     return true;
200*dec1c94eSAdrian Prantl   default:
201*dec1c94eSAdrian Prantl     return false;
202*dec1c94eSAdrian Prantl   }
203*dec1c94eSAdrian Prantl }
204*dec1c94eSAdrian Prantl 
2051e05d7b3SAdrian Prantl bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type desired_type,
2061e05d7b3SAdrian Prantl                                   const FileSpec &sdk_path) {
2071e05d7b3SAdrian Prantl   ConstString last_path_component = sdk_path.GetLastPathComponent();
2081e05d7b3SAdrian Prantl 
2094356aa20SAdrian Prantl   if (!last_path_component)
2101e05d7b3SAdrian Prantl     return false;
2111e05d7b3SAdrian Prantl 
2124356aa20SAdrian Prantl   XcodeSDK sdk(last_path_component.GetStringRef().str());
2134356aa20SAdrian Prantl   if (sdk.GetType() != desired_type)
2141e05d7b3SAdrian Prantl     return false;
2154356aa20SAdrian Prantl   return SDKSupportsModules(sdk.GetType(), sdk.GetVersion());
2161e05d7b3SAdrian Prantl }
2176e95d51eSAdrian Prantl 
2186e95d51eSAdrian Prantl XcodeSDK::Type XcodeSDK::GetSDKTypeForTriple(const llvm::Triple &triple) {
2196e95d51eSAdrian Prantl   using namespace llvm;
2206e95d51eSAdrian Prantl   switch (triple.getOS()) {
2216e95d51eSAdrian Prantl   case Triple::MacOSX:
2226e95d51eSAdrian Prantl   case Triple::Darwin:
2236e95d51eSAdrian Prantl     return XcodeSDK::MacOSX;
2246e95d51eSAdrian Prantl   case Triple::IOS:
2256e95d51eSAdrian Prantl     switch (triple.getEnvironment()) {
2266e95d51eSAdrian Prantl     case Triple::MacABI:
2276e95d51eSAdrian Prantl       return XcodeSDK::MacOSX;
2286e95d51eSAdrian Prantl     case Triple::Simulator:
2296e95d51eSAdrian Prantl       return XcodeSDK::iPhoneSimulator;
2306e95d51eSAdrian Prantl     default:
2316e95d51eSAdrian Prantl       return XcodeSDK::iPhoneOS;
2326e95d51eSAdrian Prantl     }
2336e95d51eSAdrian Prantl   case Triple::TvOS:
2346e95d51eSAdrian Prantl     if (triple.getEnvironment() == Triple::Simulator)
2356e95d51eSAdrian Prantl       return XcodeSDK::AppleTVSimulator;
2366e95d51eSAdrian Prantl     return XcodeSDK::AppleTVOS;
2376e95d51eSAdrian Prantl   case Triple::WatchOS:
2386e95d51eSAdrian Prantl     if (triple.getEnvironment() == Triple::Simulator)
2396e95d51eSAdrian Prantl       return XcodeSDK::WatchSimulator;
2406e95d51eSAdrian Prantl     return XcodeSDK::watchOS;
2416e95d51eSAdrian Prantl   case Triple::Linux:
2426e95d51eSAdrian Prantl     return XcodeSDK::Linux;
2436e95d51eSAdrian Prantl   default:
2446e95d51eSAdrian Prantl     return XcodeSDK::unknown;
2456e95d51eSAdrian Prantl   }
2466e95d51eSAdrian Prantl }
247