Skip to content

Commit 123ceb0

Browse files
authored
Remove variant name from explicit precompile rule info to allow deduping (#291)
Not all variants depend on incompatible modules. Remove the variant name from the rule info so that identical tasks are deduplicated properly and cannot race.
1 parent 6976671 commit 123ceb0

File tree

4 files changed

+106
-15
lines changed

4 files changed

+106
-15
lines changed

Sources/SWBTaskExecution/DynamicTaskSpecs/SwiftDriverJobDynamicTaskSpec.swift

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,13 @@ public struct SwiftDriverJobTaskKey: Serializable, CustomDebugStringConvertible
6666
}
6767

6868
public struct SwiftDriverExplicitDependencyJobTaskKey: Serializable, CustomDebugStringConvertible {
69-
let variant: String
7069
let arch: String
7170
let driverJobKey: LibSwiftDriver.JobKey
7271
let driverJobSignature: ByteString
7372
let compilerLocation: LibSwiftDriver.CompilerLocation
7473
let casOptions: CASOptions?
7574

76-
init(variant: String, arch: String, driverJobKey: LibSwiftDriver.JobKey, driverJobSignature: ByteString, compilerLocation: LibSwiftDriver.CompilerLocation, casOptions: CASOptions?) {
77-
self.variant = variant
75+
init(arch: String, driverJobKey: LibSwiftDriver.JobKey, driverJobSignature: ByteString, compilerLocation: LibSwiftDriver.CompilerLocation, casOptions: CASOptions?) {
7876
self.arch = arch
7977
self.driverJobKey = driverJobKey
8078
self.driverJobSignature = driverJobSignature
@@ -83,8 +81,7 @@ public struct SwiftDriverExplicitDependencyJobTaskKey: Serializable, CustomDebug
8381
}
8482

8583
public func serialize<T>(to serializer: T) where T : Serializer {
86-
serializer.serializeAggregate(6) {
87-
serializer.serialize(variant)
84+
serializer.serializeAggregate(5) {
8885
serializer.serialize(arch)
8986
serializer.serialize(driverJobKey)
9087
serializer.serialize(driverJobSignature)
@@ -94,8 +91,7 @@ public struct SwiftDriverExplicitDependencyJobTaskKey: Serializable, CustomDebug
9491
}
9592

9693
public init(from deserializer: any Deserializer) throws {
97-
try deserializer.beginAggregate(6)
98-
variant = try deserializer.deserialize()
94+
try deserializer.beginAggregate(5)
9995
arch = try deserializer.deserialize()
10096
driverJobKey = try deserializer.deserialize()
10197
driverJobSignature = try deserializer.deserialize()
@@ -104,7 +100,7 @@ public struct SwiftDriverExplicitDependencyJobTaskKey: Serializable, CustomDebug
104100
}
105101

106102
public var debugDescription: String {
107-
"<SwiftDriverExplicitDependencyJob arch=\(arch) variant=\(variant) jobKey=\(driverJobKey) jobSignature=\(driverJobSignature) compilerLocation=\(compilerLocation) casOptions=\(String(describing: casOptions))>"
103+
"<SwiftDriverExplicitDependencyJob arch=\(arch) jobKey=\(driverJobKey) jobSignature=\(driverJobSignature) compilerLocation=\(compilerLocation) casOptions=\(String(describing: casOptions))>"
108104
}
109105
}
110106

@@ -173,7 +169,7 @@ final class SwiftDriverJobDynamicTaskSpec: DynamicTaskSpec {
173169
commandLine = commandLinePrefix + job.commandLine
174170
expectedOutputs = job.outputs
175171
assert(expectedOutputs.count > 0, "Explicit modules job was expected to have at least one primary output")
176-
ruleInfo = ["SwiftExplicitDependency\(job.ruleInfoType)", key.variant, key.arch, expectedOutputs.first?.str ?? "<unknown>"]
172+
ruleInfo = ["SwiftExplicitDependency\(job.ruleInfoType)", key.arch, expectedOutputs.first?.str ?? "<unknown>"]
177173
forTarget = nil
178174
descriptionForLifecycle = job.descriptionForLifecycle
179175
// WMO doesn't apply to explicit module builds
@@ -266,7 +262,7 @@ final class SwiftDriverJobDynamicTaskSpec: DynamicTaskSpec {
266262
guard let job = context.swiftModuleDependencyGraph.plannedExplicitDependencyBuildJob(for: key.driverJobKey) else {
267263
throw StubError.error("Failed to lookup explicit module Swift driver job \(key.driverJobKey)")
268264
}
269-
return SwiftDriverJobTaskAction(job, variant: key.variant, arch: key.arch, identifier: .explicitDependency, isUsingWholeModuleOptimization: false)
265+
return SwiftDriverJobTaskAction(job, variant: nil, arch: key.arch, identifier: .explicitDependency, isUsingWholeModuleOptimization: false)
270266
default:
271267
fatalError("Unexpected dynamic task key: \(dynamicTaskKey)")
272268
}

Sources/SWBTaskExecution/TaskActions/SwiftDriverJobSchedulingTaskAction.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,6 @@ open class SwiftDriverJobSchedulingTaskAction: TaskAction {
270270
let key: DynamicTaskKey
271271
if plannedJob.driverJob.categorizer.isExplicitDependencyBuild {
272272
key = .swiftDriverExplicitDependencyJob(SwiftDriverExplicitDependencyJobTaskKey(
273-
variant: driverPayload.variant,
274273
arch: driverPayload.architecture,
275274
driverJobKey: plannedJob.key,
276275
driverJobSignature: plannedJob.driverJob.signature,

Sources/SWBTaskExecution/TaskActions/SwiftDriverJobTaskAction.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,12 @@ public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTas
112112
}
113113

114114
let identifier: SwiftDriverJobIdentifier
115-
let variant: String
115+
let variant: String?
116116
let arch: String
117117
let driverJob: LibSwiftDriver.PlannedBuild.PlannedSwiftDriverJob
118118
let isUsingWholeModuleOptimization: Bool
119119

120-
init(_ driverJob: LibSwiftDriver.PlannedBuild.PlannedSwiftDriverJob, variant: String, arch: String, identifier: SwiftDriverJobIdentifier, isUsingWholeModuleOptimization: Bool) {
120+
init(_ driverJob: LibSwiftDriver.PlannedBuild.PlannedSwiftDriverJob, variant: String?, arch: String, identifier: SwiftDriverJobIdentifier, isUsingWholeModuleOptimization: Bool) {
121121
self.driverJob = driverJob
122122
self.variant = variant
123123
self.arch = arch
@@ -211,7 +211,7 @@ public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTas
211211
}
212212
}
213213

214-
internal func constructDriverJobTaskKey(variant: String,
214+
internal func constructDriverJobTaskKey(variant: String?,
215215
arch: String,
216216
plannedJob: LibSwiftDriver.PlannedBuild.PlannedSwiftDriverJob,
217217
identifier: String?,
@@ -220,13 +220,15 @@ public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTas
220220
let key: DynamicTaskKey
221221
if plannedJob.driverJob.categorizer.isExplicitDependencyBuild {
222222
key = .swiftDriverExplicitDependencyJob(SwiftDriverExplicitDependencyJobTaskKey(
223-
variant: variant,
224223
arch: arch,
225224
driverJobKey: plannedJob.key,
226225
driverJobSignature: plannedJob.driverJob.signature,
227226
compilerLocation: compilerLocation,
228227
casOptions: casOptions))
229228
} else {
229+
guard let variant else {
230+
fatalError("Expected variant for non-explicit-module job: \(plannedJob.driverJob.descriptionForLifecycle)")
231+
}
230232
guard let jobID = identifier else {
231233
fatalError("Expected job identifier for target compile: \(plannedJob.driverJob.descriptionForLifecycle)")
232234
}

Tests/SWBBuildSystemTests/SwiftDriverTests.swift

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4448,6 +4448,100 @@ fileprivate struct SwiftDriverTests: CoreBasedTests {
44484448
}
44494449
}
44504450

4451+
@Test(.requireSDKs(.macOS))
4452+
func explicitPCMDeduplicationWithBuildVariant() async throws {
4453+
try await withTemporaryDirectory { tmpDirPath async throws -> Void in
4454+
let testWorkspace = try await TestWorkspace(
4455+
"Test",
4456+
sourceRoot: tmpDirPath.join("Test"),
4457+
projects: [
4458+
TestProject(
4459+
"aProject",
4460+
groupTree: TestGroup(
4461+
"Sources",
4462+
path: "Sources",
4463+
children: [
4464+
TestFile("fileC.c"),
4465+
TestFile("Target0.h"),
4466+
TestFile("file1.swift"),
4467+
]),
4468+
buildConfigurations: [
4469+
TestBuildConfiguration(
4470+
"Debug",
4471+
buildSettings: [
4472+
"PRODUCT_NAME": "$(TARGET_NAME)",
4473+
"SWIFT_VERSION": swiftVersion,
4474+
"BUILD_VARIANTS": "normal other",
4475+
"SWIFT_ENABLE_EXPLICIT_MODULES": "YES",
4476+
"DEFINES_MODULE": "YES",
4477+
"CLANG_ENABLE_MODULES": "YES"
4478+
])
4479+
],
4480+
targets: [
4481+
TestStandardTarget(
4482+
"Target0",
4483+
type: .framework,
4484+
buildPhases: [
4485+
TestSourcesBuildPhase([
4486+
"fileC.c",
4487+
]),
4488+
TestHeadersBuildPhase([
4489+
TestBuildFile("Target0.h", headerVisibility: .public)
4490+
])
4491+
]),
4492+
TestStandardTarget(
4493+
"TargetA",
4494+
type: .framework,
4495+
buildPhases: [
4496+
TestSourcesBuildPhase([
4497+
"file1.swift",
4498+
]),
4499+
], dependencies: [
4500+
"Target0"
4501+
]),
4502+
])
4503+
])
4504+
4505+
let tester = try await BuildOperationTester(getCore(), testWorkspace, simulated: false)
4506+
let parameters = BuildParameters(configuration: "Debug")
4507+
let buildRequest = BuildRequest(parameters: parameters, buildTargets: tester.workspace.projects[0].targets.map({ BuildRequest.BuildTargetInfo(parameters: parameters, target: $0) }), continueBuildingAfterErrors: false, useParallelTargets: true, useImplicitDependencies: false, useDryRun: false)
4508+
let SRCROOT = testWorkspace.sourceRoot.join("aProject")
4509+
4510+
// Create the source files.
4511+
try await tester.fs.writeFileContents(SRCROOT.join("Sources/fileC.c")) { file in
4512+
file <<<
4513+
"""
4514+
int foo() { return 11; }
4515+
"""
4516+
}
4517+
try await tester.fs.writeFileContents(SRCROOT.join("Sources/Target0.h")) { file in
4518+
file <<<
4519+
"""
4520+
int foo();
4521+
"""
4522+
}
4523+
try await tester.fs.writeFileContents(SRCROOT.join("Sources/file1.swift")) { file in
4524+
file <<<
4525+
"""
4526+
import Target0
4527+
public struct A {
4528+
public init() { foo() }
4529+
}
4530+
"""
4531+
}
4532+
4533+
try await tester.checkBuild(runDestination: .macOS, buildRequest: buildRequest, persistent: true) { results in
4534+
results.checkNoDiagnostics()
4535+
4536+
// Identical build variants should be able to share PCMs
4537+
results.checkTasks(.matchRulePattern(["SwiftExplicitDependencyGeneratePcm", .anySequence, .contains("Target0")])) { tasks in
4538+
#expect(tasks.count == 1)
4539+
}
4540+
}
4541+
}
4542+
}
4543+
4544+
44514545
@Test(.requireSDKs(.macOS))
44524546
func diagnosingLanguageFeatureEnablement() async throws {
44534547

0 commit comments

Comments
 (0)