Skip to content

Commit 952eece

Browse files
committed
Merge dumped dependency info
Since #874, we are dumping per-target dependency information, this adds a new task which merges these for a given build request. The task is only created if there's at least one target in the graph that will dump dependency information, so should be a no-op for all builds right now. Additionally, this declares the dependency info file as an output of `ValidateDependencies` which I neglected to do in my earlier PR.
1 parent de01002 commit 952eece

18 files changed

+213
-10
lines changed

Sources/SWBCore/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ add_library(SWBCore
118118
SpecImplementations/SpecRegistry.swift
119119
SpecImplementations/Specs.swift
120120
SpecImplementations/Tools/AppShortcutStringsMetadataCompiler.swift
121+
SpecImplementations/Tools/BuildDependencyInfoSpec.swift
121122
SpecImplementations/Tools/CCompiler.swift
122123
SpecImplementations/Tools/ClangModuleVerifierInputGenerator.swift
123124
SpecImplementations/Tools/ClangStatCache.swift

Sources/SWBCore/PlannedTaskAction.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ extension FileCopyTaskActionContext {
315315
public protocol TaskActionCreationDelegate
316316
{
317317
func createAuxiliaryFileTaskAction(_ context: AuxiliaryFileTaskActionContext) -> any PlannedTaskAction
318+
func createBuildDependencyInfoTaskAction() -> any PlannedTaskAction
318319
func createBuildDirectoryTaskAction() -> any PlannedTaskAction
319320
func createCodeSignTaskAction() -> any PlannedTaskAction
320321
func createConcatenateTaskAction() -> any PlannedTaskAction

Sources/SWBCore/SpecImplementations/RegisterSpecs.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public struct BuiltinSpecsExtension: SpecificationsExtension {
119119
// spec implementations (custom classes we provide which have no backing spec file at all).
120120
public func specificationImplementations() -> [any SpecImplementationType.Type] {
121121
[
122+
BuildDependencyInfoSpec.self,
122123
ConcatenateToolSpec.self,
123124
CreateAssetPackManifestToolSpec.self,
124125
CreateBuildDirectorySpec.self,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
private import Foundation
14+
public import SWBUtil
15+
import SWBMacro
16+
17+
public final class BuildDependencyInfoSpec: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable {
18+
public static let identifier = "com.apple.tools.build-dependency-info"
19+
20+
public static func construct(registry: SpecRegistry, proxy: SpecProxy) -> Spec {
21+
return Self.init(registry: registry)
22+
}
23+
24+
public init(registry: SpecRegistry) {
25+
let proxy = SpecProxy(identifier: Self.identifier, domain: "", path: Path(""), type: Self.self, classType: nil, basedOn: nil, data: ["ExecDescription": PropertyListItem("Merging build dependency info")], localizedStrings: nil)
26+
super.init(createSpecParser(for: proxy, registry: registry), nil, isGeneric: false)
27+
}
28+
29+
required init(_ parser: SpecParser, _ basedOnSpec: Spec?) {
30+
super.init(parser, basedOnSpec, isGeneric: false)
31+
}
32+
33+
override public func constructTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate) async {
34+
fatalError("unexpected direct invocation")
35+
}
36+
37+
public func createTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, dumpDependencyPaths: [Path]) async {
38+
delegate.createTask(type: self, ruleInfo: ["BuildDependencyInfo"], commandLine: ["builtin-build-dependency-info"] + dumpDependencyPaths.map { $0.str }, environment: EnvironmentBindings(), workingDirectory: cbc.producer.defaultWorkingDirectory, inputs: dumpDependencyPaths, outputs: [cbc.output], action: delegate.taskActionCreationDelegate.createBuildDependencyInfoTaskAction(), preparesForIndexing: false, enableSandboxing: false)
39+
}
40+
}

Sources/SWBCore/SpecImplementations/Tools/ValidateDependencies.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,13 @@ public final class ValidateDependenciesSpec: CommandLineToolSpec, SpecImplementa
4949
return
5050
}
5151
let signature = String(decoding: jsonData, as: UTF8.self)
52-
let output = delegate.createVirtualNode("ValidateDependencies \(configuredTarget.guid)")
53-
delegate.createTask(type: self, payload: payload, ruleInfo: ["ValidateDependencies"], additionalSignatureData: signature, commandLine: ["builtin-validate-dependencies"] + dependencyInfos.map { $0.path.str }, environment: EnvironmentBindings(), workingDirectory: cbc.producer.defaultWorkingDirectory, inputs: dependencyInfos + cbc.commandOrderingInputs, outputs: [output], action: delegate.taskActionCreationDelegate.createValidateDependenciesTaskAction(), preparesForIndexing: false, enableSandboxing: false)
52+
53+
var outputs: [any PlannedNode] = [delegate.createVirtualNode("ValidateDependencies \(configuredTarget.guid)")]
54+
if cbc.scope.evaluate(BuiltinMacros.DUMP_DEPENDENCIES) {
55+
outputs.append(MakePlannedPathNode(cbc.scope.evaluate(BuiltinMacros.DUMP_DEPENDENCIES_OUTPUT_PATH)))
56+
}
57+
58+
delegate.createTask(type: self, payload: payload, ruleInfo: ["ValidateDependencies"], additionalSignatureData: signature, commandLine: ["builtin-validate-dependencies"] + dependencyInfos.map { $0.path.str }, environment: EnvironmentBindings(), workingDirectory: cbc.producer.defaultWorkingDirectory, inputs: dependencyInfos + cbc.commandOrderingInputs, outputs: outputs, action: delegate.taskActionCreationDelegate.createValidateDependenciesTaskAction(), preparesForIndexing: false, enableSandboxing: false)
5459
}
5560
}
5661

Sources/SWBTaskConstruction/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ add_library(SWBTaskConstruction
5151
TaskProducers/StandardTaskProducer.swift
5252
TaskProducers/TaskProducer.swift
5353
TaskProducers/TaskProducerExtensionPoint.swift
54+
TaskProducers/WorkspaceTaskProducers/BuildDependencyInfoTaskProducer.swift
5455
TaskProducers/WorkspaceTaskProducers/CreateBuildDirectoryTaskProducer.swift
5556
TaskProducers/WorkspaceTaskProducers/HeadermapVFSTaskProducer.swift
5657
TaskProducers/WorkspaceTaskProducers/IndexBuildVFSDirectoryRemapTaskProducer.swift

Sources/SWBTaskConstruction/ProductPlanning/ProductPlanner.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ private struct WorkspaceProductPlanBuilder {
8181
SDKStatCacheTaskProducer(context: globalTaskProducerContext, targetContexts: targetContexts),
8282
HeadermapVFSTaskProducer(context: globalTaskProducerContext, targetContexts: targetContexts),
8383
PCHModuleMapTaskProducer(context: globalTaskProducerContext, targetContexts: targetContexts),
84+
BuildDependencyInfoTaskProducer(context: globalTaskProducerContext, targetContexts: targetContexts),
8485
] + (globalProductPlan.planRequest.buildRequest.enableIndexBuildArena ? [IndexBuildVFSDirectoryRemapTaskProducer(context: globalTaskProducerContext)] : [])
8586

8687
for taskProducerExtension in await taskProducerExtensions(globalTaskProducerContext.workspaceContext) {

Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ public class TaskProducerContext: StaleFileRemovalContext, BuildFileResolution
220220

221221
public let appShortcutStringsMetadataCompilerSpec: AppShortcutStringsMetadataCompilerSpec
222222
let appleScriptCompilerSpec: CommandLineToolSpec
223+
let buildDependencyInfoSpec: BuildDependencyInfoSpec
223224
public let clangSpec: ClangCompilerSpec
224225
public let clangAssemblerSpec: ClangCompilerSpec
225226
public let clangPreprocessorSpec: ClangCompilerSpec
@@ -344,6 +345,7 @@ public class TaskProducerContext: StaleFileRemovalContext, BuildFileResolution
344345
let domain = settings.platform?.name ?? ""
345346
self.appShortcutStringsMetadataCompilerSpec = workspaceContext.core.specRegistry.getSpec("com.apple.compilers.appshortcutstringsmetadata", domain: domain) as! AppShortcutStringsMetadataCompilerSpec
346347
self.appleScriptCompilerSpec = workspaceContext.core.specRegistry.getSpec("com.apple.compilers.osacompile", domain: domain) as! CommandLineToolSpec
348+
self.buildDependencyInfoSpec = workspaceContext.core.specRegistry.getSpec(BuildDependencyInfoSpec.identifier, domain: domain) as! BuildDependencyInfoSpec
347349
self.clangSpec = try! workspaceContext.core.specRegistry.getSpec(domain: domain) as ClangCompilerSpec
348350
self.clangAssemblerSpec = try! workspaceContext.core.specRegistry.getSpec(domain: domain) as ClangAssemblerSpec
349351
self.clangPreprocessorSpec = try! workspaceContext.core.specRegistry.getSpec(domain: domain) as ClangPreprocessorSpec
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SWBCore
14+
import SWBUtil
15+
import SWBMacro
16+
import Foundation
17+
import SWBProtocol
18+
19+
final class BuildDependencyInfoTaskProducer: StandardTaskProducer, TaskProducer {
20+
private let targetContexts: [TaskProducerContext]
21+
22+
init(context globalContext: TaskProducerContext, targetContexts: [TaskProducerContext]) {
23+
self.targetContexts = targetContexts
24+
super.init(globalContext)
25+
}
26+
27+
func generateTasks() async -> [any PlannedTask] {
28+
let components = context.globalProductPlan.planRequest.buildRequest.parameters.action.buildComponents
29+
guard components.contains("build") else {
30+
return []
31+
}
32+
33+
let output = context.settings.globalScope.evaluate(BuiltinMacros.BUILD_DIR).join("BuildDependencyInfo.json")
34+
let dumpDependencyPaths: [Path] = targetContexts.compactMap {
35+
guard let target = $0.configuredTarget?.target as? SWBCore.StandardTarget else {
36+
return nil
37+
}
38+
guard target.sourcesBuildPhase?.buildFiles.isEmpty == false else {
39+
return nil
40+
}
41+
if $0.settings.globalScope.evaluate(BuiltinMacros.DUMP_DEPENDENCIES) {
42+
return $0.settings.globalScope.evaluate(BuiltinMacros.DUMP_DEPENDENCIES_OUTPUT_PATH)
43+
} else {
44+
return nil
45+
}
46+
}
47+
48+
if dumpDependencyPaths.isEmpty {
49+
return []
50+
}
51+
52+
var tasks = [any PlannedTask]()
53+
await appendGeneratedTasks(&tasks) { delegate in
54+
await context.buildDependencyInfoSpec.createTasks(
55+
CommandBuildContext(producer: context, scope: context.settings.globalScope, inputs: dumpDependencyPaths.map { FileToBuild(context: context, absolutePath: $0) }, output: output, commandOrderingInputs: []),
56+
delegate,
57+
dumpDependencyPaths: dumpDependencyPaths
58+
)
59+
}
60+
return tasks
61+
}
62+
}

Sources/SWBTaskExecution/BuildDescriptionManager.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,10 @@ extension BuildSystemTaskPlanningDelegate: TaskActionCreationDelegate {
802802
return AuxiliaryFileTaskAction(context)
803803
}
804804

805+
func createBuildDependencyInfoTaskAction() -> any PlannedTaskAction {
806+
return BuildDependencyInfoTaskAction()
807+
}
808+
805809
func createCodeSignTaskAction() -> any PlannedTaskAction {
806810
return CodeSignTaskAction()
807811
}

0 commit comments

Comments
 (0)