Skip to content

Commit eef2dc6

Browse files
committed
Remove variant name from explicit precompile rule info to allow deduping
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 8012c0b commit eef2dc6

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)