From 57f103d82589fe0661c7e63450f143402197ecc7 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 11 Apr 2023 09:22:32 -0700 Subject: [PATCH] [SourceKit] Pass 'swiftc' path to Driver when creating frontend args Driver uses its path to derive the plugin paths (i.e. 'lib/swift/host/plugins' et al.) Previously it was a constant string 'swiftc' that caused SourceKit failed to find dylib plugins in the toolchain. Since 'SwiftLangSupport' knows the swift-frontend path, use it, but replacing the filename with 'swiftc', to derive the plugin paths. rdar://107849796 (cherry picked from commit 3517db4c3b8edb85f3bf9907dfad84d1bf1d7e2a) --- include/swift/Driver/FrontendUtil.h | 4 +- include/swift/IDETool/CompileInstance.h | 7 ++- lib/Driver/FrontendUtil.cpp | 4 +- lib/IDETool/CompileInstance.cpp | 6 ++- lib/IDETool/CompilerInvocation.cpp | 7 ++- test/SourceKit/Macros/macro_option_set.swift | 47 +++++++++++++++++ .../SourceKit/lib/SwiftLang/SwiftCompile.cpp | 7 +-- .../lib/SwiftLang/SwiftLangSupport.cpp | 3 +- .../lib/SwiftLang/SwiftLangSupport.h | 17 ++++--- tools/swift-ide-test/ModuleAPIDiff.cpp | 11 ++-- tools/swift-ide-test/ModuleAPIDiff.h | 3 +- tools/swift-ide-test/swift-ide-test.cpp | 51 ++++++++++++------- 12 files changed, 127 insertions(+), 40 deletions(-) create mode 100644 test/SourceKit/Macros/macro_option_set.swift diff --git a/include/swift/Driver/FrontendUtil.h b/include/swift/Driver/FrontendUtil.h index b052572da730..44a346f4b405 100644 --- a/include/swift/Driver/FrontendUtil.h +++ b/include/swift/Driver/FrontendUtil.h @@ -33,6 +33,7 @@ void ExpandResponseFilesWithRetry(llvm::StringSaver &Saver, /// Generates the list of arguments that would be passed to the compiler /// frontend from the given driver arguments. /// +/// \param DriverPath The path to 'swiftc'. /// \param ArgList The driver arguments (i.e. normal arguments for \c swiftc). /// \param Diags The DiagnosticEngine used to report any errors parsing the /// arguments. @@ -48,7 +49,8 @@ void ExpandResponseFilesWithRetry(llvm::StringSaver &Saver, /// \note This function is not intended to create invocations which are /// suitable for use in REPL or immediate modes. bool getSingleFrontendInvocationFromDriverArguments( - ArrayRef ArgList, DiagnosticEngine &Diags, + StringRef DriverPath, ArrayRef ArgList, + DiagnosticEngine &Diags, llvm::function_ref FrontendArgs)> Action, bool ForceNoOutputs = false); diff --git a/include/swift/IDETool/CompileInstance.h b/include/swift/IDETool/CompileInstance.h index ba0c9fe2f9a6..4d904568517d 100644 --- a/include/swift/IDETool/CompileInstance.h +++ b/include/swift/IDETool/CompileInstance.h @@ -31,6 +31,7 @@ namespace ide { /// Manages \c CompilerInstance for completion like operations. class CompileInstance { + const std::string &SwiftExecutablePath; const std::string &RuntimeResourcePath; const std::string &DiagnosticDocumentationPath; const std::shared_ptr Plugins; @@ -67,10 +68,12 @@ class CompileInstance { std::shared_ptr> CancellationFlag); public: - CompileInstance(const std::string &RuntimeResourcePath, + CompileInstance(const std::string &SwiftExecutablePath, + const std::string &RuntimeResourcePath, const std::string &DiagnosticDocumentationPath, std::shared_ptr Plugins = nullptr) - : RuntimeResourcePath(RuntimeResourcePath), + : SwiftExecutablePath(SwiftExecutablePath), + RuntimeResourcePath(RuntimeResourcePath), DiagnosticDocumentationPath(DiagnosticDocumentationPath), Plugins(Plugins), CachedCIInvalidated(false), CachedReuseCount(0) {} diff --git a/lib/Driver/FrontendUtil.cpp b/lib/Driver/FrontendUtil.cpp index 10da67f95adb..f1bf9f588061 100644 --- a/lib/Driver/FrontendUtil.cpp +++ b/lib/Driver/FrontendUtil.cpp @@ -59,7 +59,7 @@ static void removeSupplementaryOutputs(llvm::opt::ArgList &ArgList) { } bool swift::driver::getSingleFrontendInvocationFromDriverArguments( - ArrayRef Argv, DiagnosticEngine &Diags, + StringRef DriverPath, ArrayRef Argv, DiagnosticEngine &Diags, llvm::function_ref FrontendArgs)> Action, bool ForceNoOutputs) { SmallVector Args; @@ -87,7 +87,7 @@ bool swift::driver::getSingleFrontendInvocationFromDriverArguments( ExpandResponseFilesWithRetry(Saver, Args); // Force the driver into batch mode by specifying "swiftc" as the name. - Driver TheDriver("swiftc", "swiftc", Args, Diags); + Driver TheDriver(DriverPath, "swiftc", Args, Diags); // Don't check for the existence of input files, since the user of the // CompilerInvocation may wish to remap inputs to source buffers. diff --git a/lib/IDETool/CompileInstance.cpp b/lib/IDETool/CompileInstance.cpp index 30af4399b726..9d17c31404bd 100644 --- a/lib/IDETool/CompileInstance.cpp +++ b/lib/IDETool/CompileInstance.cpp @@ -261,10 +261,14 @@ bool CompileInstance::setupCI( DiagnosticDocumentationPath.c_str()}); args.append(origArgs.begin(), origArgs.end()); + SmallString<256> driverPath(SwiftExecutablePath); + llvm::sys::path::remove_filename(driverPath); + llvm::sys::path::append(driverPath, "swiftc"); + CompilerInvocation invocation; bool invocationCreationFailed = driver::getSingleFrontendInvocationFromDriverArguments( - args, Diags, + driverPath, args, Diags, [&](ArrayRef FrontendArgs) { return invocation.parseArgs(FrontendArgs, Diags); }, diff --git a/lib/IDETool/CompilerInvocation.cpp b/lib/IDETool/CompilerInvocation.cpp index d34667443b64..f2027c6a123a 100644 --- a/lib/IDETool/CompilerInvocation.cpp +++ b/lib/IDETool/CompilerInvocation.cpp @@ -173,9 +173,14 @@ bool ide::initCompilerInvocation( StreamDiagConsumer DiagConsumer(ErrOS); Diags.addConsumer(DiagConsumer); + // Derive 'swiftc' path from 'swift-frontend' path (swiftExecutablePath). + SmallString<256> driverPath(swiftExecutablePath); + llvm::sys::path::remove_filename(driverPath); + llvm::sys::path::append(driverPath, "swiftc"); + bool InvocationCreationFailed = driver::getSingleFrontendInvocationFromDriverArguments( - Args, Diags, + driverPath, Args, Diags, [&](ArrayRef FrontendArgs) { return Invocation.parseArgs( FrontendArgs, Diags, /*ConfigurationFileBuffers=*/nullptr, diff --git a/test/SourceKit/Macros/macro_option_set.swift b/test/SourceKit/Macros/macro_option_set.swift new file mode 100644 index 000000000000..30d57830a504 --- /dev/null +++ b/test/SourceKit/Macros/macro_option_set.swift @@ -0,0 +1,47 @@ + +@OptionSet +struct ShippingOptions { + private enum Options: Int { + case nextDay + case secondDay + case priority + case standard + } + + static let express: ShippingOptions = [.nextDay, .secondDay] + static let all: ShippingOptions = [.express, .priority, .standard] +} + +func test(opts: ShippingOptions) { + let _ = ShippingOptions.nextDay +} + +// REQUIRES: swift_swift_parser + +// RUN: %empty-directory(%t) +// RUN: %sourcekitd-test \ +// RUN: -shell -- echo '## DIAGS ##' == \ +// RUN: -req=diags %s -- %s ==\ +// RUN: -shell -- echo '## CURSOR ##' == \ +// RUN: -req=cursor -pos=16:27 %s -- %s == \ +// RUN: -shell -- echo '## COMPLETE ##' == \ +// RUN: -req=complete -pos=16:27 %s -- %s == \ +// RUN: -shell -- echo '## COMPILE ##' == \ +// RUN: -req=compile -name test -- -c %s -module-name TestModule -o %t/out.o \ +// RUN: | %FileCheck %s + +// CHECK-LABEL: ## DIAGS ## +// CHECK: key.diagnostics: [ +// CHECK-NEXT: ] + +// CHECK-LABEL: ## CURSOR ## +// CHECK: source.lang.swift.ref.var.static + +// CHECK-LABEL: ## COMPLETE ## +// CHECK: key.results: [ +// CHECK: key.description: "secondDay" + +// CHECK-LABEL: ## COMPILE ## +// CHECK: key.diagnostics: [ +// CHECK-NEXT: ], +// CHECK: key.value: 0 diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompile.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompile.cpp index a261d6e5057e..000a39f17f1f 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompile.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompile.cpp @@ -31,9 +31,10 @@ compile::SessionManager::getSession(StringRef name) { } bool inserted = false; - std::tie(i, inserted) = sessions.try_emplace( - name, std::make_shared( - RuntimeResourcePath, DiagnosticDocumentationPath, Plugins)); + std::tie(i, inserted) = + sessions.try_emplace(name, std::make_shared( + SwiftExecutablePath, RuntimeResourcePath, + DiagnosticDocumentationPath, Plugins)); assert(inserted); return i->second; } diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp index 77ff2110e491..a8d0d9266c51 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp @@ -297,7 +297,8 @@ SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx) SKCtx.getGlobalConfiguration()); CompileManager = std::make_shared( - RuntimeResourcePath, DiagnosticDocumentationPath, Plugins); + SwiftExecutablePath, RuntimeResourcePath, DiagnosticDocumentationPath, + Plugins); // By default, just use the in-memory cache. CCCache->inMemory = std::make_unique(); diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h index 53d10f9ad5e9..5fd15b589bd2 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h +++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h @@ -292,10 +292,12 @@ class Session { swift::ide::CompileInstance Compiler; public: - Session(const std::string &RuntimeResourcePath, + Session(const std::string &SwiftExecutablePath, + const std::string &RuntimeResourcePath, const std::string &DiagnosticDocumentationPath, std::shared_ptr Plugins) - : Compiler(RuntimeResourcePath, DiagnosticDocumentationPath, Plugins) {} + : Compiler(SwiftExecutablePath, RuntimeResourcePath, + DiagnosticDocumentationPath, Plugins) {} bool performCompile(llvm::ArrayRef Args, @@ -307,6 +309,7 @@ class Session { }; class SessionManager { + const std::string &SwiftExecutablePath; const std::string &RuntimeResourcePath; const std::string &DiagnosticDocumentationPath; const std::shared_ptr Plugins; @@ -317,10 +320,12 @@ class SessionManager { mutable llvm::sys::Mutex mtx; public: - SessionManager(std::string &RuntimeResourcePath, - std::string &DiagnosticDocumentationPath, - std::shared_ptr Plugins) - : RuntimeResourcePath(RuntimeResourcePath), + SessionManager(const std::string &SwiftExecutablePath, + const std::string &RuntimeResourcePath, + const std::string &DiagnosticDocumentationPath, + const std::shared_ptr Plugins) + : SwiftExecutablePath(SwiftExecutablePath), + RuntimeResourcePath(RuntimeResourcePath), DiagnosticDocumentationPath(DiagnosticDocumentationPath), Plugins(Plugins) {} diff --git a/tools/swift-ide-test/ModuleAPIDiff.cpp b/tools/swift-ide-test/ModuleAPIDiff.cpp index 5854d1d6831e..eb0d8bfe030f 100644 --- a/tools/swift-ide-test/ModuleAPIDiff.cpp +++ b/tools/swift-ide-test/ModuleAPIDiff.cpp @@ -896,7 +896,8 @@ std::shared_ptr createSMAModel(ModuleDecl *M) { } // unnamed namespace -int swift::doGenerateModuleAPIDescription(StringRef MainExecutablePath, +int swift::doGenerateModuleAPIDescription(StringRef DriverPath, + StringRef MainExecutablePath, ArrayRef Args) { std::vector CStringArgs; for (auto &S : Args) { @@ -910,9 +911,10 @@ int swift::doGenerateModuleAPIDescription(StringRef MainExecutablePath, CompilerInvocation Invocation; bool HadError = driver::getSingleFrontendInvocationFromDriverArguments( - CStringArgs, Diags, [&](ArrayRef FrontendArgs) { - return Invocation.parseArgs(FrontendArgs, Diags); - }); + MainExecutablePath, CStringArgs, Diags, + [&](ArrayRef FrontendArgs) { + return Invocation.parseArgs(FrontendArgs, Diags); + }); if (HadError) { llvm::errs() << "error: unable to create a CompilerInvocation\n"; @@ -941,4 +943,3 @@ int swift::doGenerateModuleAPIDescription(StringRef MainExecutablePath, return 0; } - diff --git a/tools/swift-ide-test/ModuleAPIDiff.h b/tools/swift-ide-test/ModuleAPIDiff.h index b6758afc97c9..a414a767780f 100644 --- a/tools/swift-ide-test/ModuleAPIDiff.h +++ b/tools/swift-ide-test/ModuleAPIDiff.h @@ -6,7 +6,8 @@ namespace swift { -int doGenerateModuleAPIDescription(StringRef MainExecutablePath, +int doGenerateModuleAPIDescription(StringRef DriverPath, + StringRef MainExecutablePath, ArrayRef Args); } // end namespace swift diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 550300143df4..3fa2877efdf2 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -4169,7 +4169,9 @@ static int doPrintUSRs(const CompilerInvocation &InitInvok, return 0; } -static int doTestCreateCompilerInvocation(ArrayRef Args, bool ForceNoOutputs) { +static int doTestCreateCompilerInvocation(StringRef DriverPath, + ArrayRef Args, + bool ForceNoOutputs) { PrintingDiagnosticConsumer PDC; SourceManager SM; DiagnosticEngine Diags(SM); @@ -4177,14 +4179,16 @@ static int doTestCreateCompilerInvocation(ArrayRef Args, bool Forc CompilerInvocation CI; bool HadError = driver::getSingleFrontendInvocationFromDriverArguments( - Args, Diags, [&](ArrayRef FrontendArgs) { - llvm::outs() << "Frontend Arguments BEGIN\n"; - for (const char *arg : FrontendArgs) { - llvm::outs() << arg << "\n"; - } - llvm::outs() << "Frontend Arguments END\n"; - return CI.parseArgs(FrontendArgs, Diags); - }, ForceNoOutputs); + DriverPath, Args, Diags, + [&](ArrayRef FrontendArgs) { + llvm::outs() << "Frontend Arguments BEGIN\n"; + for (const char *arg : FrontendArgs) { + llvm::outs() << arg << "\n"; + } + llvm::outs() << "Frontend Arguments END\n"; + return CI.parseArgs(FrontendArgs, Diags); + }, + ForceNoOutputs); if (HadError) { llvm::errs() << "error: unable to create a CompilerInvocation\n"; @@ -4213,11 +4217,28 @@ static int doTestCompilerInvocationFromModule(StringRef ModuleFilePath) { // without being given the address of a function in the main executable). void anchorForGetMainExecutable() {} +// Derive 'swiftc' path from 'swift-ide-test' path. +std::string getDriverPath(StringRef MainExecutablePath) { + SmallString<256> driverPath(MainExecutablePath); + llvm::sys::path::remove_filename(driverPath); // remove 'swift-ide-test'. + llvm::sys::path::remove_filename(driverPath); // remove 'bin'. + if (llvm::sys::path::filename(driverPath) == "local") { + llvm::sys::path::remove_filename(driverPath); // remove 'local'. + } + llvm::sys::path::append(driverPath, "bin", "swiftc"); + return std::string(driverPath); +} + int main(int argc, char *argv[]) { PROGRAM_START(argc, argv); INITIALIZE_LLVM(); initializeSwiftModules(); + std::string mainExecutablePath = llvm::sys::fs::getMainExecutable( + argv[0], reinterpret_cast(&anchorForGetMainExecutable)); + + std::string driverPath = getDriverPath(mainExecutablePath); + if (argc > 1) { // Handle integrated test tools which do not use // llvm::cl::ParseCommandLineOptions. @@ -4229,7 +4250,7 @@ int main(int argc, char *argv[]) { ForceNoOutputs = true; Args = Args.drop_front(); } - return doTestCreateCompilerInvocation(Args, ForceNoOutputs); + return doTestCreateCompilerInvocation(driverPath, Args, ForceNoOutputs); } } @@ -4258,10 +4279,8 @@ int main(int argc, char *argv[]) { } if (options::Action == ActionType::GenerateModuleAPIDescription) { - return doGenerateModuleAPIDescription( - llvm::sys::fs::getMainExecutable( - argv[0], reinterpret_cast(&anchorForGetMainExecutable)), - options::InputFilenames); + return doGenerateModuleAPIDescription(driverPath, mainExecutablePath, + options::InputFilenames); } if (options::Action == ActionType::DumpCompletionCache) { @@ -4328,9 +4347,7 @@ int main(int argc, char *argv[]) { for (auto &File : options::InputFilenames) InitInvok.getFrontendOptions().InputsAndOutputs.addInputFile(File); - InitInvok.setMainExecutablePath( - llvm::sys::fs::getMainExecutable(argv[0], - reinterpret_cast(&anchorForGetMainExecutable))); + InitInvok.setMainExecutablePath(mainExecutablePath); InitInvok.setModuleName(options::ModuleName); InitInvok.setSDKPath(options::SDK);