[Lldb-commits] [lldb] 79feafa - Add an internal bit to the XcodeSDK class.

Adrian Prantl via lldb-commits lldb-commits at lists.llvm.org
Fri Apr 24 12:56:21 PDT 2020


Author: Adrian Prantl
Date: 2020-04-24T12:55:53-07:00
New Revision: 79feafa5147af3cfaa821a5488ac40ed8b79b072

URL: https://github.com/llvm/llvm-project/commit/79feafa5147af3cfaa821a5488ac40ed8b79b072
DIFF: https://github.com/llvm/llvm-project/commit/79feafa5147af3cfaa821a5488ac40ed8b79b072.diff

LOG: 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

Added: 
    

Modified: 
    lldb/include/lldb/Utility/XcodeSDK.h
    lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
    lldb/source/Utility/XcodeSDK.cpp
    lldb/unittests/Host/HostInfoTest.cpp
    lldb/unittests/Utility/XcodeSDKTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Utility/XcodeSDK.h b/lldb/include/lldb/Utility/XcodeSDK.h
index 552c51c36844..24ab5b1fdf7a 100644
--- a/lldb/include/lldb/Utility/XcodeSDK.h
+++ b/lldb/include/lldb/Utility/XcodeSDK.h
@@ -22,6 +22,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"); }
 
@@ -38,7 +41,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.
@@ -49,15 +51,27 @@ class XcodeSDK {
   XcodeSDK(const XcodeSDK&) = default;
   bool operator==(XcodeSDK other);
 
-  /// Return parsed SDK number, and SDK version number.
-  std::tuple<Type, llvm::VersionTuple> 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 c09339e8c673..e495c752cb19 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 7ad0090f85e2..a34eac6b2c95 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::Type, llvm::VersionTuple> 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<XcodeSDK::Type, llvm::VersionTuple>(
-      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 ed4b7b5d39c0..d854426e4898 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 a316516a1675..95b909e70018 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));
 }


        


More information about the lldb-commits mailing list