Skip to content

Commit d791528

Browse files
committed
[Build/Commands/PackageGraph] Remove ModulesGraph.updateBuildTripleRecursively
Plugins don't actually need whole graph to be switched to use `.tools` triple because `PluginTarget.processAccessibleTools` is able to find targets/products that have to be built for the host, it just needs a way to signal that to the build system. `Buildset` has been extended to support a destination which is defaulted to `.target` because really only plugin (command) tools have to set it to `.host`, this helps to propagate the information about expected destination down through `BuildOperation.build(subset:)` and find correct llbuild names and build products.
1 parent b22168e commit d791528

File tree

7 files changed

+47
-60
lines changed

7 files changed

+47
-60
lines changed

Sources/Build/BuildOperation.swift

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,9 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
378378

379379
let subsetDescriptor: String?
380380
switch subset {
381-
case .product(let productName):
381+
case .product(let productName, _):
382382
subsetDescriptor = "product '\(productName)'"
383-
case .target(let targetName):
383+
case .target(let targetName, _):
384384
subsetDescriptor = "target: '\(targetName)'"
385385
case .allExcludingTests, .allIncludingTests:
386386
subsetDescriptor = nil
@@ -433,10 +433,10 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
433433
case .allExcludingTests, .allIncludingTests:
434434
pluginsToCompile = allPlugins
435435
continueBuilding = true
436-
case .product(let productName):
436+
case .product(let productName, _):
437437
pluginsToCompile = allPlugins.filter{ $0.productNames.contains(productName) }
438438
continueBuilding = pluginsToCompile.isEmpty
439-
case .target(let targetName):
439+
case .target(let targetName, _):
440440
pluginsToCompile = allPlugins.filter{ $0.targetName == targetName }
441441
continueBuilding = pluginsToCompile.isEmpty
442442
}
@@ -522,12 +522,14 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
522522
return LLBuildManifestBuilder.TargetKind.main.targetName
523523
case .allIncludingTests:
524524
return LLBuildManifestBuilder.TargetKind.test.targetName
525-
default:
525+
case .product(_, let destination), .target(_, let destination):
526526
// FIXME: This is super unfortunate that we might need to load the package graph.
527527
let graph = try getPackageGraph()
528528
if let result = subset.llbuildTargetName(
529529
for: graph,
530-
buildParameters: self.productsBuildParameters,
530+
using: destination == .host
531+
? self.toolsBuildParameters
532+
: self.productsBuildParameters,
531533
observabilityScope: self.observabilityScope
532534
) {
533535
return result
@@ -550,15 +552,15 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
550552
// done, which makes it hard to realign them all at once.
551553
var pluginsBuildParameters = self.toolsBuildParameters
552554
pluginsBuildParameters.dataPath = pluginsBuildParameters.dataPath.parentDirectory.appending(components: ["plugins", "tools"])
553-
var buildToolsGraph = graph
554-
try buildToolsGraph.updateBuildTripleRecursively(.tools)
555+
556+
var targetBuildParameters = pluginsBuildParameters
557+
targetBuildParameters.destination = .target
555558

556559
let buildOperationForPluginDependencies = BuildOperation(
557-
// FIXME: this doesn't maintain the products/tools split cleanly
558-
productsBuildParameters: pluginsBuildParameters,
560+
productsBuildParameters: targetBuildParameters,
559561
toolsBuildParameters: pluginsBuildParameters,
560562
cacheBuildManifest: false,
561-
packageGraphLoader: { buildToolsGraph },
563+
packageGraphLoader: { graph },
562564
scratchDirectory: pluginsBuildParameters.dataPath,
563565
additionalFileRules: self.additionalFileRules,
564566
pkgConfigDirectories: self.pkgConfigDirectories,
@@ -569,7 +571,8 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
569571
fileSystem: self.fileSystem,
570572
observabilityScope: self.observabilityScope
571573
)
572-
buildToolPluginInvocationResults = try buildToolsGraph.invokeBuildToolPlugins(
574+
575+
buildToolPluginInvocationResults = try graph.invokeBuildToolPlugins(
573576
outputDir: pluginConfiguration.workDirectory.appending("outputs"),
574577
buildParameters: pluginsBuildParameters,
575578
additionalFileRules: self.additionalFileRules,
@@ -579,8 +582,10 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
579582
observabilityScope: self.observabilityScope,
580583
fileSystem: self.fileSystem
581584
) { name, path in
582-
try buildOperationForPluginDependencies.build(subset: .product(name))
583-
if let builtTool = try buildOperationForPluginDependencies.buildPlan.buildProducts.first(where: { $0.product.name == name}) {
585+
try buildOperationForPluginDependencies.build(subset: .product(name, for: .host))
586+
if let builtTool = try buildOperationForPluginDependencies.buildPlan.buildProducts.first(where: {
587+
$0.product.name == name && $0.product.buildTriple == .tools
588+
}) {
584589
return try builtTool.binaryPath
585590
} else {
586591
return nil
@@ -893,13 +898,13 @@ extension BuildSubset {
893898
return Array(graph.reachableTargets)
894899
case .allExcludingTests:
895900
return graph.reachableTargets.filter { $0.type != .test }
896-
case .product(let productName):
901+
case .product(let productName, _):
897902
guard let product = graph.product(for: productName) else {
898903
observabilityScope.emit(error: "no product named '\(productName)'")
899904
return nil
900905
}
901906
return try product.recursiveTargetDependencies()
902-
case .target(let targetName):
907+
case .target(let targetName, _):
903908
guard let target = graph.target(for: targetName) else {
904909
observabilityScope.emit(error: "no target named '\(targetName)'")
905910
return nil
@@ -911,15 +916,17 @@ extension BuildSubset {
911916
/// Returns the name of the llbuild target that corresponds to the build subset.
912917
func llbuildTargetName(
913918
for graph: ModulesGraph,
914-
buildParameters: BuildParameters,
919+
using buildParameters: BuildParameters,
915920
observabilityScope: ObservabilityScope
916921
) -> String? {
917922
switch self {
918923
case .allExcludingTests:
919924
return LLBuildManifestBuilder.TargetKind.main.targetName
920925
case .allIncludingTests:
921926
return LLBuildManifestBuilder.TargetKind.test.targetName
922-
case .product(let productName):
927+
case .product(let productName, let destination):
928+
precondition(buildParameters.destination == destination)
929+
923930
guard let product = graph.product(for: productName) else {
924931
observabilityScope.emit(error: "no product named '\(productName)'")
925932
return nil
@@ -936,7 +943,9 @@ extension BuildSubset {
936943
return observabilityScope.trap {
937944
try product.getLLBuildTargetName(buildParameters: buildParameters)
938945
}
939-
case .target(let targetName):
946+
case .target(let targetName, let destination):
947+
precondition(buildParameters.destination == destination)
948+
940949
guard let target = graph.target(for: targetName) else {
941950
observabilityScope.emit(error: "no target named '\(targetName)'")
942951
return nil

Sources/Commands/PackageCommands/PluginCommand.swift

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -317,30 +317,27 @@ struct PluginCommand: SwiftCommand {
317317
let toolSearchDirs = [try swiftCommandState.getTargetToolchain().swiftCompilerPath.parentDirectory]
318318
+ getEnvSearchPaths(pathString: ProcessEnv.path, currentWorkingDirectory: .none)
319319

320-
var buildToolsGraph = packageGraph
321-
try buildToolsGraph.updateBuildTripleRecursively(.tools)
322-
323320
let buildParameters = try swiftCommandState.toolsBuildParameters
324321
// Build or bring up-to-date any executable host-side tools on which this plugin depends. Add them and any binary dependencies to the tool-names-to-path map.
325322
let buildSystem = try swiftCommandState.createBuildSystem(
326323
explicitBuildSystem: .native,
327324
cacheBuildManifest: false,
328-
// Force all dependencies to be built for the host, to work around the fact that BuildOperation.plan
329-
// knows to compile build tool plugin dependencies for the host but does not do the same for command
330-
// plugins.
331-
productsBuildParameters: buildParameters,
332-
packageGraphLoader: { buildToolsGraph }
325+
productsBuildParameters: swiftCommandState.productsBuildParameters,
326+
toolsBuildParameters: buildParameters,
327+
packageGraphLoader: { packageGraph }
333328
)
334329

335330
let accessibleTools = try plugin.processAccessibleTools(
336-
packageGraph: buildToolsGraph,
331+
packageGraph: packageGraph,
337332
fileSystem: swiftCommandState.fileSystem,
338333
environment: buildParameters.buildEnvironment,
339334
for: try pluginScriptRunner.hostTriple
340335
) { name, _ in
341336
// Build the product referenced by the tool, and add the executable to the tool map. Product dependencies are not supported within a package, so if the tool happens to be from the same package, we instead find the executable that corresponds to the product. There is always one, because of autogeneration of implicit executables with the same name as the target if there isn't an explicit one.
342-
try buildSystem.build(subset: .product(name))
343-
if let builtTool = try buildSystem.buildPlan.buildProducts.first(where: { $0.product.name == name }) {
337+
try buildSystem.build(subset: .product(name, for: .host))
338+
if let builtTool = try buildSystem.buildPlan.buildProducts.first(where: {
339+
$0.product.name == name && $0.product.buildTriple == .tools
340+
}) {
344341
return try builtTool.binaryPath
345342
} else {
346343
return nil

Sources/Commands/SwiftTestCommand.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,12 @@ private func buildTestsIfNeeded(
13811381
toolsBuildParameters: toolsBuildParameters
13821382
)
13831383

1384-
let subset = testProduct.map(BuildSubset.product) ?? .allIncludingTests
1384+
let subset: BuildSubset = if let testProduct {
1385+
.product(testProduct)
1386+
} else {
1387+
.allIncludingTests
1388+
}
1389+
13851390
try buildSystem.build(subset: subset)
13861391

13871392
// Find the test product.

Sources/PackageGraph/ModulesGraph.swift

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -277,30 +277,6 @@ public struct ModulesGraph {
277277
self.allProducts = allProducts
278278
}
279279

280-
package mutating func updateBuildTripleRecursively(_ buildTriple: BuildTriple) throws {
281-
self.reachableTargets = IdentifiableSet(self.reachableTargets.map {
282-
var target = $0
283-
target.buildTriple = buildTriple
284-
return target
285-
})
286-
self.reachableProducts = IdentifiableSet(self.reachableProducts.map {
287-
var product = $0
288-
product.buildTriple = buildTriple
289-
return product
290-
})
291-
292-
self.allTargets = IdentifiableSet(self.allTargets.map {
293-
var target = $0
294-
target.buildTriple = buildTriple
295-
return target
296-
})
297-
self.allProducts = IdentifiableSet(self.allProducts.map {
298-
var product = $0
299-
product.buildTriple = buildTriple
300-
return product
301-
})
302-
}
303-
304280
/// Computes a map from each executable target in any of the root packages to the corresponding test targets.
305281
@_spi(SwiftPMInternal)
306282
public func computeTestTargetsForExecutableTargets() throws -> [ResolvedModule.ID: [ResolvedModule]] {

Sources/SPMBuildCore/BuildParameters/BuildParameters.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public struct BuildParameters: Encodable {
3636
}
3737

3838
/// The destination these parameters are going to be used for.
39-
public let destination: Destination
39+
public var destination: Destination
4040

4141
/// The path to the data directory.
4242
public var dataPath: AbsolutePath

Sources/SPMBuildCore/BuildSystem/BuildSystem.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ public enum BuildSubset {
2525
case allIncludingTests
2626

2727
/// Represents a specific product.
28-
case product(String)
28+
case product(String, for: BuildParameters.Destination = .target)
2929

3030
/// Represents a specific target.
31-
case target(String)
31+
case target(String, for: BuildParameters.Destination = .target)
3232
}
3333

3434
/// A protocol that represents a build system used by SwiftPM for all build operations. This allows factoring out the

Sources/XCBuildSupport/XcodeBuildSystem.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,9 @@ extension PIFBuilderParameters {
382382
extension BuildSubset {
383383
var pifTargetName: String {
384384
switch self {
385-
case .product(let name):
385+
case .product(let name, _):
386386
PackagePIFProjectBuilder.targetName(for: name)
387-
case .target(let name):
387+
case .target(let name, _):
388388
name
389389
case .allExcludingTests:
390390
PIFBuilder.allExcludingTestsTargetName

0 commit comments

Comments
 (0)