From 1525f6b982b3c209a9d0edf45371eb14231e5c58 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 12 May 2022 11:22:08 +0200 Subject: [PATCH] [SourceKit] Pass the main swift executable path when constructing a compiler invocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #58786 (rdar://93030932) was failing because the `swift-frontend` invocations passed a `swiftExecutablePath` to `Invocation.parseArgs`. This caused the `ClangImporter` instance to point to a `clang` binary next to the `swift-frontend` executable while SourceKit used PATH to find `clang`. The clang executable next to `swift-frontend` doesn’t actually exist because `clang` lives in `llvm-linux-aarch64/bin` and `swift-frontend` lives in `swift-linux-aarch64/bin`. So some checks for a minimum clang verison failed for the normal build (because the executable doesn’t actually exists) while they pass during the SourceKit build (which used `clang` from `PATH`). This in turn caused the `outline-atomics` to be enabled to the SourceKit clang compiler arguments but not the clang compiler arguments for a normal build and thus resulted in two separate module cache directories (which includes the enabled features in the module directory hash). To fix this issue, also set the swift executable path for compiler invocations created from SourceKit. Fixes #58786 (rdar://93030932) --- include/swift/IDE/Utils.h | 1 + lib/IDE/Utils.cpp | 5 ++++- .../match-module-cache-with-compiler.swift | 3 --- .../include/SourceKit/Core/Context.h | 8 +++++++- tools/SourceKit/lib/Core/Context.cpp | 5 +++-- .../lib/SwiftLang/SwiftASTManager.cpp | 20 +++++++++++-------- .../SourceKit/lib/SwiftLang/SwiftASTManager.h | 1 + .../lib/SwiftLang/SwiftLangSupport.cpp | 3 ++- .../lib/SwiftLang/SwiftLangSupport.h | 3 +++ .../InProc/sourcekitdInProc-darwin.exports | 2 +- .../bin/InProc/sourcekitdInProc.cpp | 9 ++++++++- .../sourcekitd/bin/XPC/Service/XPCService.cpp | 12 +++++++++-- .../sourcekitd/include/sourcekitd/Internal.h | 5 ++++- .../tools/sourcekitd/lib/API/Requests.cpp | 9 +++++---- .../SourceKit/SwiftLang/CursorInfoTest.cpp | 9 ++++++++- unittests/SourceKit/SwiftLang/EditingTest.cpp | 9 ++++++++- 16 files changed, 77 insertions(+), 27 deletions(-) diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h index de8265a592f55..121bfe0ab70ad 100644 --- a/include/swift/IDE/Utils.h +++ b/include/swift/IDE/Utils.h @@ -89,6 +89,7 @@ bool initCompilerInvocation( FrontendOptions::ActionType Action, DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, llvm::IntrusiveRefCntPtr FileSystem, + const std::string &swiftExecutablePath, const std::string &runtimeResourcePath, const std::string &diagnosticDocumentationPath, time_t sessionTimestamp, std::string &Error); diff --git a/lib/IDE/Utils.cpp b/lib/IDE/Utils.cpp index 0dde804cdc448..f7e57e1da02f6 100644 --- a/lib/IDE/Utils.cpp +++ b/lib/IDE/Utils.cpp @@ -276,6 +276,7 @@ bool ide::initCompilerInvocation( FrontendOptions::ActionType Action, DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, llvm::IntrusiveRefCntPtr FileSystem, + const std::string &swiftExecutablePath, const std::string &runtimeResourcePath, const std::string &diagnosticDocumentationPath, time_t sessionTimestamp, std::string &Error) { @@ -299,7 +300,9 @@ bool ide::initCompilerInvocation( driver::getSingleFrontendInvocationFromDriverArguments( Args, Diags, [&](ArrayRef FrontendArgs) { - return Invocation.parseArgs(FrontendArgs, Diags); + return Invocation.parseArgs( + FrontendArgs, Diags, /*ConfigurationFileBuffers=*/nullptr, + /*workingDirectory=*/"", swiftExecutablePath); }, /*ForceNoOutputs=*/true); diff --git a/test/SourceKit/Misc/match-module-cache-with-compiler.swift b/test/SourceKit/Misc/match-module-cache-with-compiler.swift index 9e54e39687256..b45df667f414a 100644 --- a/test/SourceKit/Misc/match-module-cache-with-compiler.swift +++ b/test/SourceKit/Misc/match-module-cache-with-compiler.swift @@ -3,9 +3,6 @@ // REQUIRES: shell -// https://github.com/apple/swift/issues/58786 -// UNSUPPORTED: OS=linux-gnu - // RUN: %empty-directory(%t) // RUN: COMPILER_ARGS=( \ diff --git a/tools/SourceKit/include/SourceKit/Core/Context.h b/tools/SourceKit/include/SourceKit/Core/Context.h index 4ba92cb346764..4358d2881489f 100644 --- a/tools/SourceKit/include/SourceKit/Core/Context.h +++ b/tools/SourceKit/include/SourceKit/Core/Context.h @@ -169,6 +169,9 @@ class SlowRequestSimulator { }; class Context { + /// The path of the swift-frontend executable. + /// Used to find clang relative to it. + std::string SwiftExecutablePath; std::string RuntimeLibPath; std::string DiagnosticDocumentationPath; std::unique_ptr SwiftLang; @@ -178,12 +181,15 @@ class Context { std::shared_ptr SlowRequestSim; public: - Context(StringRef RuntimeLibPath, StringRef DiagnosticDocumentationPath, + Context(StringRef SwiftExecutablePath, StringRef RuntimeLibPath, + StringRef DiagnosticDocumentationPath, llvm::function_ref(Context &)> LangSupportFactoryFn, bool shouldDispatchNotificationsOnMain = true); ~Context(); + StringRef getSwiftExecutablePath() const { return SwiftExecutablePath; } + StringRef getRuntimeLibPath() const { return RuntimeLibPath; } StringRef getDiagnosticDocumentationPath() const { return DiagnosticDocumentationPath; diff --git a/tools/SourceKit/lib/Core/Context.cpp b/tools/SourceKit/lib/Core/Context.cpp index 668058aec2dda..3faf5e1978000 100644 --- a/tools/SourceKit/lib/Core/Context.cpp +++ b/tools/SourceKit/lib/Core/Context.cpp @@ -36,11 +36,12 @@ GlobalConfig::getCompletionOpts() const { } SourceKit::Context::Context( - StringRef RuntimeLibPath, StringRef DiagnosticDocumentationPath, + StringRef SwiftExecutablePath, StringRef RuntimeLibPath, + StringRef DiagnosticDocumentationPath, llvm::function_ref(Context &)> LangSupportFactoryFn, bool shouldDispatchNotificationsOnMain) - : RuntimeLibPath(RuntimeLibPath), + : SwiftExecutablePath(SwiftExecutablePath), RuntimeLibPath(RuntimeLibPath), DiagnosticDocumentationPath(DiagnosticDocumentationPath), NotificationCtr( new NotificationCenter(shouldDispatchNotificationsOnMain)), diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp index 805292f14b6a8..0212b561aae3d 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp @@ -544,10 +544,11 @@ struct SwiftASTManager::Implementation { std::shared_ptr EditorDocs, std::shared_ptr Config, std::shared_ptr Stats, - std::shared_ptr ReqTracker, StringRef RuntimeResourcePath, - StringRef DiagnosticDocumentationPath) + std::shared_ptr ReqTracker, StringRef SwiftExecutablePath, + StringRef RuntimeResourcePath, StringRef DiagnosticDocumentationPath) : EditorDocs(EditorDocs), Config(Config), Stats(Stats), - ReqTracker(ReqTracker), RuntimeResourcePath(RuntimeResourcePath), + ReqTracker(ReqTracker), SwiftExecutablePath(SwiftExecutablePath), + RuntimeResourcePath(RuntimeResourcePath), DiagnosticDocumentationPath(DiagnosticDocumentationPath), SessionTimestamp(llvm::sys::toTimeT(std::chrono::system_clock::now())) { } @@ -556,6 +557,9 @@ struct SwiftASTManager::Implementation { std::shared_ptr Config; std::shared_ptr Stats; std::shared_ptr ReqTracker; + /// The path of the swift-frontend executable. + /// Used to find clang relative to it. + std::string SwiftExecutablePath; std::string RuntimeResourcePath; std::string DiagnosticDocumentationPath; SourceManager SourceMgr; @@ -625,10 +629,10 @@ SwiftASTManager::SwiftASTManager( std::shared_ptr EditorDocs, std::shared_ptr Config, std::shared_ptr Stats, - std::shared_ptr ReqTracker, StringRef RuntimeResourcePath, - StringRef DiagnosticDocumentationPath) + std::shared_ptr ReqTracker, StringRef SwiftExecutablePath, + StringRef RuntimeResourcePath, StringRef DiagnosticDocumentationPath) : Impl(*new Implementation(EditorDocs, Config, Stats, ReqTracker, - RuntimeResourcePath, + SwiftExecutablePath, RuntimeResourcePath, DiagnosticDocumentationPath)) {} SwiftASTManager::~SwiftASTManager() { @@ -665,8 +669,8 @@ bool SwiftASTManager::initCompilerInvocation( std::string &Error) { return ide::initCompilerInvocation( Invocation, OrigArgs, Action, Diags, UnresolvedPrimaryFile, FileSystem, - Impl.RuntimeResourcePath, Impl.DiagnosticDocumentationPath, - Impl.SessionTimestamp, Error); + Impl.SwiftExecutablePath, Impl.RuntimeResourcePath, + Impl.DiagnosticDocumentationPath, Impl.SessionTimestamp, Error); } bool SwiftASTManager::initCompilerInvocation( diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.h b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.h index f0f08878f4dc3..d02a866cd4475 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.h +++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.h @@ -235,6 +235,7 @@ class SwiftASTManager : public std::enable_shared_from_this { std::shared_ptr Config, std::shared_ptr Stats, std::shared_ptr ReqTracker, + StringRef SwiftExecutablePath, StringRef RuntimeResourcePath, StringRef DiagnosticDocumentationPath); ~SwiftASTManager(); diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp index 2cad232275138..6e31c3b82b261 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp @@ -272,6 +272,7 @@ configureCompletionInstance(std::shared_ptr CompletionInst, SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx) : NotificationCtr(SKCtx.getNotificationCenter()), + SwiftExecutablePath(SKCtx.getSwiftExecutablePath()), ReqTracker(SKCtx.getRequestTracker()), CCCache(new SwiftCompletionCache), CompileManager(RuntimeResourcePath, DiagnosticDocumentationPath) { llvm::SmallString<128> LibPath(SKCtx.getRuntimeLibPath()); @@ -283,7 +284,7 @@ SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx) EditorDocuments = std::make_shared(); ASTMgr = std::make_shared( EditorDocuments, SKCtx.getGlobalConfiguration(), Stats, ReqTracker, - RuntimeResourcePath, DiagnosticDocumentationPath); + SwiftExecutablePath, RuntimeResourcePath, DiagnosticDocumentationPath); CompletionInst = std::make_shared(); diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h index 0ab892d308fbd..74cf2f9dd4b10 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h +++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h @@ -350,6 +350,9 @@ struct SwiftStatistics { class SwiftLangSupport : public LangSupport { std::shared_ptr NotificationCtr; + /// The path of the swift-frontend executable. + /// Used to find clang relative to it. + std::string SwiftExecutablePath; std::string RuntimeResourcePath; std::string DiagnosticDocumentationPath; std::shared_ptr ASTMgr; diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports index 8ee6c810b05fd..4f42446abd74a 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports @@ -70,7 +70,7 @@ sourcekitd_variant_uid_get_value _ZN10sourcekitd13cancelRequestEPKv _ZN10sourcekitd13enableLoggingEN4llvm9StringRefE _ZN10sourcekitd13handleRequestEPvPKvNSt3__18functionIFvS0_EEE -_ZN10sourcekitd17initializeServiceEN4llvm9StringRefES1_NSt3__18functionIFvPvEEE +_ZN10sourcekitd17initializeServiceEN4llvm9StringRefES1_S1_NSt3__18functionIFvPvEEE _ZN10sourcekitd24createErrorRequestFailedEN4llvm9StringRefE _ZN10sourcekitd24disposeCancellationTokenEPKv _ZN9SourceKit6Logger12LoggingLevelE diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp index f040f576d2757..ebc646b090b80 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp @@ -80,6 +80,13 @@ static std::string getRuntimeLibPath() { return libPath.str().str(); } +static std::string getSwiftExecutablePath() { + llvm::SmallString<128> path; + getToolchainPrefixPath(path); + llvm::sys::path::append(path, "bin", "swift-frontend"); + return path.str().str(); +} + static std::string getDiagnosticDocumentationPath() { llvm::SmallString<128> docPath; getToolchainPrefixPath(docPath); @@ -90,7 +97,7 @@ static std::string getDiagnosticDocumentationPath() { void sourcekitd_initialize(void) { if (sourcekitd::initializeClient()) { LOG_INFO_FUNC(High, "initializing"); - sourcekitd::initializeService(getRuntimeLibPath(), + sourcekitd::initializeService(getSwiftExecutablePath(), getRuntimeLibPath(), getDiagnosticDocumentationPath(), postNotification); } diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp index 0e7bc87ce5ee1..01f2879bb75d5 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp @@ -215,6 +215,13 @@ static std::string getRuntimeLibPath() { return path.str().str(); } +static std::string getSwiftExecutablePath() { + llvm::SmallString<128> path; + getToolchainPrefixPath(path); + llvm::sys::path::append(path, "bin", "swift-frontend"); + return path.str().str(); +} + static std::string getDiagnosticDocumentationPath() { llvm::SmallString<128> path; getToolchainPrefixPath(path); @@ -362,8 +369,9 @@ int main(int argc, const char *argv[]) { ^const char *(sourcekitd_uid_t uid) { return xpcUIdentFromSKDUID(uid).c_str(); }); - sourcekitd::initializeService( - getRuntimeLibPath(), getDiagnosticDocumentationPath(), postNotification); + sourcekitd::initializeService(getSwiftExecutablePath(), getRuntimeLibPath(), + getDiagnosticDocumentationPath(), + postNotification); // Increase the file descriptor limit. // FIXME: Portability ? diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h index 2a81b1b9bd5c2..ce6be0be4daea 100644 --- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h @@ -154,11 +154,14 @@ class RequestDict { }; /// Initialize the service. Must be called before attempting to handle requests. +/// \param swiftExecutablePath The path of the swift-frontend executable. +/// Used to find clang relative to it. /// \param runtimeLibPath The path to the toolchain's library directory. /// \param diagnosticDocumentationPath The path to diagnostics documentation. /// \param postNotification Callback to post a notification. void initializeService( - llvm::StringRef runtimeLibPath, llvm::StringRef diagnosticDocumentationPath, + llvm::StringRef swiftExecutablePath, llvm::StringRef runtimeLibPath, + llvm::StringRef diagnosticDocumentationPath, std::function postNotification); /// Shutdown the service. void shutdownService(); diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp index 42138c3651ea0..4c6a363867cce 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp @@ -107,14 +107,15 @@ static void fillDictionaryForDiagnosticInfo(ResponseBuilder::Dictionary Elem, static SourceKit::Context *GlobalCtx = nullptr; void sourcekitd::initializeService( - StringRef runtimeLibPath, StringRef diagnosticDocumentationPath, + llvm::StringRef swiftExecutablePath, StringRef runtimeLibPath, + StringRef diagnosticDocumentationPath, std::function postNotification) { INITIALIZE_LLVM(); initializeSwiftModules(); llvm::EnablePrettyStackTrace(); - GlobalCtx = - new SourceKit::Context(runtimeLibPath, diagnosticDocumentationPath, - SourceKit::createSwiftLangSupport); + GlobalCtx = new SourceKit::Context(swiftExecutablePath, runtimeLibPath, + diagnosticDocumentationPath, + SourceKit::createSwiftLangSupport); auto noteCenter = GlobalCtx->getNotificationCenter(); noteCenter->addDocumentUpdateNotificationReceiver([postNotification](StringRef DocumentName) { diff --git a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp index 3f6b764ee1eae..6c113f363d235 100644 --- a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp +++ b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp @@ -27,6 +27,12 @@ static StringRef getRuntimeLibPath() { return sys::path::parent_path(SWIFTLIB_DIR); } +static SmallString<128> getSwiftExecutablePath() { + SmallString<128> path = sys::path::parent_path(getRuntimeLibPath()); + sys::path::append(path, "bin", "swift-frontend"); + return path; +} + static void *createCancallationToken() { static std::atomic handle(1000); return reinterpret_cast( @@ -125,7 +131,8 @@ class CursorInfoTest : public ::testing::Test { } CursorInfoTest() - : Ctx(*new SourceKit::Context(getRuntimeLibPath(), + : Ctx(*new SourceKit::Context(getSwiftExecutablePath(), + getRuntimeLibPath(), /*diagnosticDocumentationPath*/ "", SourceKit::createSwiftLangSupport, /*dispatchOnMain=*/false)) { diff --git a/unittests/SourceKit/SwiftLang/EditingTest.cpp b/unittests/SourceKit/SwiftLang/EditingTest.cpp index 15de95908627c..c4a5a86c92baf 100644 --- a/unittests/SourceKit/SwiftLang/EditingTest.cpp +++ b/unittests/SourceKit/SwiftLang/EditingTest.cpp @@ -32,6 +32,12 @@ static StringRef getRuntimeLibPath() { return sys::path::parent_path(SWIFTLIB_DIR); } +static SmallString<128> getSwiftExecutablePath() { + SmallString<128> path = sys::path::parent_path(getRuntimeLibPath()); + sys::path::append(path, "bin", "swift-frontend"); + return path; +} + namespace { struct Token { @@ -124,7 +130,8 @@ class EditTest : public ::testing::Test { // This is avoiding destroying \p SourceKit::Context because another // thread may be active trying to use it to post notifications. // FIXME: Use shared_ptr ownership to avoid such issues. - Ctx = new SourceKit::Context(getRuntimeLibPath(), + Ctx = new SourceKit::Context(getSwiftExecutablePath(), + getRuntimeLibPath(), /*diagnosticDocumentationPath*/ "", SourceKit::createSwiftLangSupport, /*dispatchOnMain=*/false);