Skip to content

Commit f9217dc

Browse files
authored
Merge pull request #882 from owenv/owenv/delete-provisional-tasks
Replace provisional tasks with task validity criteria
2 parents 469349f + cce8897 commit f9217dc

17 files changed

+270
-623
lines changed

Sources/SWBCore/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ add_library(SWBCore
9191
ProjectModel/Target.swift
9292
ProjectModel/Workspace.swift
9393
ProjectModel/WorkspaceHeaderIndex.swift
94-
ProvisionalTask.swift
9594
Provisioning.swift
9695
ProvisioningTaskInputs.swift
9796
SDKRegistry.swift
@@ -172,6 +171,7 @@ add_library(SWBCore
172171
TargetPlatformDiagnostics.swift
173172
TaskGeneration.swift
174173
TaskResult.swift
174+
TaskValidityCriteria.swift
175175
ToolchainRegistry.swift
176176
ToolInfo/ClangToolInfo.swift
177177
Tuning.swift

Sources/SWBCore/PlannedTask.swift

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public protocol PlannedTaskInputsOutputs {
5959
/// A task is a concrete unit of work to be performed by the build system as a result of task construction. For example the compilation of an individual file or the copying of a single resource. In many cases, each task will directly correspond to an external command line to be executed. Every task also has inputs and outputs which will be honored by the build system.
6060
///
6161
/// A *planned* task contains information used only during task construction or which is added to the `BuildDescription` and not otherwise used during execution; information used during execution is stored in a corresponding *executable* task. A planned task also contains a strong reference to its executable task (since during task construction the planned task is the only object which is keeping the executable task alive).
62-
public protocol PlannedTask: AnyObject, CustomStringConvertible, Sendable, PlannedTaskInputsOutputs {
62+
public protocol PlannedTask: AnyObject, CustomStringConvertible, Sendable, PlannedTaskInputsOutputs, Sendable {
6363
/// The type description of the task.
6464
var type: any TaskTypeDescription { get }
6565

@@ -87,10 +87,8 @@ public protocol PlannedTask: AnyObject, CustomStringConvertible, Sendable, Plann
8787
/// The executable task for this planned task.
8888
var execTask: any ExecutableTask { get }
8989

90-
/// The provisional task corresponding to this task, if any.
91-
///
92-
/// This is mainly important for resolution of provisional tasks for directory creation: We don't want to consider a provisional task for directory creation valid just because other provisional tasks (and *only* provisional tasks) are placing content there; we want to be able to easily determine that non-provisional tasks are placing content there.
93-
var provisionalTask: ProvisionalTask? { get set }
90+
/// Criteria for determining if this task should be included in the build plan.
91+
var validityCriteria: (any TaskValidityCriteria)? { get }
9492

9593
/// Allows a task to always be executed.
9694
var alwaysExecuteTask: Bool { get }
@@ -133,7 +131,7 @@ extension PlannedTask {
133131
}
134132

135133
/// A constructed task is a concrete instance of `PlannedTask` which captures information about a task which is used during task construction and creation of the `BuildDescription`. It has a reference to the executable task which will be used during task execution.
136-
public final class ConstructedTask: PlannedTask {
134+
public final class ConstructedTask: PlannedTask, Sendable {
137135
/// The task identifier.
138136
public let identifier: TaskIdentifier
139137

@@ -159,14 +157,8 @@ public final class ConstructedTask: PlannedTask {
159157

160158
public let repairViaOwnershipAnalysis: Bool
161159

162-
/// The provisional task corresponding to this task, if any.
163-
///
164-
/// This is mainly important for resolution of provisional tasks for directory creation: We don't want to consider a provisional task for directory creation valid just because other provisional tasks (and *only* provisional tasks) are placing content there; we want to be able to easily determine that non-provisional tasks are placing content there.
165-
public weak var provisionalTask: ProvisionalTask? = nil {
166-
willSet(newProvisionalTask) {
167-
precondition(provisionalTask == nil, "A provisional task has already been assigned to planned task \(self)")
168-
}
169-
}
160+
/// Criteria for determining if this task should be included in the build plan.
161+
public let validityCriteria: (any TaskValidityCriteria)?
170162

171163
/// Construct a new task from a task builder.
172164
///
@@ -181,6 +173,7 @@ public final class ConstructedTask: PlannedTask {
181173
self.alwaysExecuteTask = builder.alwaysExecuteTask
182174
self.priority = builder.priority
183175
self.repairViaOwnershipAnalysis = builder.repairViaOwnershipAnalysis
176+
self.validityCriteria = builder.validityCriteria
184177
}
185178

186179
private enum CodingKeys: String, CodingKey {
@@ -206,7 +199,7 @@ public final class ConstructedTask: PlannedTask {
206199
}
207200

208201

209-
public final class GateTask: PlannedTask {
202+
public final class GateTask: PlannedTask, Sendable {
210203
/// A static task type description for gate tasks.
211204
private final class GateTaskTypeDescription: TaskTypeDescription {
212205
let payloadType: (any TaskPayload.Type)? = nil
@@ -258,11 +251,14 @@ public final class GateTask: PlannedTask {
258251
public let execTask: any ExecutableTask
259252

260253
/// Gate tasks do not support always execute mode.
261-
public let alwaysExecuteTask = false
254+
public var alwaysExecuteTask: Bool { false }
262255

263256
public var priority: TaskPriority { .gate }
264257

265-
public let repairViaOwnershipAnalysis: Bool = false
258+
public var repairViaOwnershipAnalysis: Bool { false }
259+
260+
/// Gate tasks never have validity criteria.
261+
public var validityCriteria: (any TaskValidityCriteria)? { nil }
266262

267263
private enum CodingKeys: String, CodingKey {
268264
case type
@@ -277,16 +273,6 @@ public final class GateTask: PlannedTask {
277273
case repairViaOwnershipAnalysis
278274
}
279275

280-
/// The provisional task corresponding to this task, if any.
281-
///
282-
/// This is mainly important for resolution of provisional tasks for directory creation: We don't want to consider a provisional task for directory creation valid just because other provisional tasks (and *only* provisional tasks) are placing content there; we want to be able to easily determine that non-provisional tasks are placing content there.
283-
/// The provisional task corresponding to this task, if any.
284-
public weak var provisionalTask: ProvisionalTask? = nil {
285-
willSet(newProvisionalTask) {
286-
preconditionFailure("Tried to assign a provisional task to gate task \(self)")
287-
}
288-
}
289-
290276
/// Construct a new task from a task builder.
291277
///
292278
/// NOTE: This initializer does not mutate the builder, but we take it as inout nevertheless to avoid unnecessary copying.

Sources/SWBCore/ProvisionalTask.swift

Lines changed: 0 additions & 249 deletions
This file was deleted.

Sources/SWBCore/SpecImplementations/ProductTypes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ public struct SymlinkDescriptor: Hashable
868868
public let location: Path
869869
/// The path the symbolic link points to. This may be a relative path.
870870
public let toPath: Path
871-
/// The effective path the symbolic link points to, if we know that `toPath` is itself going to go through symbolic links. This may be a relative path. This is important for validation of symlink provisional tasks.
871+
/// The effective path the symbolic link points to, if we know that `toPath` is itself going to go through symbolic links. This may be a relative path. This is important for validation of symlink tasks.
872872
public let effectiveToPath: Path?
873873

874874
public func hash(into hasher: inout Hasher) {

0 commit comments

Comments
 (0)