Index: lldb/include/lldb/Host/HostInfoBase.h =================================================================== --- lldb/include/lldb/Host/HostInfoBase.h +++ lldb/include/lldb/Host/HostInfoBase.h @@ -16,6 +16,7 @@ #include "lldb/Utility/XcodeSDK.h" #include "lldb/lldb-enumerations.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Errc.h" #include @@ -114,6 +115,12 @@ return ""; } + /// Return the path to a specific tool in the specified Xcode SDK. + static llvm::Expected FindSDKTool(XcodeSDK sdk, + llvm::StringRef tool) { + return llvm::errorCodeToError(llvm::errc::no_such_file_or_directory); + } + /// Return information about module \p image_name if it is loaded in /// the current process's address space. static SharedCacheImageInfo Index: lldb/include/lldb/Host/macosx/HostInfoMacOSX.h =================================================================== --- lldb/include/lldb/Host/macosx/HostInfoMacOSX.h +++ lldb/include/lldb/Host/macosx/HostInfoMacOSX.h @@ -12,6 +12,7 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/XcodeSDK.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/VersionTuple.h" #include @@ -30,8 +31,9 @@ static FileSpec GetXcodeContentsDirectory(); static FileSpec GetXcodeDeveloperDirectory(); - /// Query xcrun to find an Xcode SDK directory. static llvm::Expected GetXcodeSDKPath(XcodeSDK sdk); + static llvm::Expected FindSDKTool(XcodeSDK sdk, + llvm::StringRef tool); /// Shared cache utilities static SharedCacheImageInfo Index: lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm =================================================================== --- lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm +++ lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm @@ -522,36 +522,65 @@ return path; } -llvm::Expected HostInfoMacOSX::GetXcodeSDKPath(XcodeSDK sdk) { - struct ErrorOrPath { - std::string str; - bool is_error; - }; - static llvm::StringMap g_sdk_path; - static std::mutex g_sdk_path_mutex; +namespace { +struct ErrorOrPath { + std::string str; + bool is_error; +}; +} // namespace - std::lock_guard guard(g_sdk_path_mutex); +static llvm::Expected +find_cached_path(llvm::StringMap &cache, std::mutex &mutex, + llvm::StringRef key, + std::function(void)> compute) { + std::lock_guard guard(mutex); LLDB_SCOPED_TIMER(); - auto key = sdk.GetString(); - auto it = g_sdk_path.find(key); - if (it != g_sdk_path.end()) { + auto it = cache.find(key); + if (it != cache.end()) { if (it->second.is_error) return llvm::createStringError(llvm::inconvertibleErrorCode(), it->second.str); - else - return it->second.str; + return it->second.str; } - auto path_or_err = GetXcodeSDK(sdk); + auto path_or_err = compute(); if (!path_or_err) { std::string error = toString(path_or_err.takeError()); - g_sdk_path.insert({key, {error, true}}); + cache.insert({key, {error, true}}); return llvm::createStringError(llvm::inconvertibleErrorCode(), error); } - auto it_new = g_sdk_path.insert({key, {*path_or_err, false}}); + auto it_new = cache.insert({key, {*path_or_err, false}}); return it_new.first->second.str; } +llvm::Expected HostInfoMacOSX::GetXcodeSDKPath(XcodeSDK sdk) { + static llvm::StringMap g_sdk_path; + static std::mutex g_sdk_path_mutex; + auto key = sdk.GetString(); + return find_cached_path(g_sdk_path, g_sdk_path_mutex, key, [&](){ + return GetXcodeSDK(sdk); + }); +} + +llvm::Expected +HostInfoMacOSX::FindSDKTool(XcodeSDK sdk, llvm::StringRef tool) { + static llvm::StringMap g_tool_path; + static std::mutex g_tool_path_mutex; + std::string key; + llvm::raw_string_ostream(key) << sdk.GetString() << ":" << tool; + return find_cached_path( + g_tool_path, g_tool_path_mutex, key, + [&]() -> llvm::Expected { + std::string sdk_name = XcodeSDK::GetCanonicalName(sdk.Parse()); + if (sdk_name.empty()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Unrecognized SDK type: " + + sdk.GetString()); + llvm::SmallVector find = {"-find", tool}; + return xcrun(sdk_name, find); + }); +} + namespace { struct dyld_shared_cache_dylib_text_info { uint64_t version; // current version 1 Index: lldb/unittests/Host/HostInfoTest.cpp =================================================================== --- lldb/unittests/Host/HostInfoTest.cpp +++ lldb/unittests/Host/HostInfoTest.cpp @@ -72,6 +72,23 @@ // This is expected to fail. EXPECT_TRUE(get_sdk("CeciNestPasUnOS.sdk", true).empty()); } + +TEST_F(HostInfoTest, FindSDKTool) { + auto find_tool = [](std::string sdk, llvm::StringRef tool, + bool error = false) -> llvm::StringRef { + auto sdk_path_or_err = + HostInfo::FindSDKTool(XcodeSDK(std::move(sdk)), tool); + if (!error) { + EXPECT_TRUE((bool)sdk_path_or_err); + return *sdk_path_or_err; + } + EXPECT_FALSE((bool)sdk_path_or_err); + llvm::consumeError(sdk_path_or_err.takeError()); + return {}; + }; + EXPECT_FALSE(find_tool("MacOSX.sdk", "clang").empty()); + EXPECT_TRUE(find_tool("MacOSX.sdk", "CeciNestPasUnOutil").empty()); +} #endif TEST(HostInfoTestInitialization, InitTwice) {