xref: /freebsd-src/contrib/llvm-project/lldb/source/Utility/XcodeSDK.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
15ffd83dbSDimitry Andric //===-- XcodeSDK.cpp ------------------------------------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric #include "lldb/Utility/XcodeSDK.h"
105ffd83dbSDimitry Andric #include "lldb/Utility/FileSpec.h"
115ffd83dbSDimitry Andric 
125ffd83dbSDimitry Andric #include "lldb/lldb-types.h"
135ffd83dbSDimitry Andric 
1406c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
155ffd83dbSDimitry Andric 
165ffd83dbSDimitry Andric #include <string>
175ffd83dbSDimitry Andric 
185ffd83dbSDimitry Andric using namespace lldb;
195ffd83dbSDimitry Andric using namespace lldb_private;
205ffd83dbSDimitry Andric 
GetName(XcodeSDK::Type type)215ffd83dbSDimitry Andric static llvm::StringRef GetName(XcodeSDK::Type type) {
225ffd83dbSDimitry Andric   switch (type) {
235ffd83dbSDimitry Andric   case XcodeSDK::MacOSX:
245ffd83dbSDimitry Andric     return "MacOSX";
255ffd83dbSDimitry Andric   case XcodeSDK::iPhoneSimulator:
265ffd83dbSDimitry Andric     return "iPhoneSimulator";
275ffd83dbSDimitry Andric   case XcodeSDK::iPhoneOS:
285ffd83dbSDimitry Andric     return "iPhoneOS";
295ffd83dbSDimitry Andric   case XcodeSDK::AppleTVSimulator:
305ffd83dbSDimitry Andric     return "AppleTVSimulator";
315ffd83dbSDimitry Andric   case XcodeSDK::AppleTVOS:
325ffd83dbSDimitry Andric     return "AppleTVOS";
335ffd83dbSDimitry Andric   case XcodeSDK::WatchSimulator:
345ffd83dbSDimitry Andric     return "WatchSimulator";
355ffd83dbSDimitry Andric   case XcodeSDK::watchOS:
365ffd83dbSDimitry Andric     return "WatchOS";
37*7a6dacacSDimitry Andric   case XcodeSDK::XRSimulator:
38*7a6dacacSDimitry Andric     return "XRSimulator";
39*7a6dacacSDimitry Andric   case XcodeSDK::XROS:
40*7a6dacacSDimitry Andric     return "XROS";
415ffd83dbSDimitry Andric   case XcodeSDK::bridgeOS:
425ffd83dbSDimitry Andric     return "bridgeOS";
435ffd83dbSDimitry Andric   case XcodeSDK::Linux:
445ffd83dbSDimitry Andric     return "Linux";
455ffd83dbSDimitry Andric   case XcodeSDK::unknown:
465ffd83dbSDimitry Andric     return {};
475ffd83dbSDimitry Andric   }
485ffd83dbSDimitry Andric   llvm_unreachable("Unhandled sdk type!");
495ffd83dbSDimitry Andric }
505ffd83dbSDimitry Andric 
XcodeSDK(XcodeSDK::Info info)515ffd83dbSDimitry Andric XcodeSDK::XcodeSDK(XcodeSDK::Info info) : m_name(GetName(info.type).str()) {
525ffd83dbSDimitry Andric   if (!m_name.empty()) {
535ffd83dbSDimitry Andric     if (!info.version.empty())
545ffd83dbSDimitry Andric       m_name += info.version.getAsString();
555ffd83dbSDimitry Andric     if (info.internal)
565ffd83dbSDimitry Andric       m_name += ".Internal";
575ffd83dbSDimitry Andric     m_name += ".sdk";
585ffd83dbSDimitry Andric   }
595ffd83dbSDimitry Andric }
605ffd83dbSDimitry Andric 
6181ad6265SDimitry Andric XcodeSDK &XcodeSDK::operator=(const XcodeSDK &other) = default;
625ffd83dbSDimitry Andric 
operator ==(const XcodeSDK & other) const635f757f3fSDimitry Andric bool XcodeSDK::operator==(const XcodeSDK &other) const {
645ffd83dbSDimitry Andric   return m_name == other.m_name;
655ffd83dbSDimitry Andric }
665ffd83dbSDimitry Andric 
ParseSDKName(llvm::StringRef & name)675ffd83dbSDimitry Andric static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) {
685ffd83dbSDimitry Andric   if (name.consume_front("MacOSX"))
695ffd83dbSDimitry Andric     return XcodeSDK::MacOSX;
705ffd83dbSDimitry Andric   if (name.consume_front("iPhoneSimulator"))
715ffd83dbSDimitry Andric     return XcodeSDK::iPhoneSimulator;
725ffd83dbSDimitry Andric   if (name.consume_front("iPhoneOS"))
735ffd83dbSDimitry Andric     return XcodeSDK::iPhoneOS;
745ffd83dbSDimitry Andric   if (name.consume_front("AppleTVSimulator"))
755ffd83dbSDimitry Andric     return XcodeSDK::AppleTVSimulator;
765ffd83dbSDimitry Andric   if (name.consume_front("AppleTVOS"))
775ffd83dbSDimitry Andric     return XcodeSDK::AppleTVOS;
785ffd83dbSDimitry Andric   if (name.consume_front("WatchSimulator"))
795ffd83dbSDimitry Andric     return XcodeSDK::WatchSimulator;
805ffd83dbSDimitry Andric   if (name.consume_front("WatchOS"))
815ffd83dbSDimitry Andric     return XcodeSDK::watchOS;
82*7a6dacacSDimitry Andric   if (name.consume_front("XRSimulator"))
83*7a6dacacSDimitry Andric     return XcodeSDK::XRSimulator;
84*7a6dacacSDimitry Andric   if (name.consume_front("XROS"))
85*7a6dacacSDimitry Andric     return XcodeSDK::XROS;
865ffd83dbSDimitry Andric   if (name.consume_front("bridgeOS"))
875ffd83dbSDimitry Andric     return XcodeSDK::bridgeOS;
885ffd83dbSDimitry Andric   if (name.consume_front("Linux"))
895ffd83dbSDimitry Andric     return XcodeSDK::Linux;
905ffd83dbSDimitry Andric   static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1,
915ffd83dbSDimitry Andric                 "New SDK type was added, update this list!");
925ffd83dbSDimitry Andric   return XcodeSDK::unknown;
935ffd83dbSDimitry Andric }
945ffd83dbSDimitry Andric 
ParseSDKVersion(llvm::StringRef & name)955ffd83dbSDimitry Andric static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) {
965ffd83dbSDimitry Andric   unsigned i = 0;
975ffd83dbSDimitry Andric   while (i < name.size() && name[i] >= '0' && name[i] <= '9')
985ffd83dbSDimitry Andric     ++i;
995ffd83dbSDimitry Andric   if (i == name.size() || name[i++] != '.')
1005ffd83dbSDimitry Andric     return {};
1015ffd83dbSDimitry Andric   while (i < name.size() && name[i] >= '0' && name[i] <= '9')
1025ffd83dbSDimitry Andric     ++i;
1035ffd83dbSDimitry Andric   if (i == name.size() || name[i++] != '.')
1045ffd83dbSDimitry Andric     return {};
1055ffd83dbSDimitry Andric 
1065ffd83dbSDimitry Andric   llvm::VersionTuple version;
1075ffd83dbSDimitry Andric   version.tryParse(name.slice(0, i - 1));
1085ffd83dbSDimitry Andric   name = name.drop_front(i);
1095ffd83dbSDimitry Andric   return version;
1105ffd83dbSDimitry Andric }
1115ffd83dbSDimitry Andric 
ParseAppleInternalSDK(llvm::StringRef & name)1125ffd83dbSDimitry Andric static bool ParseAppleInternalSDK(llvm::StringRef &name) {
1135ffd83dbSDimitry Andric   return name.consume_front("Internal.") || name.consume_front(".Internal.");
1145ffd83dbSDimitry Andric }
1155ffd83dbSDimitry Andric 
Parse() const1165ffd83dbSDimitry Andric XcodeSDK::Info XcodeSDK::Parse() const {
1175ffd83dbSDimitry Andric   XcodeSDK::Info info;
1185ffd83dbSDimitry Andric   llvm::StringRef input(m_name);
1195ffd83dbSDimitry Andric   info.type = ParseSDKName(input);
1205ffd83dbSDimitry Andric   info.version = ParseSDKVersion(input);
1215ffd83dbSDimitry Andric   info.internal = ParseAppleInternalSDK(input);
1225ffd83dbSDimitry Andric   return info;
1235ffd83dbSDimitry Andric }
1245ffd83dbSDimitry Andric 
IsAppleInternalSDK() const1255ffd83dbSDimitry Andric bool XcodeSDK::IsAppleInternalSDK() const {
1265ffd83dbSDimitry Andric   llvm::StringRef input(m_name);
1275ffd83dbSDimitry Andric   ParseSDKName(input);
1285ffd83dbSDimitry Andric   ParseSDKVersion(input);
1295ffd83dbSDimitry Andric   return ParseAppleInternalSDK(input);
1305ffd83dbSDimitry Andric }
1315ffd83dbSDimitry Andric 
GetVersion() const1325ffd83dbSDimitry Andric llvm::VersionTuple XcodeSDK::GetVersion() const {
1335ffd83dbSDimitry Andric   llvm::StringRef input(m_name);
1345ffd83dbSDimitry Andric   ParseSDKName(input);
1355ffd83dbSDimitry Andric   return ParseSDKVersion(input);
1365ffd83dbSDimitry Andric }
1375ffd83dbSDimitry Andric 
GetType() const1385ffd83dbSDimitry Andric XcodeSDK::Type XcodeSDK::GetType() const {
1395ffd83dbSDimitry Andric   llvm::StringRef input(m_name);
1405ffd83dbSDimitry Andric   return ParseSDKName(input);
1415ffd83dbSDimitry Andric }
1425ffd83dbSDimitry Andric 
GetString() const1435ffd83dbSDimitry Andric llvm::StringRef XcodeSDK::GetString() const { return m_name; }
1445ffd83dbSDimitry Andric 
operator <(const Info & other) const1455ffd83dbSDimitry Andric bool XcodeSDK::Info::operator<(const Info &other) const {
1465ffd83dbSDimitry Andric   return std::tie(type, version, internal) <
1475ffd83dbSDimitry Andric          std::tie(other.type, other.version, other.internal);
1485ffd83dbSDimitry Andric }
1495ffd83dbSDimitry Andric 
operator ==(const Info & other) const1505ffd83dbSDimitry Andric bool XcodeSDK::Info::operator==(const Info &other) const {
1515ffd83dbSDimitry Andric   return std::tie(type, version, internal) ==
1525ffd83dbSDimitry Andric          std::tie(other.type, other.version, other.internal);
1535ffd83dbSDimitry Andric }
1545ffd83dbSDimitry Andric 
Merge(const XcodeSDK & other)155e8d8bef9SDimitry Andric void XcodeSDK::Merge(const XcodeSDK &other) {
1565ffd83dbSDimitry Andric   // The "bigger" SDK always wins.
1575ffd83dbSDimitry Andric   auto l = Parse();
1585ffd83dbSDimitry Andric   auto r = other.Parse();
1595ffd83dbSDimitry Andric   if (l < r)
1605ffd83dbSDimitry Andric     *this = other;
1615ffd83dbSDimitry Andric   else {
1625ffd83dbSDimitry Andric     // The Internal flag always wins.
1635f757f3fSDimitry Andric     if (llvm::StringRef(m_name).ends_with(".sdk"))
1645ffd83dbSDimitry Andric       if (!l.internal && r.internal)
1655ffd83dbSDimitry Andric         m_name =
1665ffd83dbSDimitry Andric             m_name.substr(0, m_name.size() - 3) + std::string("Internal.sdk");
1675ffd83dbSDimitry Andric   }
1685ffd83dbSDimitry Andric }
1695ffd83dbSDimitry Andric 
GetCanonicalName(XcodeSDK::Info info)1705ffd83dbSDimitry Andric std::string XcodeSDK::GetCanonicalName(XcodeSDK::Info info) {
1715ffd83dbSDimitry Andric   std::string name;
1725ffd83dbSDimitry Andric   switch (info.type) {
1735ffd83dbSDimitry Andric   case MacOSX:
1745ffd83dbSDimitry Andric     name = "macosx";
1755ffd83dbSDimitry Andric     break;
1765ffd83dbSDimitry Andric   case iPhoneSimulator:
1775ffd83dbSDimitry Andric     name = "iphonesimulator";
1785ffd83dbSDimitry Andric     break;
1795ffd83dbSDimitry Andric   case iPhoneOS:
1805ffd83dbSDimitry Andric     name = "iphoneos";
1815ffd83dbSDimitry Andric     break;
1825ffd83dbSDimitry Andric   case AppleTVSimulator:
1835ffd83dbSDimitry Andric     name = "appletvsimulator";
1845ffd83dbSDimitry Andric     break;
1855ffd83dbSDimitry Andric   case AppleTVOS:
1865ffd83dbSDimitry Andric     name = "appletvos";
1875ffd83dbSDimitry Andric     break;
1885ffd83dbSDimitry Andric   case WatchSimulator:
1895ffd83dbSDimitry Andric     name = "watchsimulator";
1905ffd83dbSDimitry Andric     break;
1915ffd83dbSDimitry Andric   case watchOS:
1925ffd83dbSDimitry Andric     name = "watchos";
1935ffd83dbSDimitry Andric     break;
194*7a6dacacSDimitry Andric   case XRSimulator:
195*7a6dacacSDimitry Andric     name = "xrsimulator";
196*7a6dacacSDimitry Andric     break;
197*7a6dacacSDimitry Andric   case XROS:
198*7a6dacacSDimitry Andric     name = "xros";
199*7a6dacacSDimitry Andric     break;
2005ffd83dbSDimitry Andric   case bridgeOS:
2015ffd83dbSDimitry Andric     name = "bridgeos";
2025ffd83dbSDimitry Andric     break;
2035ffd83dbSDimitry Andric   case Linux:
2045ffd83dbSDimitry Andric     name = "linux";
2055ffd83dbSDimitry Andric     break;
2065ffd83dbSDimitry Andric   case unknown:
2075ffd83dbSDimitry Andric     return {};
2085ffd83dbSDimitry Andric   }
2095ffd83dbSDimitry Andric   if (!info.version.empty())
2105ffd83dbSDimitry Andric     name += info.version.getAsString();
2115ffd83dbSDimitry Andric   if (info.internal)
2125ffd83dbSDimitry Andric     name += ".internal";
2135ffd83dbSDimitry Andric   return name;
2145ffd83dbSDimitry Andric }
2155ffd83dbSDimitry Andric 
SDKSupportsModules(XcodeSDK::Type sdk_type,llvm::VersionTuple version)2165ffd83dbSDimitry Andric bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type sdk_type,
2175ffd83dbSDimitry Andric                                   llvm::VersionTuple version) {
2185ffd83dbSDimitry Andric   switch (sdk_type) {
2195ffd83dbSDimitry Andric   case Type::MacOSX:
2205ffd83dbSDimitry Andric     return version >= llvm::VersionTuple(10, 10);
2215ffd83dbSDimitry Andric   case Type::iPhoneOS:
2225ffd83dbSDimitry Andric   case Type::iPhoneSimulator:
2235ffd83dbSDimitry Andric   case Type::AppleTVOS:
2245ffd83dbSDimitry Andric   case Type::AppleTVSimulator:
2255ffd83dbSDimitry Andric     return version >= llvm::VersionTuple(8);
2265ffd83dbSDimitry Andric   case Type::watchOS:
2275ffd83dbSDimitry Andric   case Type::WatchSimulator:
2285ffd83dbSDimitry Andric     return version >= llvm::VersionTuple(6);
229*7a6dacacSDimitry Andric   case Type::XROS:
230*7a6dacacSDimitry Andric   case Type::XRSimulator:
231*7a6dacacSDimitry Andric     return true;
2325ffd83dbSDimitry Andric   default:
2335ffd83dbSDimitry Andric     return false;
2345ffd83dbSDimitry Andric   }
2355ffd83dbSDimitry Andric 
2365ffd83dbSDimitry Andric   return false;
2375ffd83dbSDimitry Andric }
2385ffd83dbSDimitry Andric 
SupportsSwift() const2395ffd83dbSDimitry Andric bool XcodeSDK::SupportsSwift() const {
2405ffd83dbSDimitry Andric   XcodeSDK::Info info = Parse();
2415ffd83dbSDimitry Andric   switch (info.type) {
2425ffd83dbSDimitry Andric   case Type::MacOSX:
2435ffd83dbSDimitry Andric     return info.version.empty() || info.version >= llvm::VersionTuple(10, 10);
2445ffd83dbSDimitry Andric   case Type::iPhoneOS:
2455ffd83dbSDimitry Andric   case Type::iPhoneSimulator:
2465ffd83dbSDimitry Andric     return info.version.empty() || info.version >= llvm::VersionTuple(8);
2475ffd83dbSDimitry Andric   case Type::AppleTVSimulator:
2485ffd83dbSDimitry Andric   case Type::AppleTVOS:
2495ffd83dbSDimitry Andric     return info.version.empty() || info.version >= llvm::VersionTuple(9);
2505ffd83dbSDimitry Andric   case Type::WatchSimulator:
2515ffd83dbSDimitry Andric   case Type::watchOS:
2525ffd83dbSDimitry Andric     return info.version.empty() || info.version >= llvm::VersionTuple(2);
253*7a6dacacSDimitry Andric   case Type::XROS:
254*7a6dacacSDimitry Andric   case Type::XRSimulator:
2555ffd83dbSDimitry Andric   case Type::Linux:
2565ffd83dbSDimitry Andric     return true;
2575ffd83dbSDimitry Andric   default:
2585ffd83dbSDimitry Andric     return false;
2595ffd83dbSDimitry Andric   }
2605ffd83dbSDimitry Andric }
2615ffd83dbSDimitry Andric 
SDKSupportsModules(XcodeSDK::Type desired_type,const FileSpec & sdk_path)2625ffd83dbSDimitry Andric bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type desired_type,
2635ffd83dbSDimitry Andric                                   const FileSpec &sdk_path) {
26406c3fb27SDimitry Andric   ConstString last_path_component = sdk_path.GetFilename();
2655ffd83dbSDimitry Andric 
2665ffd83dbSDimitry Andric   if (!last_path_component)
2675ffd83dbSDimitry Andric     return false;
2685ffd83dbSDimitry Andric 
2695ffd83dbSDimitry Andric   XcodeSDK sdk(last_path_component.GetStringRef().str());
2705ffd83dbSDimitry Andric   if (sdk.GetType() != desired_type)
2715ffd83dbSDimitry Andric     return false;
2725ffd83dbSDimitry Andric   return SDKSupportsModules(sdk.GetType(), sdk.GetVersion());
2735ffd83dbSDimitry Andric }
2745ffd83dbSDimitry Andric 
GetSDKTypeForTriple(const llvm::Triple & triple)2755ffd83dbSDimitry Andric XcodeSDK::Type XcodeSDK::GetSDKTypeForTriple(const llvm::Triple &triple) {
2765ffd83dbSDimitry Andric   using namespace llvm;
2775ffd83dbSDimitry Andric   switch (triple.getOS()) {
2785ffd83dbSDimitry Andric   case Triple::MacOSX:
2795ffd83dbSDimitry Andric   case Triple::Darwin:
2805ffd83dbSDimitry Andric     return XcodeSDK::MacOSX;
2815ffd83dbSDimitry Andric   case Triple::IOS:
2825ffd83dbSDimitry Andric     switch (triple.getEnvironment()) {
2835ffd83dbSDimitry Andric     case Triple::MacABI:
2845ffd83dbSDimitry Andric       return XcodeSDK::MacOSX;
2855ffd83dbSDimitry Andric     case Triple::Simulator:
2865ffd83dbSDimitry Andric       return XcodeSDK::iPhoneSimulator;
2875ffd83dbSDimitry Andric     default:
2885ffd83dbSDimitry Andric       return XcodeSDK::iPhoneOS;
2895ffd83dbSDimitry Andric     }
2905ffd83dbSDimitry Andric   case Triple::TvOS:
2915ffd83dbSDimitry Andric     if (triple.getEnvironment() == Triple::Simulator)
2925ffd83dbSDimitry Andric       return XcodeSDK::AppleTVSimulator;
2935ffd83dbSDimitry Andric     return XcodeSDK::AppleTVOS;
2945ffd83dbSDimitry Andric   case Triple::WatchOS:
2955ffd83dbSDimitry Andric     if (triple.getEnvironment() == Triple::Simulator)
2965ffd83dbSDimitry Andric       return XcodeSDK::WatchSimulator;
2975ffd83dbSDimitry Andric     return XcodeSDK::watchOS;
298*7a6dacacSDimitry Andric   case Triple::XROS:
299*7a6dacacSDimitry Andric     if (triple.getEnvironment() == Triple::Simulator)
300*7a6dacacSDimitry Andric       return XcodeSDK::XRSimulator;
301*7a6dacacSDimitry Andric     return XcodeSDK::XROS;
3025ffd83dbSDimitry Andric   case Triple::Linux:
3035ffd83dbSDimitry Andric     return XcodeSDK::Linux;
3045ffd83dbSDimitry Andric   default:
3055ffd83dbSDimitry Andric     return XcodeSDK::unknown;
3065ffd83dbSDimitry Andric   }
3075ffd83dbSDimitry Andric }
3085ffd83dbSDimitry Andric 
FindXcodeContentsDirectoryInPath(llvm::StringRef path)3095ffd83dbSDimitry Andric std::string XcodeSDK::FindXcodeContentsDirectoryInPath(llvm::StringRef path) {
3105ffd83dbSDimitry Andric   auto begin = llvm::sys::path::begin(path);
3115ffd83dbSDimitry Andric   auto end = llvm::sys::path::end(path);
3125ffd83dbSDimitry Andric 
3135ffd83dbSDimitry Andric   // Iterate over the path components until we find something that ends with
3145ffd83dbSDimitry Andric   // .app. If the next component is Contents then we've found the Contents
3155ffd83dbSDimitry Andric   // directory.
3165ffd83dbSDimitry Andric   for (auto it = begin; it != end; ++it) {
3175f757f3fSDimitry Andric     if (it->ends_with(".app")) {
3185ffd83dbSDimitry Andric       auto next = it;
3195ffd83dbSDimitry Andric       if (++next != end && *next == "Contents") {
3205ffd83dbSDimitry Andric         llvm::SmallString<128> buffer;
3215ffd83dbSDimitry Andric         llvm::sys::path::append(buffer, begin, ++next,
3225ffd83dbSDimitry Andric                                 llvm::sys::path::Style::posix);
3235ffd83dbSDimitry Andric         return buffer.str().str();
3245ffd83dbSDimitry Andric       }
3255ffd83dbSDimitry Andric     }
3265ffd83dbSDimitry Andric   }
3275ffd83dbSDimitry Andric 
3285ffd83dbSDimitry Andric   return {};
3295ffd83dbSDimitry Andric }
330