Skip to content

Commit 717e9c7

Browse files
Merge branch 'master' into cs_embedBitcode
2 parents f5aba8b + 573a322 commit 717e9c7

24 files changed

+587
-78
lines changed

Sources/SwiftDriver/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ add_library(SwiftDriver
2222
"Incremental Compilation/IncrementalCompilation.swift"
2323
"Incremental Compilation/InputIInfoMap.swift"
2424
"Incremental Compilation/InputInfo.swift"
25+
"Incremental Compilation/SourceFileDependencyGraph.swift"
2526

2627
Jobs/AutolinkExtractJob.swift
2728
Jobs/CommandLineArguments.swift

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ public struct Driver {
7777
/// it should be identical to the real environment.
7878
public let env: [String: String]
7979

80+
/// The file system which we should interact with.
81+
public let fileSystem: FileSystem
82+
8083
/// Diagnostic engine for emitting warnings, errors, etc.
8184
public let diagnosticEngine: DiagnosticsEngine
8285

@@ -229,17 +232,19 @@ public struct Driver {
229232
public init(
230233
args: [String],
231234
env: [String: String] = ProcessEnv.vars,
232-
diagnosticsEngine: DiagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler])
235+
diagnosticsEngine: DiagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler]),
236+
fileSystem: FileSystem = localFileSystem
233237
) throws {
234238
self.env = env
239+
self.fileSystem = fileSystem
235240

236241
self.diagnosticEngine = diagnosticsEngine
237242

238243
if case .subcommand = try Self.invocationRunMode(forArgs: args).mode {
239244
throw Error.subcommandPassedToDriver
240245
}
241246

242-
var args = try Self.expandResponseFiles(args, diagnosticsEngine: self.diagnosticEngine)[...]
247+
var args = try Self.expandResponseFiles(args, fileSystem: fileSystem, diagnosticsEngine: self.diagnosticEngine)[...]
243248

244249
self.driverKind = try Self.determineDriverKind(args: &args)
245250
self.optionTable = OptionTable()
@@ -249,7 +254,7 @@ public struct Driver {
249254
.map {
250255
Triple($0, normalizing: true)
251256
}
252-
(self.toolchain, self.targetTriple) = try Self.computeToolchain(explicitTarget, diagnosticsEngine: diagnosticEngine, env: env)
257+
(self.toolchain, self.targetTriple) = try Self.computeToolchain(explicitTarget, diagnosticsEngine: diagnosticEngine, env: env, fileSystem: fileSystem)
253258
self.targetVariantTriple = self.parsedOptions.getLastArgument(.targetVariant).map { Triple($0.asSingle, normalizing: true) }
254259

255260
// Find the Swift compiler executable.
@@ -269,7 +274,7 @@ public struct Driver {
269274

270275
// Compute the working directory.
271276
workingDirectory = try parsedOptions.getLastArgument(.workingDirectory).map { workingDirectoryArg in
272-
let cwd = localFileSystem.currentWorkingDirectory
277+
let cwd = fileSystem.currentWorkingDirectory
273278
return try cwd.map{ AbsolutePath(workingDirectoryArg.asSingle, relativeTo: $0) } ?? AbsolutePath(validating: workingDirectoryArg.asSingle)
274279
}
275280

@@ -283,7 +288,7 @@ public struct Driver {
283288
self.inputFiles = inputFiles
284289
self.recordedInputModificationDates = .init(uniqueKeysWithValues:
285290
Set(inputFiles).compactMap {
286-
guard let modTime = try? localFileSystem
291+
guard let modTime = try? fileSystem
287292
.getFileInfo($0.file).modTime else { return nil }
288293
return ($0, modTime)
289294
})
@@ -292,7 +297,7 @@ public struct Driver {
292297
// Initialize an empty output file map, which will be populated when we start creating jobs.
293298
if let outputFileMapArg = parsedOptions.getLastArgument(.outputFileMap)?.asSingle {
294299
let path = try VirtualPath(path: outputFileMapArg)
295-
outputFileMap = try .load(file: path, diagnosticEngine: diagnosticEngine)
300+
outputFileMap = try .load(fileSystem: fileSystem, file: path, diagnosticEngine: diagnosticEngine)
296301
} else {
297302
outputFileMap = nil
298303
}
@@ -330,13 +335,14 @@ public struct Driver {
330335
compilerMode: compilerMode,
331336
outputFileMap: self.outputFileMap,
332337
compilerOutputType: self.compilerOutputType,
333-
moduleOutput: self.moduleOutput,
338+
moduleOutput: self.moduleOutput,
339+
fileSystem: fileSystem,
334340
inputFiles: inputFiles,
335341
diagnosticEngine: diagnosticEngine,
336342
actualSwiftVersion: try? toolchain.swiftCompilerVersion()
337343
)
338344

339-
self.sdkPath = Self.computeSDKPath(&parsedOptions, compilerMode: compilerMode, toolchain: toolchain, diagnosticsEngine: diagnosticEngine, env: env)
345+
self.sdkPath = Self.computeSDKPath(&parsedOptions, compilerMode: compilerMode, toolchain: toolchain, fileSystem: fileSystem, diagnosticsEngine: diagnosticEngine, env: env)
340346

341347
self.importedObjCHeader = try Self.computeImportedObjCHeader(&parsedOptions, compilerMode: compilerMode, diagnosticEngine: diagnosticEngine)
342348
self.bridgingPrecompiledHeader = try Self.computeBridgingPrecompiledHeader(&parsedOptions,
@@ -534,6 +540,7 @@ extension Driver {
534540
/// - Parameter visitedResponseFiles: Set containing visited response files to detect recursive parsing.
535541
private static func expandResponseFiles(
536542
_ args: [String],
543+
fileSystem: FileSystem,
537544
diagnosticsEngine: DiagnosticsEngine,
538545
visitedResponseFiles: inout Set<AbsolutePath>
539546
) throws -> [String] {
@@ -551,9 +558,9 @@ extension Driver {
551558
visitedResponseFiles.remove(responseFile)
552559
}
553560

554-
let contents = try localFileSystem.readFileContents(responseFile).cString
561+
let contents = try fileSystem.readFileContents(responseFile).cString
555562
let lines = tokenizeResponseFile(contents)
556-
result.append(contentsOf: try expandResponseFiles(lines, diagnosticsEngine: diagnosticsEngine, visitedResponseFiles: &visitedResponseFiles))
563+
result.append(contentsOf: try expandResponseFiles(lines, fileSystem: fileSystem, diagnosticsEngine: diagnosticsEngine, visitedResponseFiles: &visitedResponseFiles))
557564
} else {
558565
result.append(arg)
559566
}
@@ -565,24 +572,23 @@ extension Driver {
565572
/// Expand response files in the input arguments and return a new argument list.
566573
public static func expandResponseFiles(
567574
_ args: [String],
575+
fileSystem: FileSystem,
568576
diagnosticsEngine: DiagnosticsEngine
569577
) throws -> [String] {
570578
var visitedResponseFiles = Set<AbsolutePath>()
571-
return try expandResponseFiles(args, diagnosticsEngine: diagnosticsEngine, visitedResponseFiles: &visitedResponseFiles)
579+
return try expandResponseFiles(args, fileSystem: fileSystem, diagnosticsEngine: diagnosticsEngine, visitedResponseFiles: &visitedResponseFiles)
572580
}
573581
}
574582

575583
extension Driver {
576584
/// Determine the driver kind based on the command-line arguments, consuming the arguments
577585
/// conveying this information.
578586
public static func determineDriverKind(
579-
args: inout ArraySlice<String>,
580-
cwd: AbsolutePath? = localFileSystem.currentWorkingDirectory
587+
args: inout ArraySlice<String>
581588
) throws -> DriverKind {
582589
// Get the basename of the driver executable.
583590
let execRelPath = args.removeFirst()
584-
let execPath = try cwd.map{ AbsolutePath(execRelPath, relativeTo: $0) } ?? AbsolutePath(validating: execRelPath)
585-
var driverName = execPath.basename
591+
var driverName = try VirtualPath(path: execRelPath).basenameWithoutExt
586592

587593
// Determine driver kind based on the first argument.
588594
let driverModeOption = "--driver-mode="
@@ -680,7 +686,7 @@ extension Driver {
680686
forceResponseFiles: forceResponseFiles,
681687
recordedInputModificationDates: recordedInputModificationDates
682688
)
683-
try jobExecutor.execute(env: env)
689+
try jobExecutor.execute(env: env, fileSystem: fileSystem)
684690
}
685691

686692
public mutating func createToolExecutionDelegate() -> ToolExecutionDelegate {
@@ -704,7 +710,7 @@ extension Driver {
704710
try ProcessEnv.setVar(envVar, value: value)
705711
}
706712

707-
try job.verifyInputsNotModified(since: self.recordedInputModificationDates)
713+
try job.verifyInputsNotModified(since: self.recordedInputModificationDates, fileSystem: fileSystem)
708714

709715
return try exec(path: arguments[0], args: arguments)
710716
}
@@ -988,6 +994,9 @@ extension Driver {
988994
case .interpret:
989995
compilerOutputType = nil
990996

997+
case .scanDependencies:
998+
compilerOutputType = .jsonDependencies
999+
9911000
default:
9921001
fatalError("unhandled output mode option \(outputOption)")
9931002
}
@@ -1401,6 +1410,7 @@ extension Driver {
14011410
_ parsedOptions: inout ParsedOptions,
14021411
compilerMode: CompilerMode,
14031412
toolchain: Toolchain,
1413+
fileSystem: FileSystem,
14041414
diagnosticsEngine: DiagnosticsEngine,
14051415
env: [String: String]
14061416
) -> String? {
@@ -1436,14 +1446,14 @@ extension Driver {
14361446
// FIXME: TSC should provide a better utility for this.
14371447
if let absPath = try? AbsolutePath(validating: sdkPath) {
14381448
path = absPath
1439-
} else if let cwd = localFileSystem.currentWorkingDirectory {
1449+
} else if let cwd = fileSystem.currentWorkingDirectory {
14401450
path = AbsolutePath(sdkPath, relativeTo: cwd)
14411451
} else {
14421452
diagnosticsEngine.emit(.warning_no_such_sdk(sdkPath))
14431453
return sdkPath
14441454
}
14451455

1446-
if !localFileSystem.exists(path) {
1456+
if !fileSystem.exists(path) {
14471457
diagnosticsEngine.emit(.warning_no_such_sdk(sdkPath))
14481458
}
14491459
// .. else check if SDK is too old (we need target triple to diagnose that).
@@ -1549,11 +1559,12 @@ extension Driver {
15491559
static func computeToolchain(
15501560
_ explicitTarget: Triple?,
15511561
diagnosticsEngine: DiagnosticsEngine,
1552-
env: [String: String]
1562+
env: [String: String],
1563+
fileSystem: FileSystem
15531564
) throws -> (Toolchain, Triple) {
15541565
let toolchainType = try explicitTarget?.toolchainType(diagnosticsEngine) ??
15551566
defaultToolchainType
1556-
let toolchain = toolchainType.init(env: env)
1567+
let toolchain = toolchainType.init(env: env, fileSystem: fileSystem)
15571568
return (toolchain, try explicitTarget ?? toolchain.hostTargetTriple())
15581569
}
15591570
}

Sources/SwiftDriver/Driver/OutputFileMap.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import TSCBasic
1313
import Foundation
1414

15+
public typealias FileSystem = TSCBasic.FileSystem
16+
1517
/// Mapping of input file paths to specific output files.
1618
public struct OutputFileMap: Equatable {
1719
/// The known mapping from input file to specific output files.
@@ -68,11 +70,12 @@ public struct OutputFileMap: Equatable {
6870

6971
/// Load the output file map at the given path.
7072
public static func load(
73+
fileSystem: FileSystem,
7174
file: VirtualPath,
7275
diagnosticEngine: DiagnosticsEngine
7376
) throws -> OutputFileMap {
7477
// Load and decode the file.
75-
let contents = try localFileSystem.readFileContents(file)
78+
let contents = try fileSystem.readFileContents(file)
7679
let result = try JSONDecoder().decode(OutputFileMapJSON.self, from: Data(contents.contents))
7780

7881
// Convert the loaded entries into virual output file map.
@@ -84,6 +87,7 @@ public struct OutputFileMap: Equatable {
8487

8588
/// Store the output file map at the given path.
8689
public func store(
90+
fileSystem: FileSystem,
8791
file: AbsolutePath,
8892
diagnosticEngine: DiagnosticsEngine
8993
) throws {
@@ -98,7 +102,7 @@ public struct OutputFileMap: Equatable {
98102
#endif
99103

100104
let contents = try encoder.encode(OutputFileMapJSON.fromVirtualOutputFileMap(entries).entries)
101-
try localFileSystem.writeFileContents(file, bytes: ByteString(contents))
105+
try fileSystem.writeFileContents(file, bytes: ByteString(contents))
102106
}
103107
}
104108

Sources/SwiftDriver/Execution/JobExecutor.swift

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@ public struct ArgsResolver {
2020
/// The map of virtual path to the actual path.
2121
public var pathMapping: [VirtualPath: AbsolutePath]
2222

23+
/// The file system used by the resolver.
24+
private let fileSystem: FileSystem
25+
2326
/// Path to the directory that will contain the temporary files.
2427
private let temporaryDirectory: AbsolutePath
2528

26-
public init() throws {
29+
public init(fileSystem: FileSystem = localFileSystem) throws {
2730
self.pathMapping = [:]
31+
self.fileSystem = fileSystem
2832
self.temporaryDirectory = try withTemporaryDirectory(removeTreeOnDeinit: false) { path in
2933
// FIXME: TSC removes empty directories even when removeTreeOnDeinit is false. This seems like a bug.
30-
try localFileSystem.writeFileContents(path.appending(component: ".keep-directory")) { $0 <<< "" }
34+
try fileSystem.writeFileContents(path.appending(component: ".keep-directory")) { $0 <<< "" }
3135
return path
3236
}
3337
}
@@ -75,7 +79,7 @@ public struct ArgsResolver {
7579
"Platform does not support response files for job: \(job)")
7680
// Match the integrated driver's behavior, which uses response file names of the form "arguments-[0-9a-zA-Z].resp".
7781
let responseFilePath = temporaryDirectory.appending(component: "arguments-\(abs(job.hashValue)).resp")
78-
try localFileSystem.writeFileContents(responseFilePath) {
82+
try fileSystem.writeFileContents(responseFilePath) {
7983
$0 <<< resolvedArguments[1...].map{ $0.spm_shellEscaped() }.joined(separator: "\n")
8084
}
8185
resolvedArguments = [resolvedArguments[0], "@\(responseFilePath.pathString)"]
@@ -123,6 +127,9 @@ public final class JobExecutor {
123127
/// The environment variables.
124128
let env: [String: String]
125129

130+
/// The file system.
131+
let fileSystem: FileSystem
132+
126133
/// The job executor delegate.
127134
let executorDelegate: JobExecutorDelegate
128135

@@ -144,6 +151,7 @@ public final class JobExecutor {
144151
init(
145152
argsResolver: ArgsResolver,
146153
env: [String: String],
154+
fileSystem: FileSystem,
147155
producerMap: [VirtualPath: Job],
148156
executorDelegate: JobExecutorDelegate,
149157
jobQueue: OperationQueue,
@@ -154,6 +162,7 @@ public final class JobExecutor {
154162
self.producerMap = producerMap
155163
self.argsResolver = argsResolver
156164
self.env = env
165+
self.fileSystem = fileSystem
157166
self.executorDelegate = executorDelegate
158167
self.jobQueue = jobQueue
159168
self.processSet = processSet
@@ -202,8 +211,8 @@ public final class JobExecutor {
202211
}
203212

204213
/// Execute all jobs.
205-
public func execute(env: [String: String]) throws {
206-
let context = createContext(jobs, env: env)
214+
public func execute(env: [String: String], fileSystem: FileSystem) throws {
215+
let context = createContext(jobs, env: env, fileSystem: fileSystem)
207216

208217
let delegate = JobExecutorBuildDelegate(context)
209218
let engine = LLBuildEngine(delegate: delegate)
@@ -217,7 +226,7 @@ public final class JobExecutor {
217226
}
218227

219228
/// Create the context required during the execution.
220-
func createContext(_ jobs: [Job], env: [String: String]) -> Context {
229+
func createContext(_ jobs: [Job], env: [String: String], fileSystem: FileSystem) -> Context {
221230
var producerMap: [VirtualPath: Job] = [:]
222231
for job in jobs {
223232
for output in job.outputs {
@@ -233,6 +242,7 @@ public final class JobExecutor {
233242
return Context(
234243
argsResolver: argsResolver,
235244
env: env,
245+
fileSystem: fileSystem,
236246
producerMap: producerMap,
237247
executorDelegate: executorDelegate,
238248
jobQueue: jobQueue,
@@ -254,7 +264,7 @@ struct JobExecutorBuildDelegate: LLBuildEngineDelegate {
254264
func lookupRule(rule: String, key: Key) -> Rule {
255265
switch rule {
256266
case ExecuteAllJobsRule.ruleName:
257-
return ExecuteAllJobsRule(key)
267+
return ExecuteAllJobsRule(key, fileSystem: context.fileSystem)
258268
case ExecuteJobRule.ruleName:
259269
return ExecuteJobRule(key, context: context)
260270
default:
@@ -295,9 +305,9 @@ class ExecuteAllJobsRule: LLBuildRule {
295305
/// True if any of the inputs had any error.
296306
private var allInputsSucceeded: Bool = true
297307

298-
init(_ key: Key) {
308+
init(_ key: Key, fileSystem: FileSystem) {
299309
self.key = RuleKey(key)
300-
super.init()
310+
super.init(fileSystem: fileSystem)
301311
}
302312

303313
override func start(_ engine: LLTaskBuildEngine) {
@@ -344,7 +354,7 @@ class ExecuteJobRule: LLBuildRule {
344354
init(_ key: Key, context: JobExecutor.Context) {
345355
self.key = RuleKey(key)
346356
self.context = context
347-
super.init()
357+
super.init(fileSystem: context.fileSystem)
348358
}
349359

350360
override func start(_ engine: LLTaskBuildEngine) {
@@ -392,7 +402,7 @@ class ExecuteJobRule: LLBuildRule {
392402
let arguments: [String] = try resolver.resolveArgumentList(for: job,
393403
forceResponseFiles: context.forceResponseFiles)
394404

395-
try job.verifyInputsNotModified(since: context.recordedInputModificationDates)
405+
try job.verifyInputsNotModified(since: context.recordedInputModificationDates, fileSystem: engine.fileSystem)
396406

397407
let process = try context.executorDelegate.launchProcess(
398408
for: job, arguments: arguments, env: env

0 commit comments

Comments
 (0)