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 {sdk, version}; 73 } 74 75 llvm::VersionTuple XcodeSDK::GetVersion() const { 76 llvm::StringRef input(m_name); 77 ParseSDKName(input); 78 return ParseSDKVersion(input); 79 } 80 81 XcodeSDK::Type XcodeSDK::GetType() const { 82 llvm::StringRef input(m_name); 83 return ParseSDKName(input); 84 } 85 86 llvm::StringRef XcodeSDK::GetString() const { return m_name; } 87 88 void XcodeSDK::Merge(XcodeSDK other) { 89 // The "bigger" SDK always wins. 90 if (Parse() < other.Parse()) 91 *this = other; 92 } 93 94 llvm::StringRef XcodeSDK::GetSDKNameForType(XcodeSDK::Type type) { 95 switch (type) { 96 case MacOSX: 97 return "macosx"; 98 case iPhoneSimulator: 99 return "iphonesimulator"; 100 case iPhoneOS: 101 return "iphoneos"; 102 case AppleTVSimulator: 103 return "appletvsimulator"; 104 case AppleTVOS: 105 return "appletvos"; 106 case WatchSimulator: 107 return "watchsimulator"; 108 case watchOS: 109 return "watchos"; 110 case bridgeOS: 111 return "bridgeos"; 112 case Linux: 113 return "linux"; 114 case numSDKTypes: 115 case unknown: 116 return ""; 117 } 118 llvm_unreachable("unhandled switch case"); 119 } 120 121 bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type sdk_type, 122 llvm::VersionTuple version) { 123 switch (sdk_type) { 124 case Type::MacOSX: 125 return version >= llvm::VersionTuple(10, 10); 126 case Type::iPhoneOS: 127 case Type::iPhoneSimulator: 128 case Type::AppleTVOS: 129 case Type::AppleTVSimulator: 130 return version >= llvm::VersionTuple(8); 131 case Type::watchOS: 132 case Type::WatchSimulator: 133 return version >= llvm::VersionTuple(6); 134 default: 135 return false; 136 } 137 138 return false; 139 } 140 141 bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type desired_type, 142 const FileSpec &sdk_path) { 143 ConstString last_path_component = sdk_path.GetLastPathComponent(); 144 145 if (last_path_component) { 146 const llvm::StringRef sdk_name = last_path_component.GetStringRef(); 147 148 const std::string sdk_name_lower = sdk_name.lower(); 149 const llvm::StringRef sdk_string = GetSDKNameForType(desired_type); 150 if (!llvm::StringRef(sdk_name_lower).startswith(sdk_string)) 151 return false; 152 153 auto version_part = sdk_name.drop_front(sdk_string.size()); 154 version_part.consume_back(".sdk"); 155 156 llvm::VersionTuple version; 157 if (version.tryParse(version_part)) 158 return false; 159 return SDKSupportsModules(desired_type, version); 160 } 161 162 return false; 163 } 164