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 9 #include "lldb/Utility/FileSpec.h" 10 #include "lldb/Utility/XcodeSDK.h" 11 12 #include "lldb/lldb-types.h" 13 14 using namespace lldb; 15 using namespace lldb_private; 16 17 XcodeSDK &XcodeSDK::operator=(XcodeSDK other) { 18 m_name = other.m_name; 19 return *this; 20 } 21 22 bool XcodeSDK::operator==(XcodeSDK other) { 23 return m_name == other.m_name; 24 } 25 26 static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) { 27 if (name.consume_front("MacOSX")) 28 return XcodeSDK::MacOSX; 29 if (name.consume_front("iPhoneSimulator")) 30 return XcodeSDK::iPhoneSimulator; 31 if (name.consume_front("iPhoneOS")) 32 return XcodeSDK::iPhoneOS; 33 if (name.consume_front("AppleTVSimulator")) 34 return XcodeSDK::AppleTVSimulator; 35 if (name.consume_front("AppleTVOS")) 36 return XcodeSDK::AppleTVOS; 37 if (name.consume_front("WatchSimulator")) 38 return XcodeSDK::WatchSimulator; 39 if (name.consume_front("WatchOS")) 40 return XcodeSDK::watchOS; 41 if (name.consume_front("bridgeOS")) 42 return XcodeSDK::bridgeOS; 43 if (name.consume_front("Linux")) 44 return XcodeSDK::Linux; 45 static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1, 46 "New SDK type was added, update this list!"); 47 return XcodeSDK::unknown; 48 } 49 50 static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) { 51 unsigned i = 0; 52 while (i < name.size() && name[i] >= '0' && name[i] <= '9') 53 ++i; 54 if (i == name.size() || name[i++] != '.') 55 return {}; 56 while (i < name.size() && name[i] >= '0' && name[i] <= '9') 57 ++i; 58 if (i == name.size() || name[i++] != '.') 59 return {}; 60 61 llvm::VersionTuple version; 62 version.tryParse(name.slice(0, i - 1)); 63 name = name.drop_front(i); 64 return version; 65 } 66 67 68 std::tuple<XcodeSDK::Type, llvm::VersionTuple> XcodeSDK::Parse() const { 69 llvm::StringRef input(m_name); 70 XcodeSDK::Type sdk = ParseSDKName(input); 71 llvm::VersionTuple version = ParseSDKVersion(input); 72 return std::make_tuple<XcodeSDK::Type, llvm::VersionTuple>( 73 std::move(sdk), std::move(version)); 74 } 75 76 llvm::VersionTuple XcodeSDK::GetVersion() const { 77 llvm::StringRef input(m_name); 78 ParseSDKName(input); 79 return ParseSDKVersion(input); 80 } 81 82 XcodeSDK::Type XcodeSDK::GetType() const { 83 llvm::StringRef input(m_name); 84 return ParseSDKName(input); 85 } 86 87 llvm::StringRef XcodeSDK::GetString() const { return m_name; } 88 89 void XcodeSDK::Merge(XcodeSDK other) { 90 // The "bigger" SDK always wins. 91 if (Parse() < other.Parse()) 92 *this = other; 93 } 94 95 llvm::StringRef XcodeSDK::GetSDKNameForType(XcodeSDK::Type type) { 96 switch (type) { 97 case MacOSX: 98 return "macosx"; 99 case iPhoneSimulator: 100 return "iphonesimulator"; 101 case iPhoneOS: 102 return "iphoneos"; 103 case AppleTVSimulator: 104 return "appletvsimulator"; 105 case AppleTVOS: 106 return "appletvos"; 107 case WatchSimulator: 108 return "watchsimulator"; 109 case watchOS: 110 return "watchos"; 111 case bridgeOS: 112 return "bridgeos"; 113 case Linux: 114 return "linux"; 115 case numSDKTypes: 116 case unknown: 117 return ""; 118 } 119 llvm_unreachable("unhandled switch case"); 120 } 121 122 bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type sdk_type, 123 llvm::VersionTuple version) { 124 switch (sdk_type) { 125 case Type::MacOSX: 126 return version >= llvm::VersionTuple(10, 10); 127 case Type::iPhoneOS: 128 case Type::iPhoneSimulator: 129 case Type::AppleTVOS: 130 case Type::AppleTVSimulator: 131 return version >= llvm::VersionTuple(8); 132 case Type::watchOS: 133 case Type::WatchSimulator: 134 return version >= llvm::VersionTuple(6); 135 default: 136 return false; 137 } 138 139 return false; 140 } 141 142 bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type desired_type, 143 const FileSpec &sdk_path) { 144 ConstString last_path_component = sdk_path.GetLastPathComponent(); 145 146 if (last_path_component) { 147 const llvm::StringRef sdk_name = last_path_component.GetStringRef(); 148 149 const std::string sdk_name_lower = sdk_name.lower(); 150 const llvm::StringRef sdk_string = GetSDKNameForType(desired_type); 151 if (!llvm::StringRef(sdk_name_lower).startswith(sdk_string)) 152 return false; 153 154 auto version_part = sdk_name.drop_front(sdk_string.size()); 155 version_part.consume_back(".sdk"); 156 157 llvm::VersionTuple version; 158 if (version.tryParse(version_part)) 159 return false; 160 return SDKSupportsModules(desired_type, version); 161 } 162 163 return false; 164 } 165