From 842aca3206d392b1c6985dfc58f42389afd40ccd Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Sat, 11 Nov 2023 09:16:39 -0800 Subject: [PATCH] Support invoking known SwiftPM subcommands directly, instead of via symlink rdar://118252253 --- Sources/swift-driver/main.swift | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/Sources/swift-driver/main.swift b/Sources/swift-driver/main.swift index 69448fed5..87ddbdd7b 100644 --- a/Sources/swift-driver/main.swift +++ b/Sources/swift-driver/main.swift @@ -34,6 +34,7 @@ import class TSCBasic.Process import class TSCBasic.ProcessSet import protocol TSCBasic.DiagnosticData import var TSCBasic.localFileSystem +import struct TSCBasic.AbsolutePath let interruptSignalSource = DispatchSource.makeSignalSource(signal: SIGINT) let diagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler]) @@ -74,17 +75,38 @@ do { if case .subcommand(let subcommand) = mode { // We are running as a subcommand, try to find the subcommand adjacent to the executable we are running as. // If we didn't find the tool there, let the OS search for it. - let subcommandPath = Process.findExecutable(CommandLine.arguments[0])?.parentDirectory.appending(component: subcommand) - ?? Process.findExecutable(subcommand) + let knownSwiftPMSubcommands: Set = [ + "swift-build", + "swift-experimental-sdk", + "swift-test", + "swift-run", + "swift-package-collection", + "swift-package-registry" + ] + + let subcommandPath: AbsolutePath? + let argv0: String? + + if knownSwiftPMSubcommands.contains(subcommand) { + subcommandPath = Process.findExecutable(CommandLine.arguments[0])?.parentDirectory.appending(component: "swift-package") + ?? Process.findExecutable("swift-package") + // Set argv[0] to dispatch to the requested SwiftPM subcommand + argv0 = subcommandPath?.parentDirectory.appending(component: subcommand).pathString + } else { + subcommandPath = Process.findExecutable(CommandLine.arguments[0])?.parentDirectory.appending(component: subcommand) + ?? Process.findExecutable(subcommand) + argv0 = subcommandPath?.pathString + } guard let subcommandPath = subcommandPath, + let argv0 = argv0, localFileSystem.exists(subcommandPath) else { throw Driver.Error.unknownOrMissingSubcommand(subcommand) } // Pass the full path to subcommand executable. var arguments = arguments - arguments[0] = subcommandPath.pathString + arguments[0] = argv0 // Execute the subcommand. try exec(path: subcommandPath.pathString, args: arguments)