Skip to content

Commit 0fd6eca

Browse files
committed
Replace SwiftDriverExecutor with SPMSwiftDriverExecutor
SPM does not need or use the full functionality of SwiftDriverExecutor, which we're planning to move to a separate library so that the SwiftDriver planning lib no longer depends on LLBuild. Introduce a miinimal SPMSwiftDriverExecutor for the processes the integrated driver needs to launch during planning.
1 parent cadaa5a commit 0fd6eca

File tree

3 files changed

+87
-11
lines changed

3 files changed

+87
-11
lines changed

Sources/Build/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_library(Build
1111
BuildOperation.swift
1212
BuildPlan.swift
1313
ManifestBuilder.swift
14+
SPMSwiftDriverExecutor.swift
1415
SwiftCompilerOutputParser.swift
1516
XCFrameworkInfo.swift)
1617
target_link_libraries(Build PUBLIC

Sources/Build/ManifestBuilder.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -220,24 +220,24 @@ extension LLBuildManifestBuilder {
220220
commandLine.append(buildParameters.toolchain.swiftCompiler.pathString)
221221
// FIXME: At some point SwiftPM should provide its own executor for
222222
// running jobs/launching processes during planning
223-
let executor = try SwiftDriverExecutor(diagnosticsEngine: plan.diagnostics,
224-
processSet: ProcessSet(),
225-
fileSystem: target.fs,
226-
env: ProcessEnv.vars)
223+
let resolver = try ArgsResolver(fileSystem: target.fs)
224+
let executor = SPMSwiftDriverExecutor(resolver: resolver,
225+
fileSystem: target.fs,
226+
env: ProcessEnv.vars)
227227
var driver = try Driver(args: commandLine,
228228
diagnosticsEngine: plan.diagnostics,
229229
fileSystem: target.fs,
230230
executor: executor)
231231
let jobs = try driver.planBuild()
232-
try addSwiftDriverJobs(for: target, jobs: jobs, inputs: inputs,
232+
try addSwiftDriverJobs(for: target, jobs: jobs, inputs: inputs, resolver: resolver,
233233
isMainModule: { driver.isExplicitMainModuleJob(job: $0)})
234234
}
235235

236236
private func addSwiftDriverJobs(for targetDescription: SwiftTargetBuildDescription,
237237
jobs: [Job], inputs: [Node],
238+
resolver: ArgsResolver,
238239
isMainModule: (Job) -> Bool) throws {
239240
// Add build jobs to the manifest
240-
let resolver = try ArgsResolver(fileSystem: targetDescription.fs)
241241
for job in jobs {
242242
let tool = try resolver.resolve(.path(job.tool))
243243
let commandLine = try job.commandLine.map{ try resolver.resolve($0) }
@@ -377,10 +377,10 @@ extension LLBuildManifestBuilder {
377377
commandLine.append("-experimental-explicit-module-build")
378378
// FIXME: At some point SwiftPM should provide its own executor for
379379
// running jobs/launching processes during planning
380-
let executor = try SwiftDriverExecutor(diagnosticsEngine: plan.diagnostics,
381-
processSet: ProcessSet(),
382-
fileSystem: targetDescription.fs,
383-
env: ProcessEnv.vars)
380+
let resolver = try ArgsResolver(fileSystem: targetDescription.fs)
381+
let executor = SPMSwiftDriverExecutor(resolver: resolver,
382+
fileSystem: targetDescription.fs,
383+
env: ProcessEnv.vars)
384384
var driver = try Driver(args: commandLine, fileSystem: targetDescription.fs,
385385
executor: executor,
386386
externalModuleDependencies: targetDependencyMap)
@@ -392,7 +392,7 @@ extension LLBuildManifestBuilder {
392392
fatalError("Expected module dependency graph for target: \(targetDescription)")
393393
}
394394
targetDepGraphMap[targetDescription.target] = dependencyGraph
395-
try addSwiftDriverJobs(for: targetDescription, jobs: jobs, inputs: inputs,
395+
try addSwiftDriverJobs(for: targetDescription, jobs: jobs, inputs: inputs, resolver: resolver,
396396
isMainModule: { driver.isExplicitMainModuleJob(job: $0)})
397397
}
398398

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright 2020 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
@_implementationOnly import SwiftDriver
12+
import TSCBasic
13+
import Foundation
14+
15+
final class SPMSwiftDriverExecutor: DriverExecutor {
16+
let resolver: ArgsResolver
17+
let fileSystem: FileSystem
18+
let env: [String: String]
19+
20+
init(resolver: ArgsResolver,
21+
fileSystem: FileSystem,
22+
env: [String: String]) {
23+
self.resolver = resolver
24+
self.fileSystem = fileSystem
25+
self.env = env
26+
}
27+
28+
func execute(job: Job,
29+
forceResponseFiles: Bool,
30+
recordedInputModificationDates: [TypedVirtualPath : Date]) throws -> ProcessResult {
31+
let arguments: [String] = try resolver.resolveArgumentList(for: job,
32+
forceResponseFiles: forceResponseFiles)
33+
34+
try job.verifyInputsNotModified(since: recordedInputModificationDates,
35+
fileSystem: fileSystem)
36+
assert(!job.requiresInPlaceExecution,
37+
"SPM should not plan builds that require in-place execution.")
38+
39+
var childEnv = env
40+
childEnv.merge(job.extraEnvironment, uniquingKeysWith: { (_, new) in new })
41+
42+
let process = try Process.launchProcess(arguments: arguments, env: childEnv)
43+
return try process.waitUntilExit()
44+
}
45+
46+
func execute(jobs: [Job], delegate: JobExecutionDelegate,
47+
numParallelJobs: Int, forceResponseFiles: Bool,
48+
recordedInputModificationDates: [TypedVirtualPath : Date]) throws {
49+
fatalError("Multi-job build plans should be lifted into the SPM build graph.")
50+
}
51+
52+
func checkNonZeroExit(args: String..., environment: [String : String]) throws -> String {
53+
return try Process.checkNonZeroExit(arguments: args, environment: environment)
54+
}
55+
56+
func description(of job: Job, forceResponseFiles: Bool) throws -> String {
57+
// FIXME: This is duplicated from SwiftDriver, maybe it shouldn't be a protocol requirement.
58+
let (args, usedResponseFile) = try resolver.resolveArgumentList(for: job,
59+
forceResponseFiles: forceResponseFiles)
60+
var result = args.joined(separator: " ")
61+
62+
if usedResponseFile {
63+
// Print the response file arguments as a comment.
64+
result += " # \(job.commandLine.joinedArguments)"
65+
}
66+
67+
if !job.extraEnvironment.isEmpty {
68+
result += " #"
69+
for (envVar, val) in job.extraEnvironment {
70+
result += " \(envVar)=\(val)"
71+
}
72+
}
73+
return result
74+
}
75+
}

0 commit comments

Comments
 (0)