diff --git a/Sources/SwiftDriver/Jobs/EmitModuleJob.swift b/Sources/SwiftDriver/Jobs/EmitModuleJob.swift index 6de179a08..91e649a94 100644 --- a/Sources/SwiftDriver/Jobs/EmitModuleJob.swift +++ b/Sources/SwiftDriver/Jobs/EmitModuleJob.swift @@ -46,21 +46,6 @@ extension Driver { return } - // Add outputs that can't be merged - // Workaround for rdar://85253406 - // Ensure that the separate emit-module job does not emit `.d.` outputs. - // If we have both individual source files and the emit-module file emit .d files, we - // are risking collisions in output filenames. - // - // In cases where other compile jobs exist, they will produce dependency outputs already. - // There are currently no cases where this is the only job because even an `-emit-module` - // driver invocation currently still involves partial compilation jobs. - // When partial compilation jobs are removed for the `compilerOutputType == .swiftModule` - // case, this will need to be changed here. - // - if emitModuleSeparately { - return - } if let dependenciesFilePath = dependenciesFilePath { var path = dependenciesFilePath // FIXME: Hack to workaround the fact that SwiftPM/Xcode don't pass this path right now. diff --git a/Sources/SwiftDriver/Jobs/Planning.swift b/Sources/SwiftDriver/Jobs/Planning.swift index 6f25f2c41..297202d3f 100644 --- a/Sources/SwiftDriver/Jobs/Planning.swift +++ b/Sources/SwiftDriver/Jobs/Planning.swift @@ -434,7 +434,8 @@ extension Driver { assert(input.type.isPartOfSwiftCompilation) // We can skip the compile jobs if all we want is a module when it's - // built separately. + // built separately, unless we need per-file outputs like const values + // that only compile jobs can produce. let canSkipIfOnlyModule = compilerOutputType == .swiftModule && emitModuleSeparately try createAndAddCompileJob(primaryInput: input, emitModuleTrace: emitModuleTrace, @@ -478,7 +479,7 @@ extension Driver { ) throws { // We can skip the compile jobs if all we want is a module when it's // built separately. - if parsedOptions.hasArgument(.driverExplicitModuleBuild), canSkipIfOnlyModule { return } + if canSkipIfOnlyModule { return } // If we are in the batch mode, the constructed jobs here will be batched // later. There is no need to produce cache key for the job. let compile = try compileJob(primaryInputs: [primaryInput], diff --git a/Tests/SwiftDriverTests/IncrementalCompilationTests.swift b/Tests/SwiftDriverTests/IncrementalCompilationTests.swift index 0a4611a94..ea244e753 100644 --- a/Tests/SwiftDriverTests/IncrementalCompilationTests.swift +++ b/Tests/SwiftDriverTests/IncrementalCompilationTests.swift @@ -222,8 +222,9 @@ extension IncrementalCompilationTests { XCTAssertEqual(outputs.first!.file.absolutePath, expected) } - // Null planning should not return an empty compile job for compatibility reason. - // `swift-build` wraps the jobs returned by swift-driver in `Executor` so returning an empty list of compile job will break build system. + // When compilerOutputType == .swiftModule and emitModuleSeparately is true, + // per-file compile jobs are skipped since the emit-module job handles + // everything. Verify that the null build still returns the emit-module job. func testNullPlanningCompatibility() throws { guard let sdkArgumentsForTesting = try Driver.sdkArgumentsForTesting() else { throw XCTSkip("Cannot perform this test on this host") @@ -232,16 +233,15 @@ extension IncrementalCompilationTests { var driver = try Driver(args: commonArgs + extraArguments + sdkArgumentsForTesting) let initialJobs = try driver.planBuild() XCTAssertTrue(initialJobs.contains { $0.kind == .emitModule}) + // Module-only builds should not have compile jobs since emitModuleSeparately + // handles the module output. + XCTAssertTrue(initialJobs.filter { $0.kind == .compile }.isEmpty) try driver.run(jobs: initialJobs) - // Plan the build again without touching any file. This should be a null build but for compatibility reason, - // planBuild() should return all the jobs and supported build system will query incremental state for the actual - // jobs need to be executed. + // Plan the build again without touching any file. This should be a null build. let replanJobs = try driver.planBuild() - XCTAssertFalse( - replanJobs.filter { $0.kind == .compile }.isEmpty, - "more than one compile job needs to be planned") XCTAssertTrue(replanJobs.contains { $0.kind == .emitModule}) + XCTAssertTrue(replanJobs.filter { $0.kind == .compile }.isEmpty) } } diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index bb087af4a..8133da68e 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -2026,7 +2026,7 @@ final class SwiftDriverTests: XCTestCase { "-output-file-map", outputFileMap.description]) let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs() - XCTAssertEqual(plannedJobs.count, 3) + XCTAssertEqual(plannedJobs.count, 1) XCTAssertEqual(plannedJobs[0].kind, .emitModule) try XCTAssertJobInvocationMatches(plannedJobs[0], .flag("-serialize-diagnostics-path"), .path(.absolute(.init(validating: "/build/Foo-test.dia")))) } @@ -2051,7 +2051,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(driver.diagnosticEngine.diagnostics.isEmpty) // Test the output path is correct for GeneratePCH job. - XCTAssertEqual(plannedJobs.count, 4) + XCTAssertEqual(plannedJobs.count, 2) XCTAssertEqual(plannedJobs[0].kind, .generatePCH) try XCTAssertJobInvocationMatches(plannedJobs[0], .flag("-o"), .path(.absolute(.init(validating: "/build/Foo-bridging-header.pch")))) @@ -3911,7 +3911,7 @@ final class SwiftDriverTests: XCTestCase { var driver = try Driver(args: ["swiftc", "-module-name=ThisModule", "main.swift", "multi-threaded.swift", "-emit-module", "-o", "test.swiftmodule", "-experimental-emit-module-separately"]) let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs() - XCTAssertEqual(plannedJobs.count, 3) + XCTAssertEqual(plannedJobs.count, 1) XCTAssertEqual(plannedJobs[0].kind, .emitModule) XCTAssertJobInvocationMatches(plannedJobs[0], .flag("-emit-abi-descriptor-path")) @@ -4636,8 +4636,8 @@ final class SwiftDriverTests: XCTestCase { // -experimental-emit-module-separately. var driver = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "-module-name", "Test", "-emit-module-path", rebase("Test.swiftmodule", at: root), "-experimental-emit-module-separately"]) let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs() - XCTAssertEqual(plannedJobs.count, 3) - XCTAssertEqual(Set(plannedJobs.map { $0.kind }), Set([.emitModule, .compile])) + XCTAssertEqual(plannedJobs.count, 1) + XCTAssertEqual(plannedJobs[0].kind, .emitModule) XCTAssertTrue(plannedJobs[0].tool.name.contains("swift")) XCTAssertEqual(plannedJobs[0].outputs.count, driver.targetTriple.isDarwin ? 4 : 3) XCTAssertEqual(plannedJobs[0].outputs[0].file, .absolute(try .init(validating: rebase("Test.swiftmodule", at: root))))