Files
clang-p2996/lldb/source/Utility/XcodeSDK.cpp
Adrian Prantl ae920a81ff Add an API to construct an XcodeSDK from an SDK type.
Also, this moves numSDKs out of the actual enum, as to not mess with
the switch-cases-covered warning.

Differential Revision: https://reviews.llvm.org/D79603
2020-05-08 10:47:13 -07:00

287 lines
7.5 KiB
C++

//===-- XcodeSDK.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Utility/XcodeSDK.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/lldb-types.h"
#include "llvm/ADT/Triple.h"
#include <string>
using namespace lldb;
using namespace lldb_private;
static llvm::StringRef GetName(XcodeSDK::Type type) {
switch (type) {
case XcodeSDK::MacOSX:
return "MacOSX";
case XcodeSDK::iPhoneSimulator:
return "iPhoneSimulator";
case XcodeSDK::iPhoneOS:
return "iPhoneOS";
case XcodeSDK::AppleTVSimulator:
return "AppleTVSimulator";
case XcodeSDK::AppleTVOS:
return "AppleTVOS";
case XcodeSDK::WatchSimulator:
return "WatchSimulator";
case XcodeSDK::watchOS:
return "WatchOS";
case XcodeSDK::bridgeOS:
return "bridgeOS";
case XcodeSDK::Linux:
return "Linux";
case XcodeSDK::unknown:
return {};
}
}
XcodeSDK::XcodeSDK(XcodeSDK::Info info) : m_name(GetName(info.type).str()) {
if (!m_name.empty()) {
if (!info.version.empty())
m_name += info.version.getAsString();
if (info.internal)
m_name += ".Internal";
m_name += ".sdk";
}
}
XcodeSDK &XcodeSDK::operator=(XcodeSDK other) {
m_name = other.m_name;
return *this;
}
bool XcodeSDK::operator==(XcodeSDK other) {
return m_name == other.m_name;
}
static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) {
if (name.consume_front("MacOSX"))
return XcodeSDK::MacOSX;
if (name.consume_front("iPhoneSimulator"))
return XcodeSDK::iPhoneSimulator;
if (name.consume_front("iPhoneOS"))
return XcodeSDK::iPhoneOS;
if (name.consume_front("AppleTVSimulator"))
return XcodeSDK::AppleTVSimulator;
if (name.consume_front("AppleTVOS"))
return XcodeSDK::AppleTVOS;
if (name.consume_front("WatchSimulator"))
return XcodeSDK::WatchSimulator;
if (name.consume_front("WatchOS"))
return XcodeSDK::watchOS;
if (name.consume_front("bridgeOS"))
return XcodeSDK::bridgeOS;
if (name.consume_front("Linux"))
return XcodeSDK::Linux;
static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1,
"New SDK type was added, update this list!");
return XcodeSDK::unknown;
}
static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) {
unsigned i = 0;
while (i < name.size() && name[i] >= '0' && name[i] <= '9')
++i;
if (i == name.size() || name[i++] != '.')
return {};
while (i < name.size() && name[i] >= '0' && name[i] <= '9')
++i;
if (i == name.size() || name[i++] != '.')
return {};
llvm::VersionTuple version;
version.tryParse(name.slice(0, i - 1));
name = name.drop_front(i);
return version;
}
static bool ParseAppleInternalSDK(llvm::StringRef &name) {
return name.consume_front("Internal.") || name.consume_front(".Internal.");
}
XcodeSDK::Info XcodeSDK::Parse() const {
XcodeSDK::Info info;
llvm::StringRef input(m_name);
info.type = ParseSDKName(input);
info.version = ParseSDKVersion(input);
info.internal = ParseAppleInternalSDK(input);
return info;
}
bool XcodeSDK::IsAppleInternalSDK() const {
llvm::StringRef input(m_name);
ParseSDKName(input);
ParseSDKVersion(input);
return ParseAppleInternalSDK(input);
}
llvm::VersionTuple XcodeSDK::GetVersion() const {
llvm::StringRef input(m_name);
ParseSDKName(input);
return ParseSDKVersion(input);
}
XcodeSDK::Type XcodeSDK::GetType() const {
llvm::StringRef input(m_name);
return ParseSDKName(input);
}
llvm::StringRef XcodeSDK::GetString() const { return m_name; }
bool XcodeSDK::Info::operator<(const Info &other) const {
return std::tie(type, version, internal) <
std::tie(other.type, other.version, other.internal);
}
bool XcodeSDK::Info::operator==(const Info &other) const {
return std::tie(type, version, internal) ==
std::tie(other.type, other.version, other.internal);
}
void XcodeSDK::Merge(XcodeSDK other) {
// The "bigger" SDK always wins.
auto l = Parse();
auto r = other.Parse();
if (l < r)
*this = other;
else {
// The Internal flag always wins.
if (llvm::StringRef(m_name).endswith(".sdk"))
if (!l.internal && r.internal)
m_name =
m_name.substr(0, m_name.size() - 3) + std::string("Internal.sdk");
}
}
std::string XcodeSDK::GetCanonicalName(XcodeSDK::Info info) {
std::string name;
switch (info.type) {
case MacOSX:
name = "macosx";
break;
case iPhoneSimulator:
name = "iphonesimulator";
break;
case iPhoneOS:
name = "iphoneos";
break;
case AppleTVSimulator:
name = "appletvsimulator";
break;
case AppleTVOS:
name = "appletvos";
break;
case WatchSimulator:
name = "watchsimulator";
break;
case watchOS:
name = "watchos";
break;
case bridgeOS:
name = "bridgeos";
break;
case Linux:
name = "linux";
break;
case unknown:
return {};
}
if (!info.version.empty())
name += info.version.getAsString();
if (info.internal)
name += ".internal";
return name;
}
bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type sdk_type,
llvm::VersionTuple version) {
switch (sdk_type) {
case Type::MacOSX:
return version >= llvm::VersionTuple(10, 10);
case Type::iPhoneOS:
case Type::iPhoneSimulator:
case Type::AppleTVOS:
case Type::AppleTVSimulator:
return version >= llvm::VersionTuple(8);
case Type::watchOS:
case Type::WatchSimulator:
return version >= llvm::VersionTuple(6);
default:
return false;
}
return false;
}
bool XcodeSDK::SupportsSwift() const {
XcodeSDK::Info info = Parse();
switch (info.type) {
case Type::MacOSX:
return info.version.empty() || info.version >= llvm::VersionTuple(10, 10);
case Type::iPhoneOS:
case Type::iPhoneSimulator:
return info.version.empty() || info.version >= llvm::VersionTuple(8);
case Type::AppleTVSimulator:
case Type::AppleTVOS:
return info.version.empty() || info.version >= llvm::VersionTuple(9);
case Type::WatchSimulator:
case Type::watchOS:
return info.version.empty() || info.version >= llvm::VersionTuple(2);
case Type::Linux:
return true;
default:
return false;
}
}
bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type desired_type,
const FileSpec &sdk_path) {
ConstString last_path_component = sdk_path.GetLastPathComponent();
if (!last_path_component)
return false;
XcodeSDK sdk(last_path_component.GetStringRef().str());
if (sdk.GetType() != desired_type)
return false;
return SDKSupportsModules(sdk.GetType(), sdk.GetVersion());
}
XcodeSDK::Type XcodeSDK::GetSDKTypeForTriple(const llvm::Triple &triple) {
using namespace llvm;
switch (triple.getOS()) {
case Triple::MacOSX:
case Triple::Darwin:
return XcodeSDK::MacOSX;
case Triple::IOS:
switch (triple.getEnvironment()) {
case Triple::MacABI:
return XcodeSDK::MacOSX;
case Triple::Simulator:
return XcodeSDK::iPhoneSimulator;
default:
return XcodeSDK::iPhoneOS;
}
case Triple::TvOS:
if (triple.getEnvironment() == Triple::Simulator)
return XcodeSDK::AppleTVSimulator;
return XcodeSDK::AppleTVOS;
case Triple::WatchOS:
if (triple.getEnvironment() == Triple::Simulator)
return XcodeSDK::WatchSimulator;
return XcodeSDK::watchOS;
case Triple::Linux:
return XcodeSDK::Linux;
default:
return XcodeSDK::unknown;
}
}