From d1c62fac2bafea1f65feadf711ecf147ab998ae9 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 22 Apr 2020 14:22:54 -0700 Subject: [PATCH 1/3] Add an internal bit to the XcodeSDK class. For developing the OS itself there exists an "internal" variant of each SDK. This patch adds support for these SDK directories to the XcodeSDK class. Differential Revision: https://reviews.llvm.org/D78675 (cherry picked from commit 79feafa5147af3cfaa821a5488ac40ed8b79b072) --- lldb/include/lldb/Utility/XcodeSDK.h | 22 ++++- .../Host/macosx/objcxx/HostInfoMacOSX.mm | 87 ++++++++++++------ lldb/source/Utility/XcodeSDK.cpp | 81 +++++++++++++---- lldb/unittests/Host/HostInfoTest.cpp | 10 ++ lldb/unittests/Utility/XcodeSDKTest.cpp | 91 ++++++++++++++++--- 5 files changed, 223 insertions(+), 68 deletions(-) diff --git a/lldb/include/lldb/Utility/XcodeSDK.h b/lldb/include/lldb/Utility/XcodeSDK.h index 9b9f1d226bf09..f7516215e1bbe 100644 --- a/lldb/include/lldb/Utility/XcodeSDK.h +++ b/lldb/include/lldb/Utility/XcodeSDK.h @@ -21,6 +21,9 @@ class XcodeSDK { public: XcodeSDK() = default; + /// Initialize an XcodeSDK object with an SDK name. The SDK name is the last + /// directory component of a path one would pass to clang's -isysroot + /// parameter. For example, "MacOSX.10.14.sdk". XcodeSDK(std::string &&name) : m_name(std::move(name)) {} static XcodeSDK GetAnyMacOS() { return XcodeSDK("MacOSX.sdk"); } @@ -37,7 +40,6 @@ class XcodeSDK { numSDKTypes, unknown = -1 }; - static llvm::StringRef GetNameForType(Type type); /// The merge function follows a strict order to maintain monotonicity: /// 1. SDK with the higher SDKType wins. @@ -47,15 +49,27 @@ class XcodeSDK { XcodeSDK &operator=(XcodeSDK other); bool operator==(XcodeSDK other); - /// Return parsed SDK number, and SDK version number. - std::tuple Parse() const; + /// A parsed SDK directory name. + struct Info { + Type type = unknown; + llvm::VersionTuple version; + bool internal = false; + + Info() = default; + bool operator<(const Info &other) const; + }; + + /// Return parsed SDK type and version number. + Info Parse() const; + bool IsAppleInternalSDK() const; llvm::VersionTuple GetVersion() const; Type GetType() const; llvm::StringRef GetString() const; static bool SDKSupportsModules(Type type, llvm::VersionTuple version); static bool SDKSupportsModules(Type desired_type, const FileSpec &sdk_path); - static llvm::StringRef GetSDKNameForType(Type type); + /// Return the canonical SDK name, such as "macosx" for the macOS SDK. + static std::string GetCanonicalName(Info info); }; } // namespace lldb_private diff --git a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm index c09339e8c6731..e495c752cb193 100644 --- a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm +++ b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm @@ -298,37 +298,66 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) { } std::string HostInfoMacOSX::GetXcodeSDK(XcodeSDK sdk) { - std::string xcrun_cmd = "xcrun --show-sdk-path --sdk " + - XcodeSDK::GetSDKNameForType(sdk.GetType()).str(); - llvm::VersionTuple version = sdk.GetVersion(); - if (!version.empty()) - xcrun_cmd += version.getAsString(); - - int status = 0; - int signo = 0; - std::string output_str; - lldb_private::Status error = - Host::RunShellCommand(xcrun_cmd.c_str(), FileSpec(), &status, &signo, - &output_str, std::chrono::seconds(15)); - - // Check that xcrun return something useful. - if (status != 0 || output_str.empty()) - return {}; - - // Convert to a StringRef so we can manipulate the string without modifying - // the underlying data. - llvm::StringRef output(output_str); - - // Remove any trailing newline characters. - output = output.rtrim(); + XcodeSDK::Info info = sdk.Parse(); + std::string sdk_name = XcodeSDK::GetCanonicalName(info); + auto find_sdk = [](std::string sdk_name) -> std::string { + std::string xcrun_cmd = "xcrun --show-sdk-path --sdk " + sdk_name; + int status = 0; + int signo = 0; + std::string output_str; + lldb_private::Status error = + Host::RunShellCommand(xcrun_cmd.c_str(), FileSpec(), &status, &signo, + &output_str, std::chrono::seconds(15)); + + // Check that xcrun return something useful. + if (status != 0 || output_str.empty()) + return {}; + + // Convert to a StringRef so we can manipulate the string without modifying + // the underlying data. + llvm::StringRef output(output_str); + + // Remove any trailing newline characters. + output = output.rtrim(); + + // Strip any leading newline characters and everything before them. + const size_t last_newline = output.rfind('\n'); + if (last_newline != llvm::StringRef::npos) + output = output.substr(last_newline + 1); + + return output.str(); + }; + + std::string path = find_sdk(sdk_name); + while (path.empty()) { + // Try an alternate spelling of the name ("macosx10.9internal"). + if (info.type == XcodeSDK::Type::MacOSX && !info.version.empty() && + info.internal) { + llvm::StringRef fixed(sdk_name); + if (fixed.consume_back(".internal")) + sdk_name = fixed.str() + "internal"; + path = find_sdk(sdk_name); + if (!path.empty()) + break; + } + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + LLDB_LOGF(log, "Couldn't find SDK %s on host", sdk_name.c_str()); + + // Try without the version. + if (!info.version.empty()) { + info.version = {}; + sdk_name = XcodeSDK::GetCanonicalName(info); + path = find_sdk(sdk_name); + if (!path.empty()) + break; + } - // Strip any leading newline characters and everything before them. - const size_t last_newline = output.rfind('\n'); - if (last_newline != llvm::StringRef::npos) - output = output.substr(last_newline + 1); + LLDB_LOGF(log, "Couldn't find any matching SDK on host"); + return {}; + } // Whatever is left in output should be a valid path. - if (!FileSystem::Instance().Exists(output)) + if (!FileSystem::Instance().Exists(path)) return {}; - return output.str(); + return path; } diff --git a/lldb/source/Utility/XcodeSDK.cpp b/lldb/source/Utility/XcodeSDK.cpp index 7ad0090f85e2d..a34eac6b2c95b 100644 --- a/lldb/source/Utility/XcodeSDK.cpp +++ b/lldb/source/Utility/XcodeSDK.cpp @@ -64,13 +64,24 @@ static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) { return version; } +static bool ParseAppleInternalSDK(llvm::StringRef &name) { + return 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; +} -std::tuple XcodeSDK::Parse() const { +bool XcodeSDK::IsAppleInternalSDK() const { llvm::StringRef input(m_name); - XcodeSDK::Type sdk = ParseSDKName(input); - llvm::VersionTuple version = ParseSDKVersion(input); - return std::make_tuple( - std::move(sdk), std::move(version)); + ParseSDKName(input); + ParseSDKVersion(input); + return ParseAppleInternalSDK(input); } llvm::VersionTuple XcodeSDK::GetVersion() const { @@ -86,37 +97,64 @@ XcodeSDK::Type XcodeSDK::GetType() const { 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); +} void XcodeSDK::Merge(XcodeSDK other) { // The "bigger" SDK always wins. - if (Parse() < other.Parse()) + 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"); + } } -llvm::StringRef XcodeSDK::GetSDKNameForType(XcodeSDK::Type type) { - switch (type) { +std::string XcodeSDK::GetCanonicalName(XcodeSDK::Info info) { + std::string name; + switch (info.type) { case MacOSX: - return "macosx"; + name = "macosx"; + break; case iPhoneSimulator: - return "iphonesimulator"; + name = "iphonesimulator"; + break; case iPhoneOS: - return "iphoneos"; + name = "iphoneos"; + break; case AppleTVSimulator: - return "appletvsimulator"; + name = "appletvsimulator"; + break; case AppleTVOS: - return "appletvos"; + name = "appletvos"; + break; case WatchSimulator: - return "watchsimulator"; + name = "watchsimulator"; + break; case watchOS: - return "watchos"; + name = "watchos"; + break; case bridgeOS: - return "bridgeos"; + name = "bridgeos"; + break; case Linux: - return "linux"; + name = "linux"; + break; case numSDKTypes: case unknown: - return ""; + return {}; } - llvm_unreachable("unhandled switch case"); + if (!info.version.empty()) + name += info.version.getAsString(); + if (info.internal) + name += ".internal"; + return name; } bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type sdk_type, @@ -147,12 +185,15 @@ bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type desired_type, 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); + Info info; + info.type = desired_type; + const llvm::StringRef sdk_string = GetCanonicalName(info); 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"); + version_part.consume_back(".Internal"); llvm::VersionTuple version; if (version.tryParse(version_part)) diff --git a/lldb/unittests/Host/HostInfoTest.cpp b/lldb/unittests/Host/HostInfoTest.cpp index 450cb9edc5cd6..24a178ab64058 100644 --- a/lldb/unittests/Host/HostInfoTest.cpp +++ b/lldb/unittests/Host/HostInfoTest.cpp @@ -50,3 +50,13 @@ TEST_F(HostInfoTest, GetHostname) { std::string s("abc"); EXPECT_TRUE(HostInfo::GetHostname(s)); } + +#if defined(__APPLE__) +TEST_F(HostInfoTest, GetXcodeSDK) { + EXPECT_FALSE(HostInfo::GetXcodeSDK(XcodeSDK("MacOSX.sdk")).empty()); + // These are expected to fall back to an available version. + EXPECT_FALSE(HostInfo::GetXcodeSDK(XcodeSDK("MacOSX9999.sdk")).empty()); + // This is expected to fail. + EXPECT_TRUE(HostInfo::GetXcodeSDK(XcodeSDK("CeciNestPasUnOS.sdk")).empty()); +} +#endif diff --git a/lldb/unittests/Utility/XcodeSDKTest.cpp b/lldb/unittests/Utility/XcodeSDKTest.cpp index a316516a16758..95b909e700184 100644 --- a/lldb/unittests/Utility/XcodeSDKTest.cpp +++ b/lldb/unittests/Utility/XcodeSDKTest.cpp @@ -30,6 +30,11 @@ TEST(XcodeSDKTest, ParseTest) { EXPECT_EQ(XcodeSDK("MacOSX.sdk").GetVersion(), llvm::VersionTuple()); EXPECT_EQ(XcodeSDK("MacOSX10.9.sdk").GetVersion(), llvm::VersionTuple(10, 9)); EXPECT_EQ(XcodeSDK("MacOSX10.15.4.sdk").GetVersion(), llvm::VersionTuple(10, 15)); + EXPECT_EQ(XcodeSDK("MacOSX.sdk").IsAppleInternalSDK(), false); + EXPECT_EQ(XcodeSDK("MacOSX10.15.Internal.sdk").GetType(), XcodeSDK::MacOSX); + EXPECT_EQ(XcodeSDK("MacOSX10.15.Internal.sdk").GetVersion(), + llvm::VersionTuple(10, 15)); + EXPECT_EQ(XcodeSDK("MacOSX10.15.Internal.sdk").IsAppleInternalSDK(), true); EXPECT_EQ(XcodeSDK().GetType(), XcodeSDK::unknown); EXPECT_EQ(XcodeSDK().GetVersion(), llvm::VersionTuple()); } @@ -46,6 +51,12 @@ TEST(XcodeSDKTest, MergeTest) { EXPECT_EQ(sdk.GetVersion(), llvm::VersionTuple(1, 1)); sdk.Merge(XcodeSDK("WatchOS2.0.sdk")); EXPECT_EQ(sdk.GetVersion(), llvm::VersionTuple(2, 0)); + sdk.Merge(XcodeSDK("WatchOS1.1.Internal.sdk")); + EXPECT_EQ(sdk.GetVersion(), llvm::VersionTuple(2, 0)); + EXPECT_EQ(sdk.IsAppleInternalSDK(), true); + XcodeSDK empty; + empty.Merge(XcodeSDK("MacOSX10.14.Internal.sdk")); + EXPECT_EQ(empty.GetString(), llvm::StringRef("MacOSX10.14.Internal.sdk")); } TEST(XcodeSDKTest, SDKSupportsModules) { @@ -55,6 +66,10 @@ TEST(XcodeSDKTest, SDKSupportsModules) { FileSpec( base + "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.0.sdk"))); + EXPECT_TRUE(XcodeSDK::SDKSupportsModules( + XcodeSDK::Type::iPhoneSimulator, + FileSpec(base + "iPhoneSimulator.platform/Developer/SDKs/" + "iPhoneSimulator12.0.Internal.sdk"))); EXPECT_FALSE(XcodeSDK::SDKSupportsModules( XcodeSDK::Type::iPhoneSimulator, FileSpec( @@ -68,19 +83,65 @@ TEST(XcodeSDKTest, SDKSupportsModules) { FileSpec(base + "MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk"))); } -TEST(XcodeSDKTest, GetSDKNameForType) { - EXPECT_EQ("macosx", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::MacOSX)); - EXPECT_EQ("iphonesimulator", - XcodeSDK::GetSDKNameForType(XcodeSDK::Type::iPhoneSimulator)); - EXPECT_EQ("iphoneos", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::iPhoneOS)); - EXPECT_EQ("appletvsimulator", - XcodeSDK::GetSDKNameForType(XcodeSDK::Type::AppleTVSimulator)); - EXPECT_EQ("appletvos", - XcodeSDK::GetSDKNameForType(XcodeSDK::Type::AppleTVOS)); - EXPECT_EQ("watchsimulator", - XcodeSDK::GetSDKNameForType(XcodeSDK::Type::WatchSimulator)); - EXPECT_EQ("watchos", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::watchOS)); - EXPECT_EQ("linux", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::Linux)); - EXPECT_EQ("", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::numSDKTypes)); - EXPECT_EQ("", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::unknown)); +TEST(XcodeSDKTest, GetCanonicalName) { + XcodeSDK::Info info; + info.type = XcodeSDK::Type::MacOSX; + EXPECT_EQ("macosx", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::iPhoneSimulator; + EXPECT_EQ("iphonesimulator", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::iPhoneOS; + EXPECT_EQ("iphoneos", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::AppleTVSimulator; + EXPECT_EQ("appletvsimulator", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::AppleTVOS; + EXPECT_EQ("appletvos", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::WatchSimulator; + EXPECT_EQ("watchsimulator", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::watchOS; + EXPECT_EQ("watchos", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::Linux; + EXPECT_EQ("linux", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::numSDKTypes; + EXPECT_EQ("", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::unknown; + EXPECT_EQ("", XcodeSDK::GetCanonicalName(info)); + + info.internal = true; + info.type = XcodeSDK::Type::MacOSX; + EXPECT_EQ("macosx.internal", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::iPhoneSimulator; + EXPECT_EQ("iphonesimulator.internal", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::iPhoneOS; + EXPECT_EQ("iphoneos.internal", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::AppleTVSimulator; + EXPECT_EQ("appletvsimulator.internal", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::AppleTVOS; + EXPECT_EQ("appletvos.internal", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::WatchSimulator; + EXPECT_EQ("watchsimulator.internal", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::watchOS; + EXPECT_EQ("watchos.internal", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::MacOSX; + info.version = llvm::VersionTuple(10, 9); + EXPECT_EQ("macosx10.9.internal", XcodeSDK::GetCanonicalName(info)); + + info.type = XcodeSDK::Type::iPhoneOS; + info.version = llvm::VersionTuple(7, 0); + EXPECT_EQ("iphoneos7.0.internal", XcodeSDK::GetCanonicalName(info)); } From 9d38665ced27e4b73141c19e0efdb9a6f837e8d6 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 24 Apr 2020 17:15:55 -0700 Subject: [PATCH 2/3] Add a getter to retrieve the XcodeSDK from Module --- lldb/include/lldb/Core/Module.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 8cde45ad6c784..08a858858ebce 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -875,6 +875,11 @@ class Module : public std::enable_shared_from_this, std::vector GetASTData(lldb::LanguageType language); + /// Return the Xcode SDK this module was compiled against. This + /// is computed by merging the SDKs from each compilation unit in + /// the module. + XcodeSDK GetXcodeSDK() const { return m_xcode_sdk; } + /// Update the ArchSpec to a more specific variant. bool MergeArchitecture(const ArchSpec &arch_spec); From 0d76f0c10347b21e614545935abccf6e9be76065 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 24 Apr 2020 14:21:16 -0700 Subject: [PATCH 3/3] Add support for detecting the SDK based on the SDK info in DWARF. rdar://problem/60640017 --- lldb/source/Symbol/SwiftASTContext.cpp | 42 ++++++++++--------- lldb/test/API/lang/swift/xcode_sdk/Makefile | 4 ++ .../API/lang/swift/xcode_sdk/TestXcodeSDK.py | 38 +++++++++++++++++ lldb/test/API/lang/swift/xcode_sdk/main.swift | 1 + 4 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 lldb/test/API/lang/swift/xcode_sdk/Makefile create mode 100644 lldb/test/API/lang/swift/xcode_sdk/TestXcodeSDK.py create mode 100644 lldb/test/API/lang/swift/xcode_sdk/main.swift diff --git a/lldb/source/Symbol/SwiftASTContext.cpp b/lldb/source/Symbol/SwiftASTContext.cpp index 6e5f89eef56c0..521a06d601324 100644 --- a/lldb/source/Symbol/SwiftASTContext.cpp +++ b/lldb/source/Symbol/SwiftASTContext.cpp @@ -998,7 +998,9 @@ static SDKTypeMinVersion GetSDKType(const llvm::Triple &target, StringRef SwiftASTContext::GetSwiftStdlibOSDir(const llvm::Triple &target, const llvm::Triple &host) { auto sdk = GetSDKType(target, host); - llvm::StringRef sdk_name = XcodeSDK::GetSDKNameForType(sdk.sdk_type); + XcodeSDK::Info sdk_info; + sdk_info.type = sdk.sdk_type; + llvm::StringRef sdk_name = XcodeSDK::GetCanonicalName(sdk_info); if (!sdk_name.empty()) return sdk_name; return target.getOSName(); @@ -1668,17 +1670,21 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language, set_triple = true; } + // SDK path setup. llvm::StringRef serialized_sdk_path = swift_ast_sp->GetCompilerInvocation().getSDKPath(); - if (serialized_sdk_path.empty()) { + if (serialized_sdk_path.empty()) LOG_PRINTF(LIBLLDB_LOG_TYPES, "No serialized SDK path."); - } else { - LOG_PRINTF(LIBLLDB_LOG_TYPES, "Got serialized SDK path %s.", + else + LOG_PRINTF(LIBLLDB_LOG_TYPES, "Serialized SDK path is %s.", serialized_sdk_path.str().c_str()); - FileSpec sdk_spec(serialized_sdk_path.str().c_str()); - if (FileSystem::Instance().Exists(sdk_spec)) { - swift_ast_sp->SetPlatformSDKPath(serialized_sdk_path); - } + XcodeSDK sdk = module.GetXcodeSDK(); + PlatformSP platform = + Platform::GetPlatformForArchitecture(module.GetArchitecture(), nullptr); + std::string sdk_path = platform->GetSDKPath(sdk); + LOG_PRINTF(LIBLLDB_LOG_TYPES, "Host SDK path is %s.", sdk_path.c_str()); + if (FileSystem::Instance().Exists(sdk_path)) { + swift_ast_sp->SetPlatformSDKPath(sdk_path); } } @@ -2668,14 +2674,6 @@ void SwiftASTContext::InitializeSearchPathOptions( // someone is passing this to us on the command line (e.g., for the // REPL), they probably know what they're doing. - set_sdk = true; - } - } else if (!m_platform_sdk_path.empty()) { - FileSpec platform_sdk(m_platform_sdk_path.c_str()); - - if (FileSystem::Instance().Exists(platform_sdk) && - SDKSupportsSwift(platform_sdk, XcodeSDK::Type::unknown)) { - invocation.setSDKPath(m_platform_sdk_path.c_str()); set_sdk = true; } } @@ -2694,13 +2692,19 @@ void SwiftASTContext::InitializeSearchPathOptions( auto sdk = GetSDKType(triple, HostInfo::GetArchitecture().GetTriple()); // Explicitly leave the SDKPath blank on other platforms. if (sdk.sdk_type != XcodeSDK::Type::unknown) { - auto dir = GetSDKDirectory(sdk.sdk_type, sdk.min_version_major, - sdk.min_version_minor); + std::string sdk_path = m_platform_sdk_path; + if (sdk_path.empty() || !FileSystem::Instance().Exists(sdk_path) || + !SDKSupportsSwift(FileSpec(sdk_path), sdk.sdk_type)) { + sdk_path = GetSDKDirectory(sdk.sdk_type, sdk.min_version_major, + sdk.min_version_minor) + .GetStringRef() + .str(); + } // Note that calling setSDKPath() also recomputes all paths that // depend on the SDK path including the // RuntimeLibraryImportPaths, which are *only* initialized // through this mechanism. - invocation.setSDKPath(dir.AsCString("")); + invocation.setSDKPath(sdk_path); } std::vector &lpaths = diff --git a/lldb/test/API/lang/swift/xcode_sdk/Makefile b/lldb/test/API/lang/swift/xcode_sdk/Makefile new file mode 100644 index 0000000000000..13d4d1a086bff --- /dev/null +++ b/lldb/test/API/lang/swift/xcode_sdk/Makefile @@ -0,0 +1,4 @@ +SWIFT_SOURCES := main.swift +SWIFTFLAGS_EXTRAS := -Xfrontend -no-serialize-debugging-options + +include Makefile.rules diff --git a/lldb/test/API/lang/swift/xcode_sdk/TestXcodeSDK.py b/lldb/test/API/lang/swift/xcode_sdk/TestXcodeSDK.py new file mode 100644 index 0000000000000..5b118f0b3192f --- /dev/null +++ b/lldb/test/API/lang/swift/xcode_sdk/TestXcodeSDK.py @@ -0,0 +1,38 @@ +import lldb +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbtest as lldbtest +import lldbsuite.test.lldbutil as lldbutil +import os +import unittest2 + + +class TestSwiftAppleInternalSDK(lldbtest.TestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @swiftTest + @skipUnlessDarwin + @skipIfDarwinEmbedded + def test(self): + """Test that we can detect an Xcode SDK from the DW_AT_APPLE_sdk attribute.""" + self.build() + log = self.getBuildArtifact("types.log") + command_result = lldb.SBCommandReturnObject() + interpreter = self.dbg.GetCommandInterpreter() + interpreter.HandleCommand("log enable lldb types -f "+log, command_result) + + target, process, thread, bkpt = lldbutil.run_to_name_breakpoint( + self, 'main') + + self.expect("p 1") + logfile = open(log, "r") + in_expr_log = 0 + found = 0 + for line in logfile: + if line.startswith(" SwiftASTContextForExpressions::LogConfiguration"): + in_expr_log += 1 + if in_expr_log and "SDK path" in line and ".sdk" in line: + found += 1 + self.assertEqual(in_expr_log, 1) + self.assertEqual(found, 1) diff --git a/lldb/test/API/lang/swift/xcode_sdk/main.swift b/lldb/test/API/lang/swift/xcode_sdk/main.swift new file mode 100644 index 0000000000000..4fdc9b23df9d8 --- /dev/null +++ b/lldb/test/API/lang/swift/xcode_sdk/main.swift @@ -0,0 +1 @@ +print("I have loaded Swift successfully - break here")