Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Sources/Basics/Graph/GraphAlgorithms.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public func depthFirstSearch<T: Hashable>(
public func depthFirstSearch<T: Hashable>(
_ nodes: [T],
successors: (T) async throws -> [T],
onUnique: (T) -> Void,
onDuplicate: (T, T) -> Void
onUnique: (T) async throws -> Void,
onDuplicate: (T, T) async -> Void
) async rethrows {
var stack = OrderedSet<T>()
var visited = Set<T>()
Expand All @@ -74,9 +74,9 @@ public func depthFirstSearch<T: Hashable>(

let visitResult = visited.insert(curr)
if visitResult.inserted {
onUnique(curr)
try await onUnique(curr)
} else {
onDuplicate(visitResult.memberAfterInsert, curr)
await onDuplicate(visitResult.memberAfterInsert, curr)
continue
}

Expand Down
47 changes: 26 additions & 21 deletions Sources/Build/BuildOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

@_spi(SwiftPMInternal)
import Basics
import _Concurrency
import LLBuildManifest
import PackageGraph
import PackageLoading
Expand Down Expand Up @@ -186,7 +187,9 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
}

public var builtTestProducts: [BuiltTestProduct] {
(try? getBuildDescription())?.builtTestProducts ?? []
get async {
(try? await getBuildDescription())?.builtTestProducts ?? []
}
}

/// File rules to determine resource handling behavior.
Expand Down Expand Up @@ -277,8 +280,8 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
///
/// This will try skip build planning if build manifest caching is enabled
/// and the package structure hasn't changed.
public func getBuildDescription(subset: BuildSubset? = nil) throws -> BuildDescription {
return try self.buildDescription.memoize {
public func getBuildDescription(subset: BuildSubset? = nil) async throws -> BuildDescription {
return try await self.buildDescription.memoize {
if self.cacheBuildManifest {
do {
// if buildPackageStructure returns a valid description we use that, otherwise we perform full planning
Expand Down Expand Up @@ -307,12 +310,12 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
}
}
// We need to perform actual planning if we reach here.
return try self.plan(subset: subset).description
return try await self.plan(subset: subset).description
}
}

public func getBuildManifest() throws -> LLBuildManifest {
return try self.plan().manifest
public func getBuildManifest() async throws -> LLBuildManifest {
try await self.plan().manifest
}

/// Cancel the active build operation.
Expand Down Expand Up @@ -397,7 +400,9 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
// Get the build description (either a cached one or newly created).

// Get the build description
let buildDescription = try getBuildDescription(subset: subset)
let buildDescription = try unsafe_await {
try await self.getBuildDescription(subset: subset)
}

// Verify dependency imports on the described targets
try verifyTargetImports(in: buildDescription)
Expand All @@ -412,7 +417,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
// If any plugins are part of the build set, compile them now to surface
// any errors up-front. Returns true if we should proceed with the build
// or false if not. It will already have thrown any appropriate error.
guard try self.compilePlugins(in: subset) else {
guard try unsafe_await({ try await self.compilePlugins(in: subset) }) else {
return
}

Expand Down Expand Up @@ -476,10 +481,10 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
/// true if the build should proceed. Throws an error in case of failure. A
/// reason why the build might not proceed even on success is if only plugins
/// should be compiled.
func compilePlugins(in subset: BuildSubset) throws -> Bool {
func compilePlugins(in subset: BuildSubset) async throws -> Bool {
// Figure out what, if any, plugin descriptions to compile, and whether
// to continue building after that based on the subset.
let allPlugins = try getBuildDescription().pluginDescriptions
let allPlugins = try await getBuildDescription().pluginDescriptions
let pluginsToCompile: [PluginBuildDescription]
let continueBuilding: Bool
switch subset {
Expand All @@ -497,7 +502,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
// Compile any plugins we ended up with. If any of them fails, it will
// throw.
for plugin in pluginsToCompile {
try compilePlugin(plugin)
try await compilePlugin(plugin)
}

// If we get this far they all succeeded. Return whether to continue the
Expand All @@ -507,7 +512,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS

// Compiles a single plugin, emitting its output and throwing an error if it
// fails.
func compilePlugin(_ plugin: PluginBuildDescription) throws {
func compilePlugin(_ plugin: PluginBuildDescription) async throws {
guard let pluginConfiguration else {
throw InternalError("unknown plugin script runner")
}
Expand Down Expand Up @@ -554,15 +559,15 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
preparationStepName: "Compiling plugin \(plugin.moduleName)",
progressTracker: self.current?.tracker
)
let result = try temp_await {
let result = try await withCheckedThrowingContinuation {
pluginConfiguration.scriptRunner.compilePluginScript(
sourceFiles: plugin.sources.paths,
pluginName: plugin.moduleName,
toolsVersion: plugin.toolsVersion,
observabilityScope: self.observabilityScope,
callbackQueue: DispatchQueue.sharedConcurrent,
delegate: delegate,
completion: $0)
completion: $0.resume(with:))
}

// Throw an error on failure; we will already have emitted the compiler's output in this case.
Expand Down Expand Up @@ -641,7 +646,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
}

/// Create the build plan and return the build description.
private func plan(subset: BuildSubset? = nil) throws -> (description: BuildDescription, manifest: LLBuildManifest) {
private func plan(subset: BuildSubset? = nil) async throws -> (description: BuildDescription, manifest: LLBuildManifest) {
// Load the package graph.
let graph = try getPackageGraph()

Expand All @@ -655,7 +660,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
satisfying: self.config.buildEnvironment(for: .host)
)

pluginTools = try buildPluginTools(
pluginTools = try await buildPluginTools(
graph: graph,
pluginsPerModule: pluginsPerModule,
hostTriple: try pluginConfiguration.scriptRunner.hostTriple
Expand All @@ -665,7 +670,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
}

// Create the build plan based on the modules graph and any information from plugins.
let plan = try BuildPlan(
let plan = try await BuildPlan(
destinationBuildParameters: self.config.destinationBuildParameters,
toolsBuildParameters: self.config.buildParameters(for: .host),
graph: graph,
Expand Down Expand Up @@ -834,9 +839,9 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
return nil
}

public func packageStructureChanged() -> Bool {
public func packageStructureChanged() async -> Bool {
do {
_ = try self.plan()
_ = try await self.plan()
}
catch Diagnostics.fatalError {
return false
Expand Down Expand Up @@ -875,7 +880,7 @@ extension BuildOperation {
graph: ModulesGraph,
pluginsPerModule: [ResolvedModule.ID: [ResolvedModule]],
hostTriple: Basics.Triple
) throws -> [ResolvedModule.ID: [String: PluginTool]] {
) async throws -> [ResolvedModule.ID: [String: PluginTool]] {
var accessibleToolsPerPlugin: [ResolvedModule.ID: [String: PluginTool]] = [:]

var config = self.config
Expand All @@ -893,7 +898,7 @@ extension BuildOperation {
component: "plugin-tools-description.json"
)

let buildPlan = try BuildPlan(
let buildPlan = try await BuildPlan(
destinationBuildParameters: config.destinationBuildParameters,
toolsBuildParameters: config.toolsBuildParameters,
graph: graph,
Expand Down
25 changes: 13 additions & 12 deletions Sources/Build/BuildPlan/BuildPlan.swift
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one needs import _Concurrency at the top to build with CMake/XCBuild

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//

import _Concurrency
import Basics
import Foundation
import LLBuildManifest
Expand Down Expand Up @@ -250,8 +251,8 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
graph: ModulesGraph,
fileSystem: any FileSystem,
observabilityScope: ObservabilityScope
) throws {
try self.init(
) async throws {
try await self.init(
destinationBuildParameters: productsBuildParameters,
toolsBuildParameters: toolsBuildParameters,
graph: graph,
Expand All @@ -274,7 +275,7 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
disableSandbox: Bool = false,
fileSystem: any FileSystem,
observabilityScope: ObservabilityScope
) throws {
) async throws {
self.destinationBuildParameters = destinationBuildParameters
self.toolsBuildParameters = toolsBuildParameters
self.graph = graph
Expand All @@ -295,7 +296,7 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
var pluginDescriptions = [PluginBuildDescription]()
var shouldGenerateTestObservation = true

try Self.computeDestinations(
try await Self.computeDestinations(
graph: graph,
onProduct: { product, destination in
if !product.shouldCreateProductDescription {
Expand Down Expand Up @@ -344,7 +345,7 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
}

if let pluginConfiguration, !buildParameters.shouldSkipBuilding {
let pluginInvocationResults = try Self.invokeBuildToolPlugins(
let pluginInvocationResults = try await Self.invokeBuildToolPlugins(
for: module,
configuration: pluginConfiguration,
buildParameters: toolsBuildParameters,
Expand Down Expand Up @@ -737,7 +738,7 @@ extension BuildPlan {
fileSystem: any FileSystem,
observabilityScope: ObservabilityScope,
surfaceDiagnostics: Bool = false
) throws -> [BuildToolPluginInvocationResult] {
) async throws -> [BuildToolPluginInvocationResult] {
let outputDir = configuration.workDirectory.appending("outputs")

/// Determine the package that contains the target.
Expand Down Expand Up @@ -799,7 +800,7 @@ extension BuildPlan {
pluginDerivedResources = []
}

let result = try temp_await {
let result = try await withCheckedThrowingContinuation {
pluginModule.invoke(
module: plugin,
action: .createBuildToolCommands(
Expand All @@ -822,7 +823,7 @@ extension BuildPlan {
fileSystem: fileSystem,
modulesGraph: modulesGraph,
observabilityScope: observabilityScope,
completion: $0
completion: $0.resume(with:)
)
}

Expand Down Expand Up @@ -916,8 +917,8 @@ extension BuildPlan {
fileprivate static func computeDestinations(
graph: ModulesGraph,
onProduct: (ResolvedProduct, Destination) throws -> Void,
onModule: (ResolvedModule, Destination) throws -> Void
) rethrows {
onModule: (ResolvedModule, Destination) async throws -> Void
) async rethrows {
enum Node: Hashable {
case package(ResolvedPackage)
case product(ResolvedProduct, Destination)
Expand Down Expand Up @@ -1023,7 +1024,7 @@ extension BuildPlan {
}
}

try depthFirstSearch(graph.packages.map { Node.package($0) }) { node in
try await depthFirstSearch(graph.packages.map { Node.package($0) }) { node in
switch node {
case .package(let package):
successors(for: package)
Expand All @@ -1040,7 +1041,7 @@ extension BuildPlan {
try onProduct(product, destination)

case .module(let module, let destination):
try onModule(module, destination)
try await onModule(module, destination)
}
} onDuplicate: { _, _ in
// No de-duplication is necessary we only want unique nodes.
Expand Down
4 changes: 3 additions & 1 deletion Sources/Build/LLBuildCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,9 @@ final class PackageStructureCommand: CustomLLBuildCommand {
_: SPMLLBuild.Command,
_: SPMLLBuild.BuildSystemCommandInterface
) -> Bool {
self.context.packageStructureDelegate.packageStructureChanged()
unsafe_await {
await self.context.packageStructureDelegate.packageStructureChanged()
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Build/LLBuildProgressTracker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public final class BuildExecutionContext {
}

public protocol PackageStructureDelegate {
func packageStructureChanged() -> Bool
func packageStructureChanged() async -> Bool
}

/// Convenient llbuild build system delegate implementation
Expand Down
2 changes: 1 addition & 1 deletion Sources/Commands/SwiftBuildCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public struct SwiftBuildCommand: AsyncSwiftCommand {
) as? BuildOperation else {
throw StringError("asked for native build system but did not get it")
}
let buildManifest = try buildOperation.getBuildManifest()
let buildManifest = try await buildOperation.getBuildManifest()
var serializer = DOTManifestSerializer(manifest: buildManifest)
// print to stdout
let outputStream = stdoutStream
Expand Down
2 changes: 1 addition & 1 deletion Sources/Commands/SwiftTestCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1495,7 +1495,7 @@ private func buildTestsIfNeeded(
try buildSystem.build(subset: subset)

// Find the test product.
let testProducts = buildSystem.builtTestProducts
let testProducts = await buildSystem.builtTestProducts
guard !testProducts.isEmpty else {
if let testProduct {
throw TestError.productIsNotTest(productName: testProduct)
Expand Down
4 changes: 2 additions & 2 deletions Sources/Commands/Utilities/PluginDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ final class PluginDelegate: PluginInvocationDelegate {
// Iterate over the tests and run those that match the filter.
var testTargetResults: [PluginInvocationTestResult.TestTarget] = []
var numFailedTests = 0
for testProduct in buildSystem.builtTestProducts {
for testProduct in await buildSystem.builtTestProducts {
// Get the test suites in the bundle. Each is just a container for test cases.
let testSuites = try TestingSupport.getTestSuites(
fromTestAt: testProduct.bundlePath,
Expand Down Expand Up @@ -344,7 +344,7 @@ final class PluginDelegate: PluginInvocationDelegate {
// Use `llvm-cov` to export the merged `.profdata` file contents in JSON form.
var llvmCovCommand = [try toolchain.getLLVMCov().pathString]
llvmCovCommand += ["export", "-instr-profile=\(mergedCovFile.pathString)"]
for product in buildSystem.builtTestProducts {
for product in await buildSystem.builtTestProducts {
llvmCovCommand.append("-object")
llvmCovCommand.append(product.binaryPath.pathString)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SPMBuildCore/BuildSystem/BuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public protocol BuildSystem: Cancellable {
var delegate: BuildSystemDelegate? { get }

/// The test products that this build system will build.
var builtTestProducts: [BuiltTestProduct] { get }
var builtTestProducts: [BuiltTestProduct] { get async }

/// Returns the package graph used by the build system.
func getPackageGraph() throws -> ModulesGraph
Expand Down
Loading