[Lldb-commits] [lldb] 1e05d7b - Remap the target (Xcode) SDK directory to the host SDK directory.

Adrian Prantl via lldb-commits lldb-commits at lists.llvm.org
Mon Apr 6 15:51:59 PDT 2020


Author: Adrian Prantl
Date: 2020-04-06T15:51:30-07:00
New Revision: 1e05d7b3d3c6d29ff6f9493cc478a36244cc32bd

URL: https://github.com/llvm/llvm-project/commit/1e05d7b3d3c6d29ff6f9493cc478a36244cc32bd
DIFF: https://github.com/llvm/llvm-project/commit/1e05d7b3d3c6d29ff6f9493cc478a36244cc32bd.diff

LOG: Remap the target (Xcode) SDK directory to the host SDK directory.

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

Added: 
    lldb/include/lldb/Utility/XcodeSDK.h
    lldb/source/Utility/XcodeSDK.cpp
    lldb/unittests/Utility/XcodeSDKTest.cpp

Modified: 
    lldb/include/lldb/Core/Module.h
    lldb/include/lldb/Host/HostInfoBase.h
    lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
    lldb/include/lldb/Target/Platform.h
    lldb/source/Core/Module.cpp
    lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
    lldb/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h
    lldb/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h
    lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
    lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
    lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
    lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
    lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
    lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
    lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
    lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/source/Utility/CMakeLists.txt
    lldb/unittests/Platform/PlatformDarwinTest.cpp
    lldb/unittests/Utility/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index 4715961eabf1..35d00d295fa8 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -20,6 +20,7 @@
 #include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/Status.h"
+#include "lldb/Utility/XcodeSDK.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-defines.h"
 #include "lldb/lldb-enumerations.h"
@@ -509,6 +510,12 @@ class Module : public std::enable_shared_from_this<Module>,
     m_mod_time = mod_time;
   }
 
+  /// This callback will be called by SymbolFile implementations when
+  /// parsing a compile unit that contains SDK information.
+  /// \param sdk will be merged with \p m_sdk.
+  /// \param sysroot will be added to the path remapping dictionary.
+  void RegisterXcodeSDK(llvm::StringRef sdk, llvm::StringRef sysroot);
+
   /// Tells whether this module is capable of being the main executable for a
   /// process.
   ///
@@ -971,6 +978,10 @@ class Module : public std::enable_shared_from_this<Module>,
   /// module that doesn't match where the sources currently are.
   PathMappingList m_source_mappings =
       ModuleList::GetGlobalModuleListProperties().GetSymlinkMappings();
+
+  /// The (Xcode) SDK this module was compiled with.
+  XcodeSDK m_xcode_sdk;
+  
   lldb::SectionListUP m_sections_up; ///< Unified section list for module that
                                      /// is used by the ObjectFile and and
                                      /// ObjectFile instances for the debug info

diff  --git a/lldb/include/lldb/Host/HostInfoBase.h b/lldb/include/lldb/Host/HostInfoBase.h
index d7c28061b10c..f195a9a1f021 100644
--- a/lldb/include/lldb/Host/HostInfoBase.h
+++ b/lldb/include/lldb/Host/HostInfoBase.h
@@ -12,6 +12,7 @@
 #include "lldb/Utility/ArchSpec.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/UserIDResolver.h"
+#include "lldb/Utility/XcodeSDK.h"
 #include "lldb/lldb-enumerations.h"
 #include "llvm/ADT/StringRef.h"
 
