Skip to content

Move forwarding to non-compiler driver kinds into the planning stage #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Sources/SwiftDriver/Driver/Driver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -558,10 +558,6 @@ extension Driver {
executorDelegate: JobExecutorDelegate? = nil,
processSet: ProcessSet? = nil
) throws {
// We just need to invoke the corresponding tool if the kind isn't Swift compiler.
guard driverKind.isSwiftCompiler else {
return try exec(path: toolchain.getToolPath(.swiftCompiler).pathString, args: driverKind.usageArgs + parsedOptions.commandLine)
}

if parsedOptions.contains(.help) || parsedOptions.contains(.helpHidden) {
optionTable.printHelp(driverKind: driverKind, includeHidden: parsedOptions.contains(.helpHidden))
Expand Down
16 changes: 8 additions & 8 deletions Sources/SwiftDriver/Driver/DriverKind.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,28 @@ public enum DriverKind {

extension DriverKind {
public var usage: String {
usageArgs.joined(separator: " ")
usageArgs.joinedArguments
}

public var usageArgs: [String] {
public var usageArgs: [Job.ArgTemplate] {
switch self {
case .autolinkExtract:
return ["swift-autolink-extract"]
return [.flag("swift-autolink-extract")]

case .batch:
return ["swiftc"]
return [.flag("swiftc")]

case .frontend:
return ["swift", "-frontend"]
return [.flag("swift"), .flag("-frontend")]

case .indent:
return ["swift-indent"]
return [.flag("swift-indent")]

case .interactive:
return ["swift"]
return [.flag("swift")]

case .moduleWrap:
return ["swift-modulewrap"]
return [.flag("swift-modulewrap")]
}
}

Expand Down
3 changes: 3 additions & 0 deletions Sources/SwiftDriver/Jobs/Job.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public struct Job: Codable, Equatable {
case verifyDebugInfo = "verify-debug-info"
case printTargetInfo = "print-target-info"
case versionRequest = "version-request"

// A generic job which forwards a command line to another tool.
case forwarding
}

public enum ArgTemplate: Equatable {
Expand Down
14 changes: 14 additions & 0 deletions Sources/SwiftDriver/Jobs/Planning.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,20 @@ extension Driver {
/// Create a job if needed for simple requests that can be immediately
/// forwarded to the frontend.
public mutating func immediateForwardingJob() throws -> Job? {

// We just need to invoke the corresponding tool if the kind isn't Swift compiler.
if !driverKind.isSwiftCompiler {
var commandLine: [Job.ArgTemplate] = driverKind.usageArgs
try commandLine.append(contentsOf: parsedOptions.allArguments())
return Job(kind: .forwarding,
tool: .absolute(try toolchain.getToolPath(.swiftCompiler)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting choice. In many of these cases, we're not actually executing the Swift compiler, but some other tool. Should we look up that tool by name, rather than having the "tool" effectively be ignored?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the way to go. It'll be a lot simpler once the compiler binary is renamed to swift-frontend though. That'll allow us to avoid needing to add -frontend or -modulewrap when invoking it with the right tool name. This PR isn't an important change, so I might just hold off on landing it until then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like I really need to finish off that compiler binary rename. Thanks for the nudge ;)

commandLine: commandLine,
displayInputs: [],
inputs: [],
outputs: [],
requiresInPlaceExecution: true)
}

if parsedOptions.hasArgument(.printTargetInfo) {
var commandLine: [Job.ArgTemplate] = [.flag("-frontend"),
.flag("-print-target-info")]
Expand Down
8 changes: 8 additions & 0 deletions Sources/SwiftDriver/Options/ParsedOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ extension ParsedOptions {
return result
}

/// Return all options and mark them as consumed.
public mutating func allArguments() -> [ParsedOption] {
for option in parsedOptions {
consumed[option.index] = true
}
return parsedOptions
}

public mutating func arguments(for options: Option...) -> [ParsedOption] {
return options.flatMap { lookup($0) }
}
Expand Down
61 changes: 61 additions & 0 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,67 @@ final class SwiftDriverTests: XCTestCase {
try assertArgsThrow("swiftc", "--driver-mode=")
}

func testForwarding() throws {
do {
var driver = try Driver(args: ["swiftc", "-frontend", "foo", "bar",
"-debug-assert-after-parse"])
let plannedJobs = try driver.planBuild()
XCTAssertEqual(plannedJobs.count, 1)
let forwardingJob = plannedJobs.first!
XCTAssertEqual(forwardingJob.kind, .forwarding)
XCTAssertTrue(forwardingJob.requiresInPlaceExecution)
let expected: [Job.ArgTemplate] = [.flag("swift"), .flag("-frontend"),
.path(try VirtualPath(path: "foo")),
.path(try VirtualPath(path: "bar")),
.flag("-debug-assert-after-parse")]
XCTAssertEqual(forwardingJob.commandLine, expected)
}

do {
var driver = try Driver(args: ["swiftc",
"--driver-mode=swift-autolink-extract",
"foo"])
let plannedJobs = try driver.planBuild()
XCTAssertEqual(plannedJobs.count, 1)
let forwardingJob = plannedJobs.first!
XCTAssertEqual(forwardingJob.kind, .forwarding)
XCTAssertTrue(forwardingJob.requiresInPlaceExecution)
let expected: [Job.ArgTemplate] = [.flag("swift-autolink-extract"),
.path(try VirtualPath(path: "foo"))]
XCTAssertEqual(forwardingJob.commandLine, expected)
}

do {
var driver = try Driver(args: ["swiftc",
"--driver-mode=swift-indent",
"bar"])
let plannedJobs = try driver.planBuild()
XCTAssertEqual(plannedJobs.count, 1)
let forwardingJob = plannedJobs.first!
XCTAssertEqual(forwardingJob.kind, .forwarding)
XCTAssertTrue(forwardingJob.requiresInPlaceExecution)
let expected: [Job.ArgTemplate] = [.flag("swift-indent"),
.path(try VirtualPath(path: "bar"))]
XCTAssertEqual(forwardingJob.commandLine, expected)
}

do {
var driver = try Driver(args: ["swiftc",
"-modulewrap",
"bar", "-o", "foo"])
let plannedJobs = try driver.planBuild()
XCTAssertEqual(plannedJobs.count, 1)
let forwardingJob = plannedJobs.first!
XCTAssertEqual(forwardingJob.kind, .forwarding)
XCTAssertTrue(forwardingJob.requiresInPlaceExecution)
let expected: [Job.ArgTemplate] = [.flag("swift-modulewrap"),
.path(try VirtualPath(path: "bar")),
.flag("-o"),
.path(try VirtualPath(path: "foo"))]
XCTAssertEqual(forwardingJob.commandLine, expected)
}
}

func testCompilerMode() throws {
do {
let driver1 = try Driver(args: ["swift", "main.swift"])
Expand Down