[Lldb-commits] [lldb] [lldb]HostInfoMacOSX] Search CommandLineTools directory when looking up SDK paths (PR #128712)
Michael Buch via lldb-commits
lldb-commits at lists.llvm.org
Tue Feb 25 05:23:38 PST 2025
https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/128712
`GetSDKRoot` uses `xcrun` to find an SDK root path for a given SDK version string. But if the SDK doesn't exist in the Xcode installations, but instead lives in the `CommandLineTools`, `xcrun` will fail to find it. Negative searches for an SDK path cost a lot (a few seconds) each time `xcrun` is invoked. We do cache negative results in `find_cached_path` inside LLDB, but we would still pay the price on every new debug session the first time we evaluate an expression. This doesn't only cause a noticable delay in running the expression, but also generates following error:
```
error: Error while searching for Xcode SDK: timed out waiting for shell command to complete
(int) $0 = 42
```
To avoid this `xcrun` penalty, we search `CommandLineTools` for a matching SDK ourselves, and only if we don't find it, do we fall back to calling `xcrun`.
rdar://113619904
rdar://113619723
>From 2665e747d5866480f2f704d5a72fe016d258f200 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 25 Feb 2025 13:11:33 +0000
Subject: [PATCH] [lldb]HostInfoMacOSX] Search CommandLineTools directory when
looking up SDK paths
`GetSDKRoot` uses `xcrun` to find an SDK root path for a given SDK
version string. But if the SDK doesn't exist in the Xcode installations,
but instead lives in the `CommandLineTools`, `xcrun` will fail to find
it. Negative searches for an SDK path cost a lot (a few seconds) each
time `xcrun` is invoked. We do cache negative results in
`find_cached_path` inside LLDB, but we would still pay the price on
every new debug session the first time we evaluate an expression. This
doesn't only cause a noticable delay in running the expression, but also
generates following error:
```
error: Error while searching for Xcode SDK: timed out waiting for shell command to complete
(int) $0 = 42
```
To avoid this `xcrun` penalty, we search `CommandLineTools` for a
matching SDK ourselves, and only if we don't find it, do we fall back to
calling `xcrun`.
rdar://113619904
rdar://113619723
---
lldb/include/lldb/Host/FileSystem.h | 5 +-
.../Host/macosx/objcxx/HostInfoMacOSX.mm | 60 +++++++++++++++++++
2 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/lldb/include/lldb/Host/FileSystem.h b/lldb/include/lldb/Host/FileSystem.h
index 640f3846e448c..4128d7b012041 100644
--- a/lldb/include/lldb/Host/FileSystem.h
+++ b/lldb/include/lldb/Host/FileSystem.h
@@ -183,8 +183,9 @@ class FileSystem {
eEnumerateDirectoryResultQuit
};
- typedef EnumerateDirectoryResult (*EnumerateDirectoryCallbackType)(
- void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef);
+ typedef std::function<EnumerateDirectoryResult(
+ void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef)>
+ EnumerateDirectoryCallbackType;
typedef std::function<EnumerateDirectoryResult(
llvm::sys::fs::file_type file_type, llvm::StringRef)>
diff --git a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
index 6e924fdc684cf..a94fd3b57f9d6 100644
--- a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
+++ b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
@@ -15,11 +15,14 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Timer.h"
+#include "clang/Basic/DarwinSDKInfo.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
// C++ Includes
@@ -569,10 +572,52 @@ static bool ResolveAndVerifyCandidateSupportDir(FileSpec &path) {
cache.insert({key, {error, true}});
return llvm::createStringError(llvm::inconvertibleErrorCode(), error);
}
+
+ if (path_or_err->empty())
+ return llvm::createStringError("Empty path determined for '%s'",
+ key.data());
+
auto it_new = cache.insert({key, {*path_or_err, false}});
return it_new.first->second.str;
}
+static llvm::Expected<std::string>
+GetCommandLineToolsSDKRoot(llvm::VersionTuple version) {
+ std::string clt_root_dir;
+ FileSystem::Instance().EnumerateDirectory(
+ "/Library/Developer/CommandLineTools/SDKs/", /*find_directories=*/true,
+ /*find_files=*/false, /*find_other=*/false,
+ [&](void *baton, llvm::sys::fs::file_type file_type,
+ llvm::StringRef name) {
+ assert(file_type == llvm::sys::fs::file_type::directory_file);
+
+ if (!name.ends_with(".sdk"))
+ return FileSystem::eEnumerateDirectoryResultNext;
+
+ llvm::Expected<std::optional<clang::DarwinSDKInfo>> sdk_info =
+ clang::parseDarwinSDKInfo(
+ *FileSystem::Instance().GetVirtualFileSystem(), name);
+ if (!sdk_info) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), sdk_info.takeError(),
+ "Error while parsing {1}: {0}", name);
+ return FileSystem::eEnumerateDirectoryResultNext;
+ }
+
+ if (!*sdk_info)
+ return FileSystem::eEnumerateDirectoryResultNext;
+
+ if (version == (*sdk_info)->getVersion()) {
+ clt_root_dir = name;
+ return FileSystem::eEnumerateDirectoryResultQuit;
+ }
+
+ return FileSystem::eEnumerateDirectoryResultNext;
+ },
+ /*baton=*/nullptr);
+
+ return clt_root_dir;
+}
+
llvm::Expected<llvm::StringRef> HostInfoMacOSX::GetSDKRoot(SDKOptions options) {
static llvm::StringMap<ErrorOrPath> g_sdk_path;
static std::mutex g_sdk_path_mutex;
@@ -581,6 +626,21 @@ static bool ResolveAndVerifyCandidateSupportDir(FileSpec &path) {
"XcodeSDK not specified");
XcodeSDK sdk = *options.XcodeSDKSelection;
auto key = sdk.GetString();
+
+ // xcrun doesn't search SDKs in the CommandLineTools (CLT) directory. So if
+ // a program was compiled against a CLT SDK, but that SDK wasn't present in
+ // any of the Xcode installations, then xcrun would fail to find the SDK
+ // (which is expensive). To avoid this we first try to find the specified SDK
+ // in the CLT directory.
+ auto clt_root_dir = find_cached_path(g_sdk_path, g_sdk_path_mutex, key, [&] {
+ return GetCommandLineToolsSDKRoot(sdk.GetVersion());
+ });
+
+ if (clt_root_dir)
+ return clt_root_dir;
+ else
+ llvm::consumeError(clt_root_dir.takeError());
+
return find_cached_path(g_sdk_path, g_sdk_path_mutex, key, [&](){
return GetXcodeSDK(sdk);
});
More information about the lldb-commits
mailing list