Skip to content

Commit

Permalink
[Build/PackageGraph] Sink fallback logic for macro/plugin/test produc…
Browse files Browse the repository at this point in the history
…ts and packages identification into `ModulesGraph`

This is a temporary fix until we can figure out a proper way to
handle situations were all we get is a name of a product or a
target.

Resolves: rdar://129400066
  • Loading branch information
xedin committed Jun 7, 2024
1 parent ee9d0b2 commit 09b3ed1
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 41 deletions.
53 changes: 14 additions & 39 deletions Sources/Build/BuildOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -526,36 +526,22 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
// FIXME: This is super unfortunate that we might need to load the package graph.
let graph = try getPackageGraph()

var product = graph.product(
let product = graph.product(
for: productName,
destination: destination == .host ? .tools : .destination
)

var buildParameters = if destination == .host {
self.toolsBuildParameters
} else {
self.productsBuildParameters
}

// It's possible to request a build of a macro or a plugin via `swift build`
// which won't have the right destination set because it's impossible to indicate it.
//
// Same happens with `--test-product` - if one of the test targets directly references
// a macro then all if its targets and the product itself become `host`.
if product == nil && destination == .target {
if let toolsProduct = graph.product(for: productName, destination: .tools),
toolsProduct.type == .macro || toolsProduct.type == .plugin || toolsProduct.type == .test
{
product = toolsProduct
buildParameters = self.toolsBuildParameters
}
}

guard let product else {
observabilityScope.emit(error: "no product named '\(productName)'")
throw Diagnostics.fatalError
}

let buildParameters = if product.buildTriple == .tools {
self.toolsBuildParameters
} else {
self.productsBuildParameters
}

// If the product is automatic, we build the main target because automatic products
// do not produce a binary right now.
if product.type == .library(.automatic) {
Expand All @@ -570,33 +556,22 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
// FIXME: This is super unfortunate that we might need to load the package graph.
let graph = try getPackageGraph()

var target = graph.target(
let target = graph.target(
for: targetName,
destination: destination == .host ? .tools : .destination
)

var buildParameters = if destination == .host {
self.toolsBuildParameters
} else {
self.productsBuildParameters
}

// It's possible to request a build of a macro or a plugin via `swift build`
// which won't have the right destination because it's impossible to indicate it.
if target == nil && destination == .target {
if let toolsTarget = graph.target(for: targetName, destination: .tools),
toolsTarget.type == .macro || toolsTarget.type == .plugin
{
target = toolsTarget
buildParameters = self.toolsBuildParameters
}
}

guard let target else {
observabilityScope.emit(error: "no target named '\(targetName)'")
throw Diagnostics.fatalError
}

let buildParameters = if target.buildTriple == .tools {
self.toolsBuildParameters
} else {
self.productsBuildParameters
}

return target.getLLBuildTargetName(buildParameters: buildParameters)
}
}
Expand Down
50 changes: 48 additions & 2 deletions Sources/PackageGraph/ModulesGraph.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,57 @@ public struct ModulesGraph {
}

public func product(for name: String, destination: BuildTriple) -> ResolvedProduct? {
self.allProducts.first { $0.name == name && $0.buildTriple == destination }
func findProduct(name: String, destination: BuildTriple) -> ResolvedProduct? {
self.allProducts.first { $0.name == name && $0.buildTriple == destination }
}

if let product = findProduct(name: name, destination: destination) {
return product
}

// FIXME: This is a temporary workaround and needs to be handled by the callers.

// It's possible to request a build of a macro, a plugin, or a test via `swift build`
// which won't have the right destination set because it's impossible to indicate it.
//
// Same happens with `--test-product` - if one of the test targets directly references
// a macro then all if its targets and the product itself become `host`.
if destination == .destination {
if let toolsProduct = findProduct(name: name, destination: .tools),
toolsProduct.type == .macro || toolsProduct.type == .plugin || toolsProduct.type == .test
{
return toolsProduct
}
}

return nil
}

public func target(for name: String, destination: BuildTriple) -> ResolvedModule? {
self.allTargets.first { $0.name == name && $0.buildTriple == destination }
func findModule(name: String, destination: BuildTriple) -> ResolvedModule? {
self.allTargets.first { $0.name == name && $0.buildTriple == destination }
}

if let module = findModule(name: name, destination: destination) {
return module
}

// FIXME: This is a temporary workaround and needs to be handled by the callers.

// It's possible to request a build of a macro, a plugin or a test via `swift build`
// which won't have the right destination set because it's impossible to indicate it.
//
// Same happens with `--test-product` - if one of the test targets directly references
// a macro then all if its targets and the product itself become `host`.
if destination == .destination {
if let toolsModule = findModule(name: name, destination: .tools),
toolsModule.type == .macro || toolsModule.type == .plugin || toolsModule.type == .test
{
return toolsModule
}
}

return nil
}

/// All root and root dependency packages provided as input to the graph.
Expand Down

0 comments on commit 09b3ed1

Please sign in to comment.