@@ -91,6 +92,9 @@ class HostInfoBase {
   static bool ComputePathRelativeToLibrary(FileSpec &file_spec,
                                            llvm::StringRef dir);
 
+  /// Return the directory containing a specific Xcode SDK.
+  static std::string GetXcodeSDK(XcodeSDK sdk) { return {}; }
+
 protected:
   static bool ComputeSharedLibraryDirectory(FileSpec &file_spec);
   static bool ComputeSupportExeDirectory(FileSpec &file_spec);

diff  --git a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
index cd5161c4159f..fdbe869ea475 100644
--- a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
+++ b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
@@ -11,6 +11,7 @@
 
 #include "lldb/Host/posix/HostInfoPosix.h"
 #include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/XcodeSDK.h"
 #include "llvm/Support/VersionTuple.h"
 
 namespace lldb_private {
@@ -31,7 +32,10 @@ class HostInfoMacOSX : public HostInfoPosix {
   static bool GetOSBuildString(std::string &s);
   static bool GetOSKernelDescription(std::string &s);
   static FileSpec GetProgramFileSpec();
+  static std::string FindXcodeContentsDirectoryInPath(llvm::StringRef path);
 
+  /// Query xcrun to find an Xcode SDK directory.
+  static std::string GetXcodeSDK(XcodeSDK sdk);
 protected:
   static bool ComputeSupportExeDirectory(FileSpec &file_spec);
   static void ComputeHostArchitectureSupport(ArchSpec &arch_32,

diff  --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index 190ad0653073..029bb590de68 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -434,6 +434,10 @@ class Platform : public PluginInterface {
     return lldb_private::ConstString();
   }
 
+  virtual llvm::StringRef GetSDKPath(lldb_private::XcodeSDK sdk) {
+    return {};
+  }
+
   const std::string &GetRemoteURL() const { return m_remote_url; }
 
   bool IsHost() const {

diff  --git a/lldb/include/lldb/Utility/XcodeSDK.h b/lldb/include/lldb/Utility/XcodeSDK.h
new file mode 100644
index 000000000000..9b9f1d226bf0
--- /dev/null
+++ b/lldb/include/lldb/Utility/XcodeSDK.h
@@ -0,0 +1,63 @@
+//===-- XcodeSDK.h ----------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_SDK_H
+#define LLDB_UTILITY_SDK_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/VersionTuple.h"
+#include <tuple>
+
+namespace lldb_private {
+
+/// An abstraction for Xcode-style SDKs that works like \ref ArchSpec.
+class XcodeSDK {
+  std::string m_name;
+
+public:
+  XcodeSDK() = default;
+  XcodeSDK(std::string &&name) : m_name(std::move(name)) {}
+  static XcodeSDK GetAnyMacOS() { return XcodeSDK("MacOSX.sdk"); }
+
+  enum Type : int {
+    MacOSX = 0,
+    iPhoneSimulator,
+    iPhoneOS,
+    AppleTVSimulator,
+    AppleTVOS,
+    WatchSimulator,
+    watchOS,
+    bridgeOS,
+    Linux,
+    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.
+  /// 2. The newer SDK wins.
+  void Merge(XcodeSDK other);
+
+  XcodeSDK &operator=(XcodeSDK other);
+  bool operator==(XcodeSDK other);
+
+  /// Return parsed SDK number, and SDK version number.
+  std::tuple<Type, llvm::VersionTuple> Parse() 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);
+};
+
+} // namespace lldb_private
+
+#endif

diff  --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index fefc23a9b1c5..658bcff6739d 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -1596,6 +1596,24 @@ bool Module::RemapSourceFile(llvm::StringRef path,
   return m_source_mappings.RemapPath(path, new_path);
 }
 
+void Module::RegisterXcodeSDK(llvm::StringRef sdk_name, llvm::StringRef sysroot) {
+  XcodeSDK sdk(sdk_name.str());
+  if (m_xcode_sdk == sdk)
+    return;
+  m_xcode_sdk.Merge(sdk);
+  PlatformSP module_platform =
+      Platform::GetPlatformForArchitecture(GetArchitecture(), nullptr);
+  ConstString sdk_path(module_platform->GetSDKPath(sdk));
+  if (!sdk_path)
+    return;
+  // If merged SDK changed for a previously registered source path, update it.
+  // This could happend with -fdebug-prefix-map, otherwise it's unlikely.
+  ConstString sysroot_cs(sysroot);
+  if (!m_source_mappings.Replace(sysroot_cs, sdk_path, true))
+    // In the general case, however, append it to the list.
+    m_source_mappings.Append(sysroot_cs, sdk_path, false);
+}
+
 bool Module::MergeArchitecture(const ArchSpec &arch_spec) {
   if (!arch_spec.IsValid())
     return false;

diff  --git a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
index e73d2ffe9b9a..c09339e8c673 100644
--- a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
+++ b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
@@ -8,6 +8,7 @@
 
 #include "lldb/Host/macosx/HostInfoMacOSX.h"
 #include "lldb/Host/FileSystem.h"
+#include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Utility/Args.h"
 #include "lldb/Utility/Log.h"
@@ -295,3 +296,39 @@ 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();
+
+  // 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);
+
+  // Whatever is left in output should be a valid path.
+  if (!FileSystem::Instance().Exists(output))
+    return {};
+  return output.str();
+}

diff  --git a/lldb/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h b/lldb/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h
index 34cbff99cc15..2170e03e4552 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h
@@ -69,7 +69,7 @@ class PlatformAppleTVSimulator : public PlatformDarwin {
   AddClangModuleCompilationOptions(lldb_private::Target *target,
                                    std::vector<std::string> &options) override {
     return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
-        target, options, PlatformDarwin::SDKType::iPhoneSimulator);
+        target, options, lldb_private::XcodeSDK::Type::iPhoneSimulator);
   }
 
 protected:

diff  --git a/lldb/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h b/lldb/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h
index 04c3eb10d1d1..eceb3f08886b 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h
@@ -69,7 +69,7 @@ class PlatformAppleWatchSimulator : public PlatformDarwin {
   AddClangModuleCompilationOptions(lldb_private::Target *target,
                                    std::vector<std::string> &options) override {
     return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
-        target, options, PlatformDarwin::SDKType::iPhoneSimulator);
+        target, options, lldb_private::XcodeSDK::Type::iPhoneSimulator);
   }
 
 protected:

diff  --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index e1633007f23f..0777c78aa22d 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -1220,56 +1220,12 @@ static FileSpec GetCommandLineToolsLibraryPath() {
   return g_command_line_tools_filespec;
 }
 
-bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type,
-                                        llvm::VersionTuple version) {
-  switch (sdk_type) {
-  case SDKType::MacOSX:
-    return version >= llvm::VersionTuple(10, 10);
-  case SDKType::iPhoneOS:
-  case SDKType::iPhoneSimulator:
-  case SDKType::AppleTVOS:
-  case SDKType::AppleTVSimulator:
-    return version >= llvm::VersionTuple(8);
-  case SDKType::watchOS:
-  case SDKType::WatchSimulator:
-    return version >= llvm::VersionTuple(6);
-  default:
-    return false;
-  }
-
-  return false;
-}
-
-bool PlatformDarwin::SDKSupportsModules(SDKType 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;
-}
-
 FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator(
     void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) {
   SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton);
 
   FileSpec spec(path);
-  if (SDKSupportsModules(enumerator_info->sdk_type, spec)) {
+  if (XcodeSDK::SDKSupportsModules(enumerator_info->sdk_type, spec)) {
     enumerator_info->found_path = spec;
     return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
   }
@@ -1277,7 +1233,7 @@ FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator(
   return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
 }
 
-FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type,
+FileSpec PlatformDarwin::FindSDKInXcodeForModules(XcodeSDK::Type sdk_type,
                                                   const FileSpec &sdks_spec) {
   // Look inside Xcode for the required installed iOS SDK version
 
@@ -1303,19 +1259,19 @@ FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type,
     return FileSpec();
 }
 
-FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) {
+FileSpec PlatformDarwin::GetSDKDirectoryForModules(XcodeSDK::Type sdk_type) {
   FileSpec sdks_spec = GetXcodeContentsDirectory();
   sdks_spec.AppendPathComponent("Developer");
   sdks_spec.AppendPathComponent("Platforms");
 
   switch (sdk_type) {
-  case SDKType::MacOSX:
+  case XcodeSDK::Type::MacOSX:
     sdks_spec.AppendPathComponent("MacOSX.platform");
     break;
-  case SDKType::iPhoneSimulator:
+  case XcodeSDK::Type::iPhoneSimulator:
     sdks_spec.AppendPathComponent("iPhoneSimulator.platform");
     break;
-  case SDKType::iPhoneOS:
+  case XcodeSDK::Type::iPhoneOS:
     sdks_spec.AppendPathComponent("iPhoneOS.platform");
     break;
   default:
@@ -1325,11 +1281,11 @@ FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) {
   sdks_spec.AppendPathComponent("Developer");
   sdks_spec.AppendPathComponent("SDKs");
 
-  if (sdk_type == SDKType::MacOSX) {
+  if (sdk_type == XcodeSDK::Type::MacOSX) {
     llvm::VersionTuple version = HostInfo::GetOSVersion();
 
     if (!version.empty()) {
-      if (SDKSupportsModules(SDKType::MacOSX, version)) {
+      if (XcodeSDK::SDKSupportsModules(XcodeSDK::Type::MacOSX, version)) {
         // If the Xcode SDKs are not available then try to use the
         // Command Line Tools one which is only for MacOSX.
         if (!FileSystem::Instance().Exists(sdks_spec)) {
@@ -1498,7 +1454,7 @@ PlatformDarwin::ExtractCrashInfoAnnotations(Process &process) {
 }
 
 void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
-    Target *target, std::vector<std::string> &options, SDKType sdk_type) {
+    Target *target, std::vector<std::string> &options, XcodeSDK::Type sdk_type) {
   const std::vector<std::string> apple_arguments = {
       "-x",       "objective-c++", "-fobjc-arc",
       "-fblocks", "-D_ISO646_H",   "-D__ISO646_H",
@@ -1509,7 +1465,7 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
   StreamString minimum_version_option;
   bool use_current_os_version = false;
   switch (sdk_type) {
-  case SDKType::iPhoneOS:
+  case XcodeSDK::Type::iPhoneOS:
 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
     use_current_os_version = true;
 #else
@@ -1517,11 +1473,11 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
 #endif
     break;
 
-  case SDKType::iPhoneSimulator:
+  case XcodeSDK::Type::iPhoneSimulator:
     use_current_os_version = false;
     break;
 
-  case SDKType::MacOSX:
+  case XcodeSDK::Type::MacOSX:
 #if defined(__i386__) || defined(__x86_64__)
     use_current_os_version = true;
 #else
@@ -1548,15 +1504,15 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
   // Only add the version-min options if we got a version from somewhere
   if (!version.empty()) {
     switch (sdk_type) {
-    case SDKType::iPhoneOS:
+    case XcodeSDK::Type::iPhoneOS:
       minimum_version_option.PutCString("-mios-version-min=");
       minimum_version_option.PutCString(version.getAsString());
       break;
-    case SDKType::iPhoneSimulator:
+    case XcodeSDK::Type::iPhoneSimulator:
       minimum_version_option.PutCString("-mios-simulator-version-min=");
       minimum_version_option.PutCString(version.getAsString());
       break;
-    case SDKType::MacOSX:
+    case XcodeSDK::Type::MacOSX:
       minimum_version_option.PutCString("-mmacosx-version-min=");
       minimum_version_option.PutCString(version.getAsString());
       break;
@@ -1805,70 +1761,11 @@ PlatformDarwin::FindXcodeContentsDirectoryInPath(llvm::StringRef path) {
   return {};
 }
 
-llvm::StringRef PlatformDarwin::GetSDKNameForType(SDKType 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");
-}
-
-FileSpec PlatformDarwin::GetXcodeSDK(SDKType type) {
-  std::string xcrun_cmd =
-      "xcrun --show-sdk-path --sdk " + GetSDKNameForType(type).str();
-
-  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);
-
-  // Whatever is left in output should be a valid path.
-  if (!FileSystem::Instance().Exists(output))
-    return {};
-
-  // Find the contents dir in the xcrun provided path.
-  std::string xcode_contents_dir = FindXcodeContentsDirectoryInPath(output);
-  if (xcode_contents_dir.empty())
-    return {};
-
-  return FileSpec(xcode_contents_dir);
+llvm::StringRef PlatformDarwin::GetSDKPath(XcodeSDK sdk) {
+  std::string &path = m_sdk_path[sdk.GetString()];
+  if (path.empty())
+    path = HostInfo::GetXcodeSDK(sdk);
+  return path;
 }
 
 FileSpec PlatformDarwin::GetXcodeContentsDirectory() {
@@ -1899,7 +1796,8 @@ FileSpec PlatformDarwin::GetXcodeContentsDirectory() {
       }
     }
 
-    if (FileSpec fspec = GetXcodeSDK(SDKType::MacOSX)) {
+    FileSpec fspec(HostInfo::GetXcodeSDK(XcodeSDK::GetAnyMacOS()));
+    if (fspec) {
       if (FileSystem::Instance().Exists(fspec)) {
         std::string xcode_contents_dir =
             FindXcodeContentsDirectoryInPath(fspec.GetPath());

diff  --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
index 619a8595fa21..7d205be59689 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
@@ -11,8 +11,10 @@
 
 #include "Plugins/Platform/POSIX/PlatformPOSIX.h"
 #include "lldb/Host/FileSystem.h"
+#include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/StructuredData.h"
+#include "lldb/Utility/XcodeSDK.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/FileSystem.h"
 
@@ -84,25 +86,11 @@ class PlatformDarwin : public PlatformPOSIX {
   static std::tuple<llvm::VersionTuple, llvm::StringRef>
   ParseVersionBuildDir(llvm::StringRef str);
 
-  enum SDKType : int {
-    MacOSX = 0,
-    iPhoneSimulator,
-    iPhoneOS,
-    AppleTVSimulator,
-    AppleTVOS,
-    WatchSimulator,
-    watchOS,
-    bridgeOS,
-    Linux,
-    numSDKTypes,
-    unknown = -1
-  };
-
   llvm::Expected<lldb_private::StructuredData::DictionarySP>
   FetchExtendedCrashInformation(lldb_private::Process &process) override;
 
-  static llvm::StringRef GetSDKNameForType(SDKType type);
-  static lldb_private::FileSpec GetXcodeSDK(SDKType type);
+  llvm::StringRef GetSDKPath(lldb_private::XcodeSDK sdk) override;
+
   static lldb_private::FileSpec GetXcodeContentsDirectory();
   static lldb_private::FileSpec GetXcodeDeveloperDirectory();
 
@@ -151,14 +139,9 @@ class PlatformDarwin : public PlatformPOSIX {
       const lldb_private::FileSpecList *module_search_paths_ptr,
       lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr);
 
-  static bool SDKSupportsModules(SDKType sdk_type, llvm::VersionTuple version);
-
-  static bool SDKSupportsModules(SDKType desired_type,
-                                 const lldb_private::FileSpec &sdk_path);
-
   struct SDKEnumeratorInfo {
     lldb_private::FileSpec found_path;
-    SDKType sdk_type;
+    lldb_private::XcodeSDK::Type sdk_type;
   };
 
   static lldb_private::FileSystem::EnumerateDirectoryResult
@@ -166,17 +149,15 @@ class PlatformDarwin : public PlatformPOSIX {
                       llvm::StringRef path);
 
   static lldb_private::FileSpec
-  FindSDKInXcodeForModules(SDKType sdk_type,
+  FindSDKInXcodeForModules(lldb_private::XcodeSDK::Type sdk_type,
                            const lldb_private::FileSpec &sdks_spec);
 
   static lldb_private::FileSpec
-  GetSDKDirectoryForModules(PlatformDarwin::SDKType sdk_type);
-
-  void
-  AddClangModuleCompilationOptionsForSDKType(lldb_private::Target *target,
-                                             std::vector<std::string> &options,
-                                             SDKType sdk_type);
+  GetSDKDirectoryForModules(lldb_private::XcodeSDK::Type sdk_type);
 
+  void AddClangModuleCompilationOptionsForSDKType(
+      lldb_private::Target *target, std::vector<std::string> &options,
+      lldb_private::XcodeSDK::Type sdk_type);
 
   lldb_private::Status FindBundleBinaryInExecSearchPaths(
       const lldb_private::ModuleSpec &module_spec,
@@ -188,6 +169,8 @@ class PlatformDarwin : public PlatformPOSIX {
                                          llvm::StringRef component);
   static std::string FindXcodeContentsDirectoryInPath(llvm::StringRef path);
 
+  std::string m_developer_directory;
+  llvm::StringMap<std::string> m_sdk_path;
 
 private:
   DISALLOW_COPY_AND_ASSIGN(PlatformDarwin);

diff  --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
index 5efb041367e3..4fcecf776bd2 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
@@ -208,7 +208,8 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) {
   }
 
   // Use the default SDK as a fallback.
-  if (FileSpec fspec = GetXcodeSDK(SDKType::MacOSX)) {
+  FileSpec fspec(HostInfo::GetXcodeSDK(lldb_private::XcodeSDK::GetAnyMacOS()));
+  if (fspec) {
     if (FileSystem::Instance().Exists(fspec))
       return ConstString(fspec.GetPath());
   }

diff  --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
index 82568efdca89..3e3187c0da31 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
@@ -73,7 +73,7 @@ class PlatformMacOSX : public PlatformDarwin {
   AddClangModuleCompilationOptions(lldb_private::Target *target,
                                    std::vector<std::string> &options) override {
     return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
-        target, options, PlatformDarwin::SDKType::MacOSX);
+        target, options, lldb_private::XcodeSDK::Type::MacOSX);
   }
 
 private:

diff  --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
index baf004ba9c3f..5e8422b4df45 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
@@ -45,7 +45,7 @@ class PlatformRemoteDarwinDevice : public PlatformDarwin {
   AddClangModuleCompilationOptions(lldb_private::Target *target,
                                    std::vector<std::string> &options) override {
     return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
-        target, options, PlatformDarwin::SDKType::iPhoneOS);
+        target, options, lldb_private::XcodeSDK::Type::iPhoneOS);
   }
 
 protected:

diff  --git a/lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h b/lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
index a3110ee106c7..095d81b7ca5f 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
@@ -71,7 +71,7 @@ class PlatformiOSSimulator : public PlatformAppleSimulator {
   AddClangModuleCompilationOptions(lldb_private::Target *target,
                                    std::vector<std::string> &options) override {
     return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
-        target, options, PlatformDarwin::SDKType::iPhoneSimulator);
+        target, options, lldb_private::XcodeSDK::Type::iPhoneSimulator);
   }
 
 protected:

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 938a49453e37..bc080db0105e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -12,6 +12,7 @@
 #include "DWARFDIE.h"
 #include "DWARFDebugInfoEntry.h"
 #include "lldb/lldb-enumerations.h"
+#include "lldb/Utility/XcodeSDK.h"
 #include "llvm/Support/RWMutex.h"
 #include <atomic>
 

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index ab271d2364bd..6d43f957d362 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -664,6 +664,12 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
         const DWARFBaseDIE cu_die =
             dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly();
         if (cu_die) {
+          if (const char *sdk =
+                  cu_die.GetAttributeValueAsString(DW_AT_APPLE_sdk, nullptr)) {
+            const char *sysroot =
+                cu_die.GetAttributeValueAsString(DW_AT_LLVM_sysroot, "");
+            module_sp->RegisterXcodeSDK(sdk, sysroot);
+          }
           FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());
           MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp);
 

diff  --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt
index 1bbacc384475..48456ef1e3b1 100644
--- a/lldb/source/Utility/CMakeLists.txt
+++ b/lldb/source/Utility/CMakeLists.txt
@@ -57,6 +57,7 @@ add_lldb_library(lldbUtility
   UserIDResolver.cpp
   VASprintf.cpp
   VMRange.cpp
+  XcodeSDK.cpp
 
   LINK_LIBS
     ${LLDB_SYSTEM_LIBS}

diff  --git a/lldb/source/Utility/XcodeSDK.cpp b/lldb/source/Utility/XcodeSDK.cpp
new file mode 100644
index 000000000000..f2403f10de55
--- /dev/null
+++ b/lldb/source/Utility/XcodeSDK.cpp
@@ -0,0 +1,163 @@
+//===-- 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;
+}

diff  --git a/lldb/unittests/Platform/PlatformDarwinTest.cpp b/lldb/unittests/Platform/PlatformDarwinTest.cpp
index 20916f3cd125..0a4c802c30bb 100644
--- a/lldb/unittests/Platform/PlatformDarwinTest.cpp
+++ b/lldb/unittests/Platform/PlatformDarwinTest.cpp
@@ -21,10 +21,6 @@ struct PlatformDarwinTester : public PlatformDarwin {
 public:
   using PlatformDarwin::FindComponentInPath;
   using PlatformDarwin::FindXcodeContentsDirectoryInPath;
-  static bool SDKSupportsModules(SDKType desired_type,
-                                 const lldb_private::FileSpec &sdk_path) {
-    return PlatformDarwin::SDKSupportsModules(desired_type, sdk_path);
-  }
 };
 
 TEST(PlatformDarwinTest, TestParseVersionBuildDir) {
@@ -53,24 +49,6 @@ TEST(PlatformDarwinTest, TestParseVersionBuildDir) {
 
   std::tie(V, D) = PlatformDarwin::ParseVersionBuildDir("3.4.5");
   EXPECT_EQ(llvm::VersionTuple(3, 4, 5), V);
-
-  std::string base = "/Applications/Xcode.app/Contents/Developer/Platforms/";
-  EXPECT_TRUE(PlatformDarwinTester::SDKSupportsModules(
-      PlatformDarwin::SDKType::iPhoneSimulator,
-      FileSpec(
-          base +
-          "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.0.sdk")));
-  EXPECT_FALSE(PlatformDarwinTester::SDKSupportsModules(
-      PlatformDarwin::SDKType::iPhoneSimulator,
-      FileSpec(
-          base +
-          "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.2.sdk")));
-  EXPECT_TRUE(PlatformDarwinTester::SDKSupportsModules(
-      PlatformDarwin::SDKType::MacOSX,
-      FileSpec(base + "MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk")));
-  EXPECT_FALSE(PlatformDarwinTester::SDKSupportsModules(
-      PlatformDarwin::SDKType::MacOSX,
-      FileSpec(base + "MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk")));
 }
 
 TEST(PlatformDarwinTest, FindXcodeContentsDirectoryInPath) {
@@ -111,29 +89,6 @@ TEST(PlatformDarwinTest, FindXcodeContentsDirectoryInPath) {
                     no_capitalization));
 }
 
-TEST(PlatformDarwinTest, GetSDKNameForType) {
-  EXPECT_EQ("macosx",
-            PlatformDarwin::GetSDKNameForType(PlatformDarwin::SDKType::MacOSX));
-  EXPECT_EQ("iphonesimulator", PlatformDarwin::GetSDKNameForType(
-                                   PlatformDarwin::SDKType::iPhoneSimulator));
-  EXPECT_EQ("iphoneos", PlatformDarwin::GetSDKNameForType(
-                            PlatformDarwin::SDKType::iPhoneOS));
-  EXPECT_EQ("appletvsimulator", PlatformDarwin::GetSDKNameForType(
-                                    PlatformDarwin::SDKType::AppleTVSimulator));
-  EXPECT_EQ("appletvos", PlatformDarwin::GetSDKNameForType(
-                             PlatformDarwin::SDKType::AppleTVOS));
-  EXPECT_EQ("watchsimulator", PlatformDarwin::GetSDKNameForType(
-                                  PlatformDarwin::SDKType::WatchSimulator));
-  EXPECT_EQ("watchos", PlatformDarwin::GetSDKNameForType(
-                           PlatformDarwin::SDKType::watchOS));
-  EXPECT_EQ("linux",
-            PlatformDarwin::GetSDKNameForType(PlatformDarwin::SDKType::Linux));
-  EXPECT_EQ("", PlatformDarwin::GetSDKNameForType(
-                    PlatformDarwin::SDKType::numSDKTypes));
-  EXPECT_EQ(
-      "", PlatformDarwin::GetSDKNameForType(PlatformDarwin::SDKType::unknown));
-}
-
 TEST(PlatformDarwinTest, FindComponentInPath) {
   EXPECT_EQ("/path/to/foo",
             PlatformDarwinTester::FindComponentInPath("/path/to/foo/", "foo"));

diff  --git a/lldb/unittests/Utility/CMakeLists.txt b/lldb/unittests/Utility/CMakeLists.txt
index 5e27c6725d4b..c624c3674924 100644
--- a/lldb/unittests/Utility/CMakeLists.txt
+++ b/lldb/unittests/Utility/CMakeLists.txt
@@ -42,6 +42,7 @@ add_lldb_unittest(UtilityTests
   UUIDTest.cpp
   VASprintfTest.cpp
   VMRangeTest.cpp
+  XcodeSDKTest.cpp
 
   LINK_LIBS
       lldbUtility

diff  --git a/lldb/unittests/Utility/XcodeSDKTest.cpp b/lldb/unittests/Utility/XcodeSDKTest.cpp
new file mode 100644
index 000000000000..a316516a1675
--- /dev/null
+++ b/lldb/unittests/Utility/XcodeSDKTest.cpp
@@ -0,0 +1,86 @@
+//===-- XcodeSDKTest.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 "gtest/gtest.h"
+
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/XcodeSDK.h"
+
+#include "llvm/ADT/StringRef.h"
+
+#include <tuple>
+
+using namespace lldb_private;
+
+TEST(XcodeSDKTest, ParseTest) {
+  EXPECT_EQ(XcodeSDK::GetAnyMacOS().GetType(), XcodeSDK::MacOSX);
+  EXPECT_EQ(XcodeSDK("MacOSX.sdk").GetType(), XcodeSDK::MacOSX);
+  EXPECT_EQ(XcodeSDK("iPhoneSimulator.sdk").GetType(), XcodeSDK::iPhoneSimulator);
+  EXPECT_EQ(XcodeSDK("iPhoneOS.sdk").GetType(), XcodeSDK::iPhoneOS);
+  EXPECT_EQ(XcodeSDK("AppleTVSimulator.sdk").GetType(), XcodeSDK::AppleTVSimulator);
+  EXPECT_EQ(XcodeSDK("AppleTVOS.sdk").GetType(), XcodeSDK::AppleTVOS);
+  EXPECT_EQ(XcodeSDK("WatchSimulator.sdk").GetType(), XcodeSDK::WatchSimulator);
+  EXPECT_EQ(XcodeSDK("WatchOS.sdk").GetType(), XcodeSDK::watchOS);
+  EXPECT_EQ(XcodeSDK("Linux.sdk").GetType(), XcodeSDK::Linux);
+  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().GetType(), XcodeSDK::unknown);
+  EXPECT_EQ(XcodeSDK().GetVersion(), llvm::VersionTuple());
+}
+
+TEST(XcodeSDKTest, MergeTest) {
+  XcodeSDK sdk("MacOSX.sdk");
+  sdk.Merge(XcodeSDK("WatchOS.sdk"));
+  // This doesn't make any particular sense and shouldn't happen in practice, we
+  // just want to guarantee a well-defined behavior when choosing one
+  // SDK to fit all CUs in an lldb::Module.
+  // -> The higher number wins.
+  EXPECT_EQ(sdk.GetType(), XcodeSDK::watchOS);
+  sdk.Merge(XcodeSDK("WatchOS1.1.sdk"));
+  EXPECT_EQ(sdk.GetVersion(), llvm::VersionTuple(1, 1));
+  sdk.Merge(XcodeSDK("WatchOS2.0.sdk"));
+  EXPECT_EQ(sdk.GetVersion(), llvm::VersionTuple(2, 0));
+}
+
+TEST(XcodeSDKTest, SDKSupportsModules) {
+  std::string base = "/Applications/Xcode.app/Contents/Developer/Platforms/";
+  EXPECT_TRUE(XcodeSDK::SDKSupportsModules(
+      XcodeSDK::Type::iPhoneSimulator,
+      FileSpec(
+          base +
+          "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.0.sdk")));
+  EXPECT_FALSE(XcodeSDK::SDKSupportsModules(
+      XcodeSDK::Type::iPhoneSimulator,
+      FileSpec(
+          base +
+          "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.2.sdk")));
+  EXPECT_TRUE(XcodeSDK::SDKSupportsModules(
+      XcodeSDK::Type::MacOSX,
+      FileSpec(base + "MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk")));
+  EXPECT_FALSE(XcodeSDK::SDKSupportsModules(
+      XcodeSDK::Type::MacOSX,
+      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));
+}


        


More information about the lldb-commits mailing list