Skip to content

Fix Driver/driver-compile.swift #475

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

Merged
merged 2 commits into from
Feb 10, 2021
Merged
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
44 changes: 40 additions & 4 deletions Sources/SwiftDriver/Driver/Driver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ public struct Driver {
.appending(component: filename + ".priors")
}

/// Whether to consider incremental compilation.
let shouldAttemptIncrementalCompilation: Bool
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we can clean things up by running this check when we're planning the build in the first place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's where it was before, in the creation of IncrementalCompilationState, but I needed this for computeSupplementaryOutputPath for -emit-reference-dependencies-path. It likely makes sense to delay this check until later, currently if incremental builds are later disabled we still pass -emit-reference-dependencies-path to the frontend. That's the c++ driver logic that I'm imitating here, so that the tests pass, but long term it's worth evaluating if that's the right approach. (I honestly don't know much about incremental builds and swiftDeps, so I can't say for sure one way or the other. My approach so far with swift-driver is trying to get it to feature parity with c++, making sure it can stand in and have the lit tests still pass.)


/// Code & data for incremental compilation. Nil if not running in incremental mode.
/// Set during planning because needs the jobs to look at outputs.
@_spi(Testing) public private(set) var incrementalCompilationState: IncrementalCompilationState? = nil
Expand Down Expand Up @@ -246,6 +249,9 @@ public struct Driver {

/// Path to the dependencies file.
let dependenciesFilePath: VirtualPath?

/// Path to the references dependencies file.
let referenceDependenciesPath: VirtualPath?

/// Path to the serialized diagnostics file.
let serializedDiagnosticsFilePath: VirtualPath?
Expand Down Expand Up @@ -376,6 +382,10 @@ public struct Driver {

// Determine the compilation mode.
self.compilerMode = try Self.computeCompilerMode(&parsedOptions, driverKind: driverKind, diagnosticsEngine: diagnosticEngine)

self.shouldAttemptIncrementalCompilation = Self.shouldAttemptIncrementalCompilation(&parsedOptions,
diagnosticEngine: diagnosticsEngine,
compilerMode: compilerMode)

// Compute the working directory.
workingDirectory = try parsedOptions.getLastArgument(.workingDirectory).map { workingDirectoryArg in
Expand Down Expand Up @@ -411,7 +421,7 @@ public struct Driver {
swiftCompilerPrefixArgs: self.swiftCompilerPrefixArgs)

// Classify and collect all of the input files.
let inputFiles = try Self.collectInputFiles(&self.parsedOptions)
let inputFiles = try Self.collectInputFiles(&self.parsedOptions, diagnosticsEngine: diagnosticsEngine)
self.inputFiles = inputFiles
self.recordedInputModificationDates = .init(uniqueKeysWithValues:
Set(inputFiles).compactMap {
Expand Down Expand Up @@ -533,6 +543,13 @@ public struct Driver {
compilerMode: compilerMode,
outputFileMap: self.outputFileMap,
moduleName: moduleOutputInfo.name)
self.referenceDependenciesPath = try Self.computeSupplementaryOutputPath(
&parsedOptions, type: .swiftDeps, isOutputOptions: shouldAttemptIncrementalCompilation ? [.incremental] : [],
outputPath: .emitReferenceDependenciesPath,
compilerOutputType: compilerOutputType,
compilerMode: compilerMode,
outputFileMap: self.outputFileMap,
moduleName: moduleOutputInfo.name)
self.serializedDiagnosticsFilePath = try Self.computeSupplementaryOutputPath(
&parsedOptions, type: .diagnostics, isOutputOptions: [.serializeDiagnostics],
outputPath: .serializeDiagnosticsPath,
Expand Down Expand Up @@ -1314,7 +1331,8 @@ extension Driver {
}

/// Collect all of the input files from the parsed options, translating them into input files.
private static func collectInputFiles(_ parsedOptions: inout ParsedOptions) throws -> [TypedVirtualPath] {
private static func collectInputFiles(_ parsedOptions: inout ParsedOptions, diagnosticsEngine: DiagnosticsEngine) throws -> [TypedVirtualPath] {
var swiftFiles = [String: String]() // [Basename: Path]
return try parsedOptions.allInputs.map { input in
// Standard input is assumed to be Swift code.
if input == "-" {
Expand All @@ -1330,6 +1348,17 @@ extension Driver {
// FIXME: The object-file default is carried over from the existing
// driver, but seems odd.
let fileType = FileType(rawValue: fileExtension) ?? FileType.object

if fileType == .swift {
let basename = file.basename
if let originalPath = swiftFiles[basename] {
diagnosticsEngine.emit(.error_two_files_same_name(basename: basename, firstPath: originalPath, secondPath: input))
diagnosticsEngine.emit(.note_explain_two_files_same_name)
throw Diagnostics.fatalError
} else {
swiftFiles[basename] = input
}
}

return TypedVirtualPath(file: file, type: fileType)
}
Expand Down Expand Up @@ -1453,6 +1482,14 @@ extension Diagnostic.Message {
static var warn_ignore_embed_bitcode_marker: Diagnostic.Message {
.warning("ignoring -embed-bitcode-marker since no object file is being generated")
}

static func error_two_files_same_name(basename: String, firstPath: String, secondPath: String) -> Diagnostic.Message {
.error("filename \"\(basename)\" used twice: '\(firstPath)' and '\(secondPath)'")
}

static var note_explain_two_files_same_name: Diagnostic.Message {
.note("filenames are used to distinguish private declarations with the same name")
}
}

// Multithreading
Expand Down Expand Up @@ -2288,8 +2325,7 @@ extension Driver {
compilerOutputType: FileType?,
compilerMode: CompilerMode,
outputFileMap: OutputFileMap?,
moduleName: String,
patternOutputFile: VirtualPath? = nil
moduleName: String
) throws -> VirtualPath? {
// If there is an explicit argument for the output path, use that
if let outputPathArg = parsedOptions.getLastArgument(outputPath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ public class IncrementalCompilationState {
options: Options,
jobsInPhases: JobsInPhases
) throws {
guard driver.shouldAttemptIncrementalCompilation()
else {
return nil
}
guard driver.shouldAttemptIncrementalCompilation else { return nil }

if options.contains(.showIncremental) {
self.reporter = Reporter(diagnosticEngine: driver.diagnosticEngine,
Expand Down Expand Up @@ -359,9 +356,13 @@ extension IncrementalCompilationState {
}
}

fileprivate extension Driver {
extension Driver {
/// Check various arguments to rule out incremental compilation if need be.
mutating func shouldAttemptIncrementalCompilation() -> Bool {
static func shouldAttemptIncrementalCompilation(
_ parsedOptions: inout ParsedOptions,
diagnosticEngine: DiagnosticsEngine,
compilerMode: CompilerMode
) -> Bool {
guard parsedOptions.hasArgument(.incremental) else {
return false
}
Expand Down
14 changes: 5 additions & 9 deletions Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -310,15 +310,11 @@ extension Driver {
input: input,
flag: "-emit-dependencies-path")

if let input = input, let outputFileMap = outputFileMap {
let referenceDependenciesPath =
outputFileMap.existingOutput(inputFile: input.file, outputType: .swiftDeps)
addOutputOfType(
outputType: .swiftDeps,
finalOutputPath: referenceDependenciesPath,
input: input,
flag: "-emit-reference-dependencies-path")
}
addOutputOfType(
outputType: .swiftDeps,
finalOutputPath: referenceDependenciesPath,
input: input,
flag: "-emit-reference-dependencies-path")

addOutputOfType(
outputType: .yamlOptimizationRecord,
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftDriver/Jobs/Planning.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ struct CompileJobGroup {
}
}

/// // MARK: Standard build planning
// MARK: Standard build planning
extension Driver {
/// Plan a standard compilation, which produces jobs for compiling separate
/// primary files.
Expand Down
21 changes: 21 additions & 0 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,27 @@ final class SwiftDriverTests: XCTestCase {
XCTAssertFalse(plannedJobs[2].commandLine.contains(.flag("-emit-dependencies-path")))
XCTAssertFalse(plannedJobs[2].commandLine.contains(.flag("-serialize-diagnostics-path")))
}

func testReferenceDependencies() throws {
var driver = try Driver(args: ["swiftc", "foo.swift", "-incremental"])
let plannedJobs = try driver.planBuild()
XCTAssertTrue(plannedJobs[0].kind == .compile)
XCTAssertTrue(plannedJobs[0].commandLine.contains(.flag("-emit-reference-dependencies-path")))
}

func testDuplicateName() throws {
assertDiagnostics { diagnosticsEngine, verify in
_ = try? Driver(args: ["swiftc", "-c", "foo.swift", "foo.swift"], diagnosticsEngine: diagnosticsEngine)
verify.expect(.error("filename \"foo.swift\" used twice: 'foo.swift' and 'foo.swift'"))
verify.expect(.note("filenames are used to distinguish private declarations with the same name"))
}

assertDiagnostics { diagnosticsEngine, verify in
_ = try? Driver(args: ["swiftc", "-c", "foo.swift", "foo/foo.swift"], diagnosticsEngine: diagnosticsEngine)
verify.expect(.error("filename \"foo.swift\" used twice: 'foo.swift' and 'foo/foo.swift'"))
verify.expect(.note("filenames are used to distinguish private declarations with the same name"))
}
}

func testOutputFileMapStoring() throws {
// Create sample OutputFileMap:
Expand Down