mirror of
https://github.com/intel/llvm.git
synced 2026-01-18 16:50:51 +08:00
This is mostly useful for Swift support; it allows LLDB to substitute a matching SDK it shipped with instead of the sysroot path that was used at compile time. The goal of this is to make the Xcode SDK something that behaves more like the compiler's resource directory, as in that it ships with LLDB rather than with the debugged program. This important primarily for importing Swift and Clang modules in the expression evaluator, and getting at the APINotes from the SDK in Swift. For a cross-debugging scenario, this means you have to have an SDK for your target installed alongside LLDB. In Xcode this will always be the case. rdar://problem/60640017 Differential Revision: https://reviews.llvm.org/D76471
164 lines
4.5 KiB
C++
164 lines
4.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/FileSpec.h"
|
|
#include "lldb/Utility/XcodeSDK.h"
|
|
|
|
#include "lldb/lldb-types.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
std::tuple<XcodeSDK::Type, llvm::VersionTuple> XcodeSDK::Parse() const {
|
|
llvm::StringRef input(m_name);
|
|
XcodeSDK::Type sdk = ParseSDKName(input);
|
|
llvm::VersionTuple version = ParseSDKVersion(input);
|
|
return {sdk, version};
|
|
}
|
|
|
|
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; }
|
|
|
|
void XcodeSDK::Merge(XcodeSDK other) {
|
|
// The "bigger" SDK always wins.
|
|
if (Parse() < other.Parse())
|
|
*this = other;
|
|
}
|
|
|
|
llvm::StringRef XcodeSDK::GetSDKNameForType(XcodeSDK::Type type) {
|
|
switch (type) {
|
|
case MacOSX:
|
|
return "macosx";
|
|
case iPhoneSimulator:
|
|
return "iphonesimulator";
|
|
case iPhoneOS:
|
|
return "iphoneos";
|
|
case AppleTVSimulator:
|
|
return "appletvsimulator";
|
|
case AppleTVOS:
|
|
return "appletvos";
|
|
case WatchSimulator:
|
|
return "watchsimulator";
|
|
case watchOS:
|
|
return "watchos";
|
|
case bridgeOS:
|
|
return "bridgeos";
|
|
case Linux:
|
|
return "linux";
|
|
case numSDKTypes:
|
|
case unknown:
|
|
return "";
|
|
}
|
|
llvm_unreachable("unhandled switch case");
|
|
}
|
|
|
|
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::SDKSupportsModules(XcodeSDK::Type desired_type,
|
|
const FileSpec &sdk_path) {
|
|
ConstString last_path_component = sdk_path.GetLastPathComponent();
|
|
|
|
if (last_path_component) {
|
|
const llvm::StringRef sdk_name = last_path_component.GetStringRef();
|
|
|
|
const std::string sdk_name_lower = sdk_name.lower();
|
|
const llvm::StringRef sdk_string = GetSDKNameForType(desired_type);
|
|
if (!llvm::StringRef(sdk_name_lower).startswith(sdk_string))
|
|
return false;
|
|
|
|
auto version_part = sdk_name.drop_front(sdk_string.size());
|
|
version_part.consume_back(".sdk");
|
|
|
|
llvm::VersionTuple version;
|
|
if (version.tryParse(version_part))
|
|
return false;
|
|
return SDKSupportsModules(desired_type, version);
|
|
}
|
|
|
|
return false;
|
|
}
|