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
145ffd83dbSDimitry Andric #include "llvm/ADT/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";
375ffd83dbSDimitry Andric case XcodeSDK::bridgeOS:
385ffd83dbSDimitry Andric return "bridgeOS";
395ffd83dbSDimitry Andric case XcodeSDK::Linux:
405ffd83dbSDimitry Andric return "Linux";
415ffd83dbSDimitry Andric case XcodeSDK::unknown:
425ffd83dbSDimitry Andric return {};
435ffd83dbSDimitry Andric }
445ffd83dbSDimitry Andric llvm_unreachable("Unhandled sdk type!");
455ffd83dbSDimitry Andric }
465ffd83dbSDimitry Andric
XcodeSDK(XcodeSDK::Info info)475ffd83dbSDimitry Andric XcodeSDK::XcodeSDK(XcodeSDK::Info info) : m_name(GetName(info.type).str()) {
485ffd83dbSDimitry Andric if (!m_name.empty()) {
495ffd83dbSDimitry Andric if (!info.version.empty())
505ffd83dbSDimitry Andric m_name += info.version.getAsString();
515ffd83dbSDimitry Andric if (info.internal)
525ffd83dbSDimitry Andric m_name += ".Internal";
535ffd83dbSDimitry Andric m_name += ".sdk";
545ffd83dbSDimitry Andric }
555ffd83dbSDimitry Andric }
565ffd83dbSDimitry Andric
operator =(const XcodeSDK & other)57*af732203SDimitry Andric XcodeSDK &XcodeSDK::operator=(const XcodeSDK &other) {
585ffd83dbSDimitry Andric m_name = other.m_name;
595ffd83dbSDimitry Andric return *this;
605ffd83dbSDimitry Andric }
615ffd83dbSDimitry Andric
operator ==(const XcodeSDK & other)62*af732203SDimitry Andric bool XcodeSDK::operator==(const XcodeSDK &other) {
635ffd83dbSDimitry Andric return m_name == other.m_name;
645ffd83dbSDimitry Andric }
655ffd83dbSDimitry Andric
ParseSDKName(llvm::StringRef & name)665ffd83dbSDimitry Andric static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) {
675ffd83dbSDimitry Andric if (name.consume_front("MacOSX"))
685ffd83dbSDimitry Andric return XcodeSDK::MacOSX;
695ffd83dbSDimitry Andric if (name.consume_front("iPhoneSimulator"))
705ffd83dbSDimitry Andric return XcodeSDK::iPhoneSimulator;
715ffd83dbSDimitry Andric if (name.consume_front("iPhoneOS"))
725ffd83dbSDimitry Andric return XcodeSDK::iPhoneOS;
735ffd83dbSDimitry Andric if (name.consume_front("AppleTVSimulator"))
745ffd83dbSDimitry Andric return XcodeSDK::AppleTVSimulator;
755ffd83dbSDimitry Andric if (name.consume_front("AppleTVOS"))
765ffd83dbSDimitry Andric return XcodeSDK::AppleTVOS;
775ffd83dbSDimitry Andric if (name.consume_front("WatchSimulator"))
785ffd83dbSDimitry Andric return XcodeSDK::WatchSimulator;
795ffd83dbSDimitry Andric if (name.consume_front("WatchOS"))
805ffd83dbSDimitry Andric return XcodeSDK::watchOS;
815ffd83dbSDimitry Andric if (name.consume_front("bridgeOS"))
825ffd83dbSDimitry Andric return XcodeSDK::bridgeOS;
835ffd83dbSDimitry Andric if (name.consume_front("Linux"))
845ffd83dbSDimitry Andric return XcodeSDK::Linux;
855ffd83dbSDimitry Andric static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1,
865ffd83dbSDimitry Andric "New SDK type was added, update this list!");
875ffd83dbSDimitry Andric return XcodeSDK::unknown;
885ffd83dbSDimitry Andric }
895ffd83dbSDimitry Andric
ParseSDKVersion(llvm::StringRef & name)905ffd83dbSDimitry Andric static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) {
915ffd83dbSDimitry Andric unsigned i = 0;
925ffd83dbSDimitry Andric while (i < name.size() && name[i] >= '0' && name[i] <= '9')
935ffd83dbSDimitry Andric ++i;
945ffd83dbSDimitry Andric if (i == name.size() || name[i++] != '.')
955ffd83dbSDimitry Andric return {};
965ffd83dbSDimitry Andric while (i < name.size() && name[i] >= '0' && name[i] <= '9')
975ffd83dbSDimitry Andric ++i;
985ffd83dbSDimitry Andric if (i == name.size() || name[i++] != '.')
995ffd83dbSDimitry Andric return {};
1005ffd83dbSDimitry Andric
1015ffd83dbSDimitry Andric llvm::VersionTuple version;
1025ffd83dbSDimitry Andric version.tryParse(name.slice(0, i - 1));
1035ffd83dbSDimitry Andric name = name.drop_front(i);
1045ffd83dbSDimitry Andric return version;
1055ffd83dbSDimitry Andric }
1065ffd83dbSDimitry Andric
ParseAppleInternalSDK(llvm::StringRef & name)1075ffd83dbSDimitry Andric static bool ParseAppleInternalSDK(llvm::StringRef &name) {
1085ffd83dbSDimitry Andric return name.consume_front("Internal.") || name.consume_front(".Internal.");
1095ffd83dbSDimitry Andric }
1105ffd83dbSDimitry Andric
Parse() const1115ffd83dbSDimitry Andric XcodeSDK::Info XcodeSDK::Parse() const {
1125ffd83dbSDimitry Andric XcodeSDK::Info info;
1135ffd83dbSDimitry Andric llvm::StringRef input(m_name);
1145ffd83dbSDimitry Andric info.type = ParseSDKName(input);
1155ffd83dbSDimitry Andric info.version = ParseSDKVersion(input);
1165ffd83dbSDimitry Andric info.internal = ParseAppleInternalSDK(input);
1175ffd83dbSDimitry Andric return info;
1185ffd83dbSDimitry Andric }
1195ffd83dbSDimitry Andric
IsAppleInternalSDK() const1205ffd83dbSDimitry Andric bool XcodeSDK::IsAppleInternalSDK() const {
1215ffd83dbSDimitry Andric llvm::StringRef input(m_name);
1225ffd83dbSDimitry Andric ParseSDKName(input);
1235ffd83dbSDimitry Andric ParseSDKVersion(input);
1245ffd83dbSDimitry Andric return ParseAppleInternalSDK(input);
1255ffd83dbSDimitry Andric }
1265ffd83dbSDimitry Andric
GetVersion() const1275ffd83dbSDimitry Andric llvm::VersionTuple XcodeSDK::GetVersion() const {
1285ffd83dbSDimitry Andric llvm::StringRef input(m_name);
1295ffd83dbSDimitry Andric ParseSDKName(input);
1305ffd83dbSDimitry Andric return ParseSDKVersion(input);
1315ffd83dbSDimitry Andric }
1325ffd83dbSDimitry Andric
GetType() const1335ffd83dbSDimitry Andric XcodeSDK::Type XcodeSDK::GetType() const {
1345ffd83dbSDimitry Andric llvm::StringRef input(m_name);
1355ffd83dbSDimitry Andric return ParseSDKName(input);
1365ffd83dbSDimitry Andric }
1375ffd83dbSDimitry Andric
GetString() const1385ffd83dbSDimitry Andric llvm::StringRef XcodeSDK::GetString() const { return m_name; }
1395ffd83dbSDimitry Andric
operator <(const Info & other) const1405ffd83dbSDimitry Andric bool XcodeSDK::Info::operator<(const Info &other) const {
1415ffd83dbSDimitry Andric return std::tie(type, version, internal) <
1425ffd83dbSDimitry Andric std::tie(other.type, other.version, other.internal);
1435ffd83dbSDimitry Andric }
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
Merge(const XcodeSDK & other)150*af732203SDimitry Andric void XcodeSDK::Merge(const XcodeSDK &other) {
1515ffd83dbSDimitry Andric // The "bigger" SDK always wins.
1525ffd83dbSDimitry Andric auto l = Parse();
1535ffd83dbSDimitry Andric auto r = other.Parse();
1545ffd83dbSDimitry Andric if (l < r)
1555ffd83dbSDimitry Andric *this = other;
1565ffd83dbSDimitry Andric else {
1575ffd83dbSDimitry Andric // The Internal flag always wins.
1585ffd83dbSDimitry Andric if (llvm::StringRef(m_name).endswith(".sdk"))
1595ffd83dbSDimitry Andric if (!l.internal && r.internal)
1605ffd83dbSDimitry Andric m_name =
1615ffd83dbSDimitry Andric m_name.substr(0, m_name.size() - 3) + std::string("Internal.sdk");
1625ffd83dbSDimitry Andric }
1635ffd83dbSDimitry Andric }
1645ffd83dbSDimitry Andric
GetCanonicalName(XcodeSDK::Info info)1655ffd83dbSDimitry Andric std::string XcodeSDK::GetCanonicalName(XcodeSDK::Info info) {
1665ffd83dbSDimitry Andric std::string name;
1675ffd83dbSDimitry Andric switch (info.type) {
1685ffd83dbSDimitry Andric case MacOSX:
1695ffd83dbSDimitry Andric name = "macosx";
1705ffd83dbSDimitry Andric break;
1715ffd83dbSDimitry Andric case iPhoneSimulator:
1725ffd83dbSDimitry Andric name = "iphonesimulator";
1735ffd83dbSDimitry Andric break;
1745ffd83dbSDimitry Andric case iPhoneOS:
1755ffd83dbSDimitry Andric name = "iphoneos";
1765ffd83dbSDimitry Andric break;
1775ffd83dbSDimitry Andric case AppleTVSimulator:
1785ffd83dbSDimitry Andric name = "appletvsimulator";
1795ffd83dbSDimitry Andric break;
1805ffd83dbSDimitry Andric case AppleTVOS:
1815ffd83dbSDimitry Andric name = "appletvos";
1825ffd83dbSDimitry Andric break;
1835ffd83dbSDimitry Andric case WatchSimulator:
1845ffd83dbSDimitry Andric name = "watchsimulator";
1855ffd83dbSDimitry Andric break;
1865ffd83dbSDimitry Andric case watchOS:
1875ffd83dbSDimitry Andric name = "watchos";
1885ffd83dbSDimitry Andric break;
1895ffd83dbSDimitry Andric case bridgeOS:
1905ffd83dbSDimitry Andric name = "bridgeos";
1915ffd83dbSDimitry Andric break;
1925ffd83dbSDimitry Andric case Linux:
1935ffd83dbSDimitry Andric name = "linux";
1945ffd83dbSDimitry Andric break;
1955ffd83dbSDimitry Andric case unknown:
1965ffd83dbSDimitry Andric return {};
1975ffd83dbSDimitry Andric }
1985ffd83dbSDimitry Andric if (!info.version.empty())
1995ffd83dbSDimitry Andric name += info.version.getAsString();
2005ffd83dbSDimitry Andric if (info.internal)
2015ffd83dbSDimitry Andric name += ".internal";
2025ffd83dbSDimitry Andric return name;
2035ffd83dbSDimitry Andric }
2045ffd83dbSDimitry Andric
SDKSupportsModules(XcodeSDK::Type sdk_type,llvm::VersionTuple version)2055ffd83dbSDimitry Andric bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type sdk_type,
2065ffd83dbSDimitry Andric llvm::VersionTuple version) {
2075ffd83dbSDimitry Andric switch (sdk_type) {
2085ffd83dbSDimitry Andric case Type::MacOSX:
2095ffd83dbSDimitry Andric return version >= llvm::VersionTuple(10, 10);
2105ffd83dbSDimitry Andric case Type::iPhoneOS:
2115ffd83dbSDimitry Andric case Type::iPhoneSimulator:
2125ffd83dbSDimitry Andric case Type::AppleTVOS:
2135ffd83dbSDimitry Andric case Type::AppleTVSimulator:
2145ffd83dbSDimitry Andric return version >= llvm::VersionTuple(8);
2155ffd83dbSDimitry Andric case Type::watchOS:
2165ffd83dbSDimitry Andric case Type::WatchSimulator:
2175ffd83dbSDimitry Andric return version >= llvm::VersionTuple(6);
2185ffd83dbSDimitry Andric default:
2195ffd83dbSDimitry Andric return false;
2205ffd83dbSDimitry Andric }
2215ffd83dbSDimitry Andric
2225ffd83dbSDimitry Andric return false;
2235ffd83dbSDimitry Andric }
2245ffd83dbSDimitry Andric
SupportsSwift() const2255ffd83dbSDimitry Andric bool XcodeSDK::SupportsSwift() const {
2265ffd83dbSDimitry Andric XcodeSDK::Info info = Parse();
2275ffd83dbSDimitry Andric switch (info.type) {
2285ffd83dbSDimitry Andric case Type::MacOSX:
2295ffd83dbSDimitry Andric return info.version.empty() || info.version >= llvm::VersionTuple(10, 10);
2305ffd83dbSDimitry Andric case Type::iPhoneOS:
2315ffd83dbSDimitry Andric case Type::iPhoneSimulator:
2325ffd83dbSDimitry Andric return info.version.empty() || info.version >= llvm::VersionTuple(8);
2335ffd83dbSDimitry Andric case Type::AppleTVSimulator:
2345ffd83dbSDimitry Andric case Type::AppleTVOS:
2355ffd83dbSDimitry Andric return info.version.empty() || info.version >= llvm::VersionTuple(9);
2365ffd83dbSDimitry Andric case Type::WatchSimulator:
2375ffd83dbSDimitry Andric case Type::watchOS:
2385ffd83dbSDimitry Andric return info.version.empty() || info.version >= llvm::VersionTuple(2);
2395ffd83dbSDimitry Andric case Type::Linux:
2405ffd83dbSDimitry Andric return true;
2415ffd83dbSDimitry Andric default:
2425ffd83dbSDimitry Andric return false;
2435ffd83dbSDimitry Andric }
2445ffd83dbSDimitry Andric }
2455ffd83dbSDimitry Andric
SDKSupportsModules(XcodeSDK::Type desired_type,const FileSpec & sdk_path)2465ffd83dbSDimitry Andric bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type desired_type,
2475ffd83dbSDimitry Andric const FileSpec &sdk_path) {
2485ffd83dbSDimitry Andric ConstString last_path_component = sdk_path.GetLastPathComponent();
2495ffd83dbSDimitry Andric
2505ffd83dbSDimitry Andric if (!last_path_component)
2515ffd83dbSDimitry Andric return false;
2525ffd83dbSDimitry Andric
2535ffd83dbSDimitry Andric XcodeSDK sdk(last_path_component.GetStringRef().str());
2545ffd83dbSDimitry Andric if (sdk.GetType() != desired_type)
2555ffd83dbSDimitry Andric return false;
2565ffd83dbSDimitry Andric return SDKSupportsModules(sdk.GetType(), sdk.GetVersion());
2575ffd83dbSDimitry Andric }
2585ffd83dbSDimitry Andric
GetSDKTypeForTriple(const llvm::Triple & triple)2595ffd83dbSDimitry Andric XcodeSDK::Type XcodeSDK::GetSDKTypeForTriple(const llvm::Triple &triple) {
2605ffd83dbSDimitry Andric using namespace llvm;
2615ffd83dbSDimitry Andric switch (triple.getOS()) {
2625ffd83dbSDimitry Andric case Triple::MacOSX:
2635ffd83dbSDimitry Andric case Triple::Darwin:
2645ffd83dbSDimitry Andric return XcodeSDK::MacOSX;
2655ffd83dbSDimitry Andric case Triple::IOS:
2665ffd83dbSDimitry Andric switch (triple.getEnvironment()) {
2675ffd83dbSDimitry Andric case Triple::MacABI:
2685ffd83dbSDimitry Andric return XcodeSDK::MacOSX;
2695ffd83dbSDimitry Andric case Triple::Simulator:
2705ffd83dbSDimitry Andric return XcodeSDK::iPhoneSimulator;
2715ffd83dbSDimitry Andric default:
2725ffd83dbSDimitry Andric return XcodeSDK::iPhoneOS;
2735ffd83dbSDimitry Andric }
2745ffd83dbSDimitry Andric case Triple::TvOS:
2755ffd83dbSDimitry Andric if (triple.getEnvironment() == Triple::Simulator)
2765ffd83dbSDimitry Andric return XcodeSDK::AppleTVSimulator;
2775ffd83dbSDimitry Andric return XcodeSDK::AppleTVOS;
2785ffd83dbSDimitry Andric case Triple::WatchOS:
2795ffd83dbSDimitry Andric if (triple.getEnvironment() == Triple::Simulator)
2805ffd83dbSDimitry Andric return XcodeSDK::WatchSimulator;
2815ffd83dbSDimitry Andric return XcodeSDK::watchOS;
2825ffd83dbSDimitry Andric case Triple::Linux:
2835ffd83dbSDimitry Andric return XcodeSDK::Linux;
2845ffd83dbSDimitry Andric default:
2855ffd83dbSDimitry Andric return XcodeSDK::unknown;
2865ffd83dbSDimitry Andric }
2875ffd83dbSDimitry Andric }
2885ffd83dbSDimitry Andric
FindXcodeContentsDirectoryInPath(llvm::StringRef path)2895ffd83dbSDimitry Andric std::string XcodeSDK::FindXcodeContentsDirectoryInPath(llvm::StringRef path) {
2905ffd83dbSDimitry Andric auto begin = llvm::sys::path::begin(path);
2915ffd83dbSDimitry Andric auto end = llvm::sys::path::end(path);
2925ffd83dbSDimitry Andric
2935ffd83dbSDimitry Andric // Iterate over the path components until we find something that ends with
2945ffd83dbSDimitry Andric // .app. If the next component is Contents then we've found the Contents
2955ffd83dbSDimitry Andric // directory.
2965ffd83dbSDimitry Andric for (auto it = begin; it != end; ++it) {
2975ffd83dbSDimitry Andric if (it->endswith(".app")) {
2985ffd83dbSDimitry Andric auto next = it;
2995ffd83dbSDimitry Andric if (++next != end && *next == "Contents") {
3005ffd83dbSDimitry Andric llvm::SmallString<128> buffer;
3015ffd83dbSDimitry Andric llvm::sys::path::append(buffer, begin, ++next,
3025ffd83dbSDimitry Andric llvm::sys::path::Style::posix);
3035ffd83dbSDimitry Andric return buffer.str().str();
3045ffd83dbSDimitry Andric }
3055ffd83dbSDimitry Andric }
3065ffd83dbSDimitry Andric }
3075ffd83dbSDimitry Andric
3085ffd83dbSDimitry Andric return {};
3095ffd83dbSDimitry Andric }
310