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/FileSpec.h" 101e05d7b3SAdrian Prantl #include "lldb/Utility/XcodeSDK.h" 111e05d7b3SAdrian Prantl 121e05d7b3SAdrian Prantl #include "lldb/lldb-types.h" 131e05d7b3SAdrian Prantl 141e05d7b3SAdrian Prantl using namespace lldb; 151e05d7b3SAdrian Prantl using namespace lldb_private; 161e05d7b3SAdrian Prantl 171e05d7b3SAdrian Prantl XcodeSDK &XcodeSDK::operator=(XcodeSDK other) { 181e05d7b3SAdrian Prantl m_name = other.m_name; 191e05d7b3SAdrian Prantl return *this; 201e05d7b3SAdrian Prantl } 211e05d7b3SAdrian Prantl 221e05d7b3SAdrian Prantl bool XcodeSDK::operator==(XcodeSDK other) { 231e05d7b3SAdrian Prantl return m_name == other.m_name; 241e05d7b3SAdrian Prantl } 251e05d7b3SAdrian Prantl 261e05d7b3SAdrian Prantl static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) { 271e05d7b3SAdrian Prantl if (name.consume_front("MacOSX")) 281e05d7b3SAdrian Prantl return XcodeSDK::MacOSX; 291e05d7b3SAdrian Prantl if (name.consume_front("iPhoneSimulator")) 301e05d7b3SAdrian Prantl return XcodeSDK::iPhoneSimulator; 311e05d7b3SAdrian Prantl if (name.consume_front("iPhoneOS")) 321e05d7b3SAdrian Prantl return XcodeSDK::iPhoneOS; 331e05d7b3SAdrian Prantl if (name.consume_front("AppleTVSimulator")) 341e05d7b3SAdrian Prantl return XcodeSDK::AppleTVSimulator; 351e05d7b3SAdrian Prantl if (name.consume_front("AppleTVOS")) 361e05d7b3SAdrian Prantl return XcodeSDK::AppleTVOS; 371e05d7b3SAdrian Prantl if (name.consume_front("WatchSimulator")) 381e05d7b3SAdrian Prantl return XcodeSDK::WatchSimulator; 391e05d7b3SAdrian Prantl if (name.consume_front("WatchOS")) 401e05d7b3SAdrian Prantl return XcodeSDK::watchOS; 411e05d7b3SAdrian Prantl if (name.consume_front("bridgeOS")) 421e05d7b3SAdrian Prantl return XcodeSDK::bridgeOS; 431e05d7b3SAdrian Prantl if (name.consume_front("Linux")) 441e05d7b3SAdrian Prantl return XcodeSDK::Linux; 451e05d7b3SAdrian Prantl static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1, 461e05d7b3SAdrian Prantl "New SDK type was added, update this list!"); 471e05d7b3SAdrian Prantl return XcodeSDK::unknown; 481e05d7b3SAdrian Prantl } 491e05d7b3SAdrian Prantl 501e05d7b3SAdrian Prantl static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) { 511e05d7b3SAdrian Prantl unsigned i = 0; 521e05d7b3SAdrian Prantl while (i < name.size() && name[i] >= '0' && name[i] <= '9') 531e05d7b3SAdrian Prantl ++i; 541e05d7b3SAdrian Prantl if (i == name.size() || name[i++] != '.') 551e05d7b3SAdrian Prantl return {}; 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 611e05d7b3SAdrian Prantl llvm::VersionTuple version; 621e05d7b3SAdrian Prantl version.tryParse(name.slice(0, i - 1)); 631e05d7b3SAdrian Prantl name = name.drop_front(i); 641e05d7b3SAdrian Prantl return version; 651e05d7b3SAdrian Prantl } 661e05d7b3SAdrian Prantl 67*79feafa5SAdrian Prantl static bool ParseAppleInternalSDK(llvm::StringRef &name) { 68*79feafa5SAdrian Prantl return name.consume_front("Internal."); 69*79feafa5SAdrian Prantl } 701e05d7b3SAdrian Prantl 71*79feafa5SAdrian Prantl XcodeSDK::Info XcodeSDK::Parse() const { 72*79feafa5SAdrian Prantl XcodeSDK::Info info; 731e05d7b3SAdrian Prantl llvm::StringRef input(m_name); 74*79feafa5SAdrian Prantl info.type = ParseSDKName(input); 75*79feafa5SAdrian Prantl info.version = ParseSDKVersion(input); 76*79feafa5SAdrian Prantl info.internal = ParseAppleInternalSDK(input); 77*79feafa5SAdrian Prantl return info; 78*79feafa5SAdrian Prantl } 79*79feafa5SAdrian Prantl 80*79feafa5SAdrian Prantl bool XcodeSDK::IsAppleInternalSDK() const { 81*79feafa5SAdrian Prantl llvm::StringRef input(m_name); 82*79feafa5SAdrian Prantl ParseSDKName(input); 83*79feafa5SAdrian Prantl ParseSDKVersion(input); 84*79feafa5SAdrian Prantl return ParseAppleInternalSDK(input); 851e05d7b3SAdrian Prantl } 861e05d7b3SAdrian Prantl 871e05d7b3SAdrian Prantl llvm::VersionTuple XcodeSDK::GetVersion() const { 881e05d7b3SAdrian Prantl llvm::StringRef input(m_name); 891e05d7b3SAdrian Prantl ParseSDKName(input); 901e05d7b3SAdrian Prantl return ParseSDKVersion(input); 911e05d7b3SAdrian Prantl } 921e05d7b3SAdrian Prantl 931e05d7b3SAdrian Prantl XcodeSDK::Type XcodeSDK::GetType() const { 941e05d7b3SAdrian Prantl llvm::StringRef input(m_name); 951e05d7b3SAdrian Prantl return ParseSDKName(input); 961e05d7b3SAdrian Prantl } 971e05d7b3SAdrian Prantl 981e05d7b3SAdrian Prantl llvm::StringRef XcodeSDK::GetString() const { return m_name; } 991e05d7b3SAdrian Prantl 100*79feafa5SAdrian Prantl bool XcodeSDK::Info::operator<(const Info &other) const { 101*79feafa5SAdrian Prantl return std::tie(type, version, internal) < 102*79feafa5SAdrian Prantl std::tie(other.type, other.version, other.internal); 103*79feafa5SAdrian Prantl } 1041e05d7b3SAdrian Prantl void XcodeSDK::Merge(XcodeSDK other) { 1051e05d7b3SAdrian Prantl // The "bigger" SDK always wins. 106*79feafa5SAdrian Prantl auto l = Parse(); 107*79feafa5SAdrian Prantl auto r = other.Parse(); 108*79feafa5SAdrian Prantl if (l < r) 1091e05d7b3SAdrian Prantl *this = other; 110*79feafa5SAdrian Prantl else { 111*79feafa5SAdrian Prantl // The Internal flag always wins. 112*79feafa5SAdrian Prantl if (llvm::StringRef(m_name).endswith(".sdk")) 113*79feafa5SAdrian Prantl if (!l.internal && r.internal) 114*79feafa5SAdrian Prantl m_name = 115*79feafa5SAdrian Prantl m_name.substr(0, m_name.size() - 3) + std::string("Internal.sdk"); 116*79feafa5SAdrian Prantl } 1171e05d7b3SAdrian Prantl } 1181e05d7b3SAdrian Prantl 119*79feafa5SAdrian Prantl std::string XcodeSDK::GetCanonicalName(XcodeSDK::Info info) { 120*79feafa5SAdrian Prantl std::string name; 121*79feafa5SAdrian Prantl switch (info.type) { 1221e05d7b3SAdrian Prantl case MacOSX: 123*79feafa5SAdrian Prantl name = "macosx"; 124*79feafa5SAdrian Prantl break; 1251e05d7b3SAdrian Prantl case iPhoneSimulator: 126*79feafa5SAdrian Prantl name = "iphonesimulator"; 127*79feafa5SAdrian Prantl break; 1281e05d7b3SAdrian Prantl case iPhoneOS: 129*79feafa5SAdrian Prantl name = "iphoneos"; 130*79feafa5SAdrian Prantl break; 1311e05d7b3SAdrian Prantl case AppleTVSimulator: 132*79feafa5SAdrian Prantl name = "appletvsimulator"; 133*79feafa5SAdrian Prantl break; 1341e05d7b3SAdrian Prantl case AppleTVOS: 135*79feafa5SAdrian Prantl name = "appletvos"; 136*79feafa5SAdrian Prantl break; 1371e05d7b3SAdrian Prantl case WatchSimulator: 138*79feafa5SAdrian Prantl name = "watchsimulator"; 139*79feafa5SAdrian Prantl break; 1401e05d7b3SAdrian Prantl case watchOS: 141*79feafa5SAdrian Prantl name = "watchos"; 142*79feafa5SAdrian Prantl break; 1431e05d7b3SAdrian Prantl case bridgeOS: 144*79feafa5SAdrian Prantl name = "bridgeos"; 145*79feafa5SAdrian Prantl break; 1461e05d7b3SAdrian Prantl case Linux: 147*79feafa5SAdrian Prantl name = "linux"; 148*79feafa5SAdrian Prantl break; 1491e05d7b3SAdrian Prantl case numSDKTypes: 1501e05d7b3SAdrian Prantl case unknown: 151*79feafa5SAdrian Prantl return {}; 1521e05d7b3SAdrian Prantl } 153*79feafa5SAdrian Prantl if (!info.version.empty()) 154*79feafa5SAdrian Prantl name += info.version.getAsString(); 155*79feafa5SAdrian Prantl if (info.internal) 156*79feafa5SAdrian Prantl name += ".internal"; 157*79feafa5SAdrian Prantl return name; 1581e05d7b3SAdrian Prantl } 1591e05d7b3SAdrian Prantl 1601e05d7b3SAdrian Prantl bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type sdk_type, 1611e05d7b3SAdrian Prantl llvm::VersionTuple version) { 1621e05d7b3SAdrian Prantl switch (sdk_type) { 1631e05d7b3SAdrian Prantl case Type::MacOSX: 1641e05d7b3SAdrian Prantl return version >= llvm::VersionTuple(10, 10); 1651e05d7b3SAdrian Prantl case Type::iPhoneOS: 1661e05d7b3SAdrian Prantl case Type::iPhoneSimulator: 1671e05d7b3SAdrian Prantl case Type::AppleTVOS: 1681e05d7b3SAdrian Prantl case Type::AppleTVSimulator: 1691e05d7b3SAdrian Prantl return version >= llvm::VersionTuple(8); 1701e05d7b3SAdrian Prantl case Type::watchOS: 1711e05d7b3SAdrian Prantl case Type::WatchSimulator: 1721e05d7b3SAdrian Prantl return version >= llvm::VersionTuple(6); 1731e05d7b3SAdrian Prantl default: 1741e05d7b3SAdrian Prantl return false; 1751e05d7b3SAdrian Prantl } 1761e05d7b3SAdrian Prantl 1771e05d7b3SAdrian Prantl return false; 1781e05d7b3SAdrian Prantl } 1791e05d7b3SAdrian Prantl 1801e05d7b3SAdrian Prantl bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type desired_type, 1811e05d7b3SAdrian Prantl const FileSpec &sdk_path) { 1821e05d7b3SAdrian Prantl ConstString last_path_component = sdk_path.GetLastPathComponent(); 1831e05d7b3SAdrian Prantl 1841e05d7b3SAdrian Prantl if (last_path_component) { 1851e05d7b3SAdrian Prantl const llvm::StringRef sdk_name = last_path_component.GetStringRef(); 1861e05d7b3SAdrian Prantl 1871e05d7b3SAdrian Prantl const std::string sdk_name_lower = sdk_name.lower(); 188*79feafa5SAdrian Prantl Info info; 189*79feafa5SAdrian Prantl info.type = desired_type; 190*79feafa5SAdrian Prantl const llvm::StringRef sdk_string = GetCanonicalName(info); 1911e05d7b3SAdrian Prantl if (!llvm::StringRef(sdk_name_lower).startswith(sdk_string)) 1921e05d7b3SAdrian Prantl return false; 1931e05d7b3SAdrian Prantl 1941e05d7b3SAdrian Prantl auto version_part = sdk_name.drop_front(sdk_string.size()); 1951e05d7b3SAdrian Prantl version_part.consume_back(".sdk"); 196*79feafa5SAdrian Prantl version_part.consume_back(".Internal"); 1971e05d7b3SAdrian Prantl 1981e05d7b3SAdrian Prantl llvm::VersionTuple version; 1991e05d7b3SAdrian Prantl if (version.tryParse(version_part)) 2001e05d7b3SAdrian Prantl return false; 2011e05d7b3SAdrian Prantl return SDKSupportsModules(desired_type, version); 2021e05d7b3SAdrian Prantl } 2031e05d7b3SAdrian Prantl 2041e05d7b3SAdrian Prantl return false; 2051e05d7b3SAdrian Prantl } 206