From 952eece487afb768eef3b271ed28bcad028c96e5 Mon Sep 17 00:00:00 2001 From: Boris Buegling Date: Thu, 6 Nov 2025 17:19:55 -0800 Subject: [PATCH] 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. --- Sources/SWBCore/CMakeLists.txt | 1 + Sources/SWBCore/PlannedTaskAction.swift | 1 + .../SpecImplementations/RegisterSpecs.swift | 1 + .../Tools/BuildDependencyInfoSpec.swift | 40 ++++++++++++ .../Tools/ValidateDependencies.swift | 9 ++- Sources/SWBTaskConstruction/CMakeLists.txt | 1 + .../ProductPlanning/ProductPlanner.swift | 1 + .../TaskProducers/TaskProducer.swift | 2 + .../BuildDependencyInfoTaskProducer.swift | 62 +++++++++++++++++++ .../BuildDescriptionManager.swift | 4 ++ .../BuiltinTaskActionsExtension.swift | 1 + Sources/SWBTaskExecution/CMakeLists.txt | 1 + .../BuildDependencyInfoTaskAction.swift | 59 ++++++++++++++++++ .../ValidateDependenciesTaskAction.swift | 2 +- .../CapturingTaskGenerationDelegate.swift | 4 ++ .../TaskPlanningTestSupport.swift | 4 ++ .../DependencyValidationTests.swift | 26 +++++--- .../CommandLineSpecPerfTests.swift | 4 ++ 18 files changed, 213 insertions(+), 10 deletions(-) create mode 100644 Sources/SWBCore/SpecImplementations/Tools/BuildDependencyInfoSpec.swift create mode 100644 Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/BuildDependencyInfoTaskProducer.swift create mode 100644 Sources/SWBTaskExecution/TaskActions/BuildDependencyInfoTaskAction.swift diff --git a/Sources/SWBCore/CMakeLists.txt b/Sources/SWBCore/CMakeLists.txt index b872cb5d..16b42812 100644 --- a/Sources/SWBCore/CMakeLists.txt +++ b/Sources/SWBCore/CMakeLists.txt @@ -118,6 +118,7 @@ add_library(SWBCore SpecImplementations/SpecRegistry.swift SpecImplementations/Specs.swift SpecImplementations/Tools/AppShortcutStringsMetadataCompiler.swift + SpecImplementations/Tools/BuildDependencyInfoSpec.swift SpecImplementations/Tools/CCompiler.swift SpecImplementations/Tools/ClangModuleVerifierInputGenerator.swift SpecImplementations/Tools/ClangStatCache.swift diff --git a/Sources/SWBCore/PlannedTaskAction.swift b/Sources/SWBCore/PlannedTaskAction.swift index ab6e2419..3632cfd2 100644 --- a/Sources/SWBCore/PlannedTaskAction.swift +++ b/Sources/SWBCore/PlannedTaskAction.swift @@ -315,6 +315,7 @@ extension FileCopyTaskActionContext { public protocol TaskActionCreationDelegate { func createAuxiliaryFileTaskAction(_ context: AuxiliaryFileTaskActionContext) -> any PlannedTaskAction + func createBuildDependencyInfoTaskAction() -> any PlannedTaskAction func createBuildDirectoryTaskAction() -> any PlannedTaskAction func createCodeSignTaskAction() -> any PlannedTaskAction func createConcatenateTaskAction() -> any PlannedTaskAction diff --git a/Sources/SWBCore/SpecImplementations/RegisterSpecs.swift b/Sources/SWBCore/SpecImplementations/RegisterSpecs.swift index 6d86dac4..b72dac09 100644 --- a/Sources/SWBCore/SpecImplementations/RegisterSpecs.swift +++ b/Sources/SWBCore/SpecImplementations/RegisterSpecs.swift @@ -119,6 +119,7 @@ public struct BuiltinSpecsExtension: SpecificationsExtension { // spec implementations (custom classes we provide which have no backing spec file at all). public func specificationImplementations() -> [any SpecImplementationType.Type] { [ + BuildDependencyInfoSpec.self, ConcatenateToolSpec.self, CreateAssetPackManifestToolSpec.self, CreateBuildDirectorySpec.self, diff --git a/Sources/SWBCore/SpecImplementations/Tools/BuildDependencyInfoSpec.swift b/Sources/SWBCore/SpecImplementations/Tools/BuildDependencyInfoSpec.swift new file mode 100644 index 00000000..c155fb8f --- /dev/null +++ b/Sources/SWBCore/SpecImplementations/Tools/BuildDependencyInfoSpec.swift @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +private import Foundation +public import SWBUtil +import SWBMacro + +public final class BuildDependencyInfoSpec: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { + public static let identifier = "com.apple.tools.build-dependency-info" + + public static func construct(registry: SpecRegistry, proxy: SpecProxy) -> Spec { + return Self.init(registry: registry) + } + + public init(registry: SpecRegistry) { + 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) + super.init(createSpecParser(for: proxy, registry: registry), nil, isGeneric: false) + } + + required init(_ parser: SpecParser, _ basedOnSpec: Spec?) { + super.init(parser, basedOnSpec, isGeneric: false) + } + + override public func constructTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate) async { + fatalError("unexpected direct invocation") + } + + public func createTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, dumpDependencyPaths: [Path]) async { + 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) + } +} diff --git a/Sources/SWBCore/SpecImplementations/Tools/ValidateDependencies.swift b/Sources/SWBCore/SpecImplementations/Tools/ValidateDependencies.swift index 5f9abb7e..ccf93888 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/ValidateDependencies.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/ValidateDependencies.swift @@ -49,8 +49,13 @@ public final class ValidateDependenciesSpec: CommandLineToolSpec, SpecImplementa return } let signature = String(decoding: jsonData, as: UTF8.self) - let output = delegate.createVirtualNode("ValidateDependencies \(configuredTarget.guid)") - 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) + + var outputs: [any PlannedNode] = [delegate.createVirtualNode("ValidateDependencies \(configuredTarget.guid)")] + if cbc.scope.evaluate(BuiltinMacros.DUMP_DEPENDENCIES) { + outputs.append(MakePlannedPathNode(cbc.scope.evaluate(BuiltinMacros.DUMP_DEPENDENCIES_OUTPUT_PATH))) + } + + 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) } } diff --git a/Sources/SWBTaskConstruction/CMakeLists.txt b/Sources/SWBTaskConstruction/CMakeLists.txt index b792f9dc..3a32f552 100644 --- a/Sources/SWBTaskConstruction/CMakeLists.txt +++ b/Sources/SWBTaskConstruction/CMakeLists.txt @@ -51,6 +51,7 @@ add_library(SWBTaskConstruction TaskProducers/StandardTaskProducer.swift TaskProducers/TaskProducer.swift TaskProducers/TaskProducerExtensionPoint.swift + TaskProducers/WorkspaceTaskProducers/BuildDependencyInfoTaskProducer.swift TaskProducers/WorkspaceTaskProducers/CreateBuildDirectoryTaskProducer.swift TaskProducers/WorkspaceTaskProducers/HeadermapVFSTaskProducer.swift TaskProducers/WorkspaceTaskProducers/IndexBuildVFSDirectoryRemapTaskProducer.swift diff --git a/Sources/SWBTaskConstruction/ProductPlanning/ProductPlanner.swift b/Sources/SWBTaskConstruction/ProductPlanning/ProductPlanner.swift index e7f27685..9d9ae265 100644 --- a/Sources/SWBTaskConstruction/ProductPlanning/ProductPlanner.swift +++ b/Sources/SWBTaskConstruction/ProductPlanning/ProductPlanner.swift @@ -81,6 +81,7 @@ private struct WorkspaceProductPlanBuilder { SDKStatCacheTaskProducer(context: globalTaskProducerContext, targetContexts: targetContexts), HeadermapVFSTaskProducer(context: globalTaskProducerContext, targetContexts: targetContexts), PCHModuleMapTaskProducer(context: globalTaskProducerContext, targetContexts: targetContexts), + BuildDependencyInfoTaskProducer(context: globalTaskProducerContext, targetContexts: targetContexts), ] + (globalProductPlan.planRequest.buildRequest.enableIndexBuildArena ? [IndexBuildVFSDirectoryRemapTaskProducer(context: globalTaskProducerContext)] : []) for taskProducerExtension in await taskProducerExtensions(globalTaskProducerContext.workspaceContext) { diff --git a/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift index 2a67841b..4371f545 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift @@ -220,6 +220,7 @@ public class TaskProducerContext: StaleFileRemovalContext, BuildFileResolution public let appShortcutStringsMetadataCompilerSpec: AppShortcutStringsMetadataCompilerSpec let appleScriptCompilerSpec: CommandLineToolSpec + let buildDependencyInfoSpec: BuildDependencyInfoSpec public let clangSpec: ClangCompilerSpec public let clangAssemblerSpec: ClangCompilerSpec public let clangPreprocessorSpec: ClangCompilerSpec @@ -344,6 +345,7 @@ public class TaskProducerContext: StaleFileRemovalContext, BuildFileResolution let domain = settings.platform?.name ?? "" self.appShortcutStringsMetadataCompilerSpec = workspaceContext.core.specRegistry.getSpec("com.apple.compilers.appshortcutstringsmetadata", domain: domain) as! AppShortcutStringsMetadataCompilerSpec self.appleScriptCompilerSpec = workspaceContext.core.specRegistry.getSpec("com.apple.compilers.osacompile", domain: domain) as! CommandLineToolSpec + self.buildDependencyInfoSpec = workspaceContext.core.specRegistry.getSpec(BuildDependencyInfoSpec.identifier, domain: domain) as! BuildDependencyInfoSpec self.clangSpec = try! workspaceContext.core.specRegistry.getSpec(domain: domain) as ClangCompilerSpec self.clangAssemblerSpec = try! workspaceContext.core.specRegistry.getSpec(domain: domain) as ClangAssemblerSpec self.clangPreprocessorSpec = try! workspaceContext.core.specRegistry.getSpec(domain: domain) as ClangPreprocessorSpec diff --git a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/BuildDependencyInfoTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/BuildDependencyInfoTaskProducer.swift new file mode 100644 index 00000000..94291c94 --- /dev/null +++ b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/BuildDependencyInfoTaskProducer.swift @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SWBCore +import SWBUtil +import SWBMacro +import Foundation +import SWBProtocol + +final class BuildDependencyInfoTaskProducer: StandardTaskProducer, TaskProducer { + private let targetContexts: [TaskProducerContext] + + init(context globalContext: TaskProducerContext, targetContexts: [TaskProducerContext]) { + self.targetContexts = targetContexts + super.init(globalContext) + } + + func generateTasks() async -> [any PlannedTask] { + let components = context.globalProductPlan.planRequest.buildRequest.parameters.action.buildComponents + guard components.contains("build") else { + return [] + } + + let output = context.settings.globalScope.evaluate(BuiltinMacros.BUILD_DIR).join("BuildDependencyInfo.json") + let dumpDependencyPaths: [Path] = targetContexts.compactMap { + guard let target = $0.configuredTarget?.target as? SWBCore.StandardTarget else { + return nil + } + guard target.sourcesBuildPhase?.buildFiles.isEmpty == false else { + return nil + } + if $0.settings.globalScope.evaluate(BuiltinMacros.DUMP_DEPENDENCIES) { + return $0.settings.globalScope.evaluate(BuiltinMacros.DUMP_DEPENDENCIES_OUTPUT_PATH) + } else { + return nil + } + } + + if dumpDependencyPaths.isEmpty { + return [] + } + + var tasks = [any PlannedTask]() + await appendGeneratedTasks(&tasks) { delegate in + await context.buildDependencyInfoSpec.createTasks( + CommandBuildContext(producer: context, scope: context.settings.globalScope, inputs: dumpDependencyPaths.map { FileToBuild(context: context, absolutePath: $0) }, output: output, commandOrderingInputs: []), + delegate, + dumpDependencyPaths: dumpDependencyPaths + ) + } + return tasks + } +} diff --git a/Sources/SWBTaskExecution/BuildDescriptionManager.swift b/Sources/SWBTaskExecution/BuildDescriptionManager.swift index d0a2a29d..bf3e318d 100644 --- a/Sources/SWBTaskExecution/BuildDescriptionManager.swift +++ b/Sources/SWBTaskExecution/BuildDescriptionManager.swift @@ -802,6 +802,10 @@ extension BuildSystemTaskPlanningDelegate: TaskActionCreationDelegate { return AuxiliaryFileTaskAction(context) } + func createBuildDependencyInfoTaskAction() -> any PlannedTaskAction { + return BuildDependencyInfoTaskAction() + } + func createCodeSignTaskAction() -> any PlannedTaskAction { return CodeSignTaskAction() } diff --git a/Sources/SWBTaskExecution/BuiltinTaskActionsExtension.swift b/Sources/SWBTaskExecution/BuiltinTaskActionsExtension.swift index 1b2e6312..299a2962 100644 --- a/Sources/SWBTaskExecution/BuiltinTaskActionsExtension.swift +++ b/Sources/SWBTaskExecution/BuiltinTaskActionsExtension.swift @@ -56,6 +56,7 @@ public struct BuiltinTaskActionsExtension: TaskActionExtension { 41: ClangNonModularCompileTaskAction.self, 42: ObjectLibraryAssemblerTaskAction.self, 43: LinkerTaskAction.self, + 45: BuildDependencyInfoTaskAction.self, ] } } diff --git a/Sources/SWBTaskExecution/CMakeLists.txt b/Sources/SWBTaskExecution/CMakeLists.txt index b8c7f116..1d873198 100644 --- a/Sources/SWBTaskExecution/CMakeLists.txt +++ b/Sources/SWBTaskExecution/CMakeLists.txt @@ -32,6 +32,7 @@ add_library(SWBTaskExecution Task.swift TaskActionExtensionPoint.swift TaskActions/AuxiliaryFileTaskAction.swift + TaskActions/BuildDependencyInfoTaskAction.swift TaskActions/ClangCachingKeyQueryTaskAction.swift TaskActions/ClangCachingMaterializeKeyTaskAction.swift TaskActions/ClangCachingOutputMaterializerTaskAction.swift diff --git a/Sources/SWBTaskExecution/TaskActions/BuildDependencyInfoTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/BuildDependencyInfoTaskAction.swift new file mode 100644 index 00000000..bfaf59f3 --- /dev/null +++ b/Sources/SWBTaskExecution/TaskActions/BuildDependencyInfoTaskAction.swift @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import ArgumentParser +import Foundation + +public import SWBCore +internal import SWBMacro +internal import SWBProtocol +import SWBUtil + +public final class BuildDependencyInfoTaskAction: TaskAction { + public override class var toolIdentifier: String { + return "build-dependency-info" + } + + private struct Options: ParsableArguments { + @Argument var inputs: [Path] + } + + public override func performTaskAction(_ task: any ExecutableTask, dynamicExecutionDelegate: any DynamicTaskExecutionDelegate, executionDelegate: any TaskExecutionDelegate, clientDelegate: any TaskExecutionClientDelegate, outputDelegate: any TaskOutputDelegate) async -> CommandResult { + guard let outputPath = task.outputPaths.first else { + outputDelegate.emitError("could not determine output path") + return .failed + } + + do { + let options = try Options.parse(Array(task.commandLineAsStrings.dropFirst())) + + var errors = [String]() + var targets = [BuildDependencyInfo.TargetDependencyInfo]() + for dumpDependencyPath in options.inputs { + let dumpDependencyData = try Data(contentsOf: URL(fileURLWithPath: dumpDependencyPath.str)) + let dumpDependencyInfo = try JSONDecoder().decode(BuildDependencyInfo.self, from: dumpDependencyData) + errors.append(contentsOf: dumpDependencyInfo.errors) + targets.append(contentsOf: dumpDependencyInfo.targets) + } + + let dependencyInfo = BuildDependencyInfo(targets: targets, errors: errors) + let outputData = try JSONEncoder(outputFormatting: [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes]).encode(dependencyInfo) + let outputURL = URL(fileURLWithPath: outputPath.str) + try outputData.write(to: outputURL) + } catch { + outputDelegate.emitError(error.localizedDescription) + return .failed + } + + return .succeeded + } +} diff --git a/Sources/SWBTaskExecution/TaskActions/ValidateDependenciesTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ValidateDependenciesTaskAction.swift index 46c87dd2..914904b5 100644 --- a/Sources/SWBTaskExecution/TaskActions/ValidateDependenciesTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ValidateDependenciesTaskAction.swift @@ -176,7 +176,7 @@ public final class ValidateDependenciesTaskAction: TaskAction { ], errors: [] ) - let outputData = try JSONEncoder().encode(dependencyInfo) + let outputData = try JSONEncoder(outputFormatting: [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes]).encode(dependencyInfo) let outputURL = URL(fileURLWithPath: payload.dumpDependenciesOutputPath) try outputData.write(to: outputURL) } diff --git a/Sources/SWBTestSupport/CapturingTaskGenerationDelegate.swift b/Sources/SWBTestSupport/CapturingTaskGenerationDelegate.swift index 2779938d..cc798247 100644 --- a/Sources/SWBTestSupport/CapturingTaskGenerationDelegate.swift +++ b/Sources/SWBTestSupport/CapturingTaskGenerationDelegate.swift @@ -116,6 +116,10 @@ extension CapturingTaskGenerationDelegate: TaskActionCreationDelegate { return AuxiliaryFileTaskAction(context) } + package func createBuildDependencyInfoTaskAction() -> any PlannedTaskAction { + return BuildDependencyInfoTaskAction() + } + package func createCodeSignTaskAction() -> any PlannedTaskAction { return CodeSignTaskAction() } diff --git a/Sources/SWBTestSupport/TaskPlanningTestSupport.swift b/Sources/SWBTestSupport/TaskPlanningTestSupport.swift index 2b0f251a..e5c290aa 100644 --- a/Sources/SWBTestSupport/TaskPlanningTestSupport.swift +++ b/Sources/SWBTestSupport/TaskPlanningTestSupport.swift @@ -344,6 +344,10 @@ extension TestTaskPlanningDelegate: TaskActionCreationDelegate { return AuxiliaryFileTaskAction(context) } + package func createBuildDependencyInfoTaskAction() -> any PlannedTaskAction { + return BuildDependencyInfoTaskAction() + } + package func createCodeSignTaskAction() -> any PlannedTaskAction { return CodeSignTaskAction() } diff --git a/Tests/SWBBuildSystemTests/DependencyValidationTests.swift b/Tests/SWBBuildSystemTests/DependencyValidationTests.swift index fca50223..116c0329 100644 --- a/Tests/SWBBuildSystemTests/DependencyValidationTests.swift +++ b/Tests/SWBBuildSystemTests/DependencyValidationTests.swift @@ -345,7 +345,7 @@ fileprivate struct DependencyValidationTests: CoreBasedTests { } } - func validateModuleDependenciesSwift(explicitModules: Bool, dumpDependencies: Bool = false, body: ((Path, BuildOperationTester.BuildResults) async throws -> ())? = nil) async throws { + func validateModuleDependenciesSwift(explicitModules: Bool, dumpDependencies: Bool = false, testFixIts: Bool = true, body: ((Path, BuildOperationTester.BuildResults) async throws -> ())? = nil) async throws { try await withTemporaryDirectory { tmpDir in let testWorkspace = try await TestWorkspace( "Test", @@ -407,10 +407,18 @@ fileprivate struct DependencyValidationTests: CoreBasedTests { let projectXCConfigPath = testWorkspace.sourceRoot.join("Project/Project.xcconfig") try await tester.fs.writeFileContents(projectXCConfigPath) { stream in - stream <<< - """ - MODULE_DEPENDENCIES[target=TargetA] = Dispatch - """ + if testFixIts { + stream <<< + """ + MODULE_DEPENDENCIES[target=TargetA] = Dispatch + """ + } else { + stream <<< + """ + MODULE_DEPENDENCIES[target=TargetA] = Dispatch Foundation + MODULE_DEPENDENCIES[target=TargetB] = Foundation + """ + } } let projectXCConfigContents = try #require(tester.fs.read(projectXCConfigPath).stringValue) @@ -419,7 +427,7 @@ fileprivate struct DependencyValidationTests: CoreBasedTests { let projectXCConfigFinalColumnNumber = (projectXCConfigLines.last?.count ?? 0) + 1 let expectedDiagsByTarget: [String: [Diagnostic]] - if explicitModules { + if explicitModules, testFixIts { expectedDiagsByTarget = [ "TargetA": [ Diagnostic( @@ -810,7 +818,7 @@ fileprivate struct DependencyValidationTests: CoreBasedTests { @Test(.requireSDKs(.macOS)) func dumpDependenciesDuringBuild() async throws { - try await validateModuleDependenciesSwift(explicitModules: true, dumpDependencies: true) { tmpDir, _ in + try await validateModuleDependenciesSwift(explicitModules: true, dumpDependencies: true, testFixIts: false) { tmpDir, _ in let debugDir = tmpDir.join("Test/Project/build/Project.build/Debug") for dir in try localFS.listdir(debugDir) { let buildDir = debugDir.join(dir) @@ -823,6 +831,10 @@ fileprivate struct DependencyValidationTests: CoreBasedTests { #expect(dependencyInfo.targets.first?.dependencies.count == 5) } } + + let globalDependencyInfoPath = tmpDir.join("Test/build/BuildDependencyInfo.json") + let globalDependencyInfo = try JSONDecoder().decode(BuildDependencyInfo.self, from: globalDependencyInfoPath, fs: localFS) + #expect(globalDependencyInfo.targets.first?.dependencies.count == 5) } } } diff --git a/Tests/SWBCorePerfTests/CommandLineSpecPerfTests.swift b/Tests/SWBCorePerfTests/CommandLineSpecPerfTests.swift index 896f48fe..0cee180f 100644 --- a/Tests/SWBCorePerfTests/CommandLineSpecPerfTests.swift +++ b/Tests/SWBCorePerfTests/CommandLineSpecPerfTests.swift @@ -111,6 +111,10 @@ extension CapturingTaskGenerationDelegate: TaskActionCreationDelegate { return AuxiliaryFileTaskAction(context) } + public func createBuildDependencyInfoTaskAction() -> any PlannedTaskAction { + return BuildDependencyInfoTaskAction() + } + public func createCodeSignTaskAction() -> any PlannedTaskAction { return CodeSignTaskAction() }