Skip to content

Commit b8d848e

Browse files
committed
[Build/Commands] Switch SymbolGraphExtract to use build plan
Yet another step on the path to remove `buildTriple` from `Resolved{Product, Module}`. Instead of trying to lookup modules in the module graph and then going the build plan for their descriptions, symbol-graph-extract should refer to the build plan directly.
1 parent 566b4e1 commit b8d848e

File tree

9 files changed

+93
-59
lines changed

9 files changed

+93
-59
lines changed

Sources/Build/BuildDescription/ClangModuleBuildDescription.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ public final class ClangModuleBuildDescription {
212212
/// this module.
213213
package func symbolGraphExtractArguments() throws -> [String] {
214214
var args = [String]()
215+
216+
args += ["-module-name", self.target.c99name]
217+
args += try self.buildParameters.tripleArgs(for: self.target)
218+
args += ["-module-cache-path", try self.buildParameters.moduleCache.pathString]
219+
215220
if self.clangTarget.isCXX {
216221
args += ["-cxx-interoperability-mode=default"]
217222
}

Sources/Build/BuildDescription/ModuleBuildDescription.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212

1313
import Basics
1414
import struct PackageGraph.ResolvedModule
15+
import struct PackageGraph.ResolvedPackage
1516
import struct PackageModel.Resource
1617
import struct PackageModel.ToolsVersion
1718
import struct SPMBuildCore.BuildToolPluginInvocationResult
1819
import struct SPMBuildCore.BuildParameters
20+
import protocol SPMBuildCore.ModuleBuildDescription
1921

2022
public enum BuildDescriptionError: Swift.Error {
2123
case requestedFileNotPartOfTarget(targetName: String, requestedFilePath: AbsolutePath)
@@ -25,7 +27,7 @@ public enum BuildDescriptionError: Swift.Error {
2527
public typealias TargetBuildDescription = ModuleBuildDescription
2628

2729
/// A module build description which can either be for a Swift or Clang module.
28-
public enum ModuleBuildDescription {
30+
public enum ModuleBuildDescription: SPMBuildCore.ModuleBuildDescription {
2931
/// Swift target description.
3032
case swift(SwiftModuleBuildDescription)
3133

@@ -73,6 +75,19 @@ public enum ModuleBuildDescription {
7375
}
7476
}
7577

78+
public var package: ResolvedPackage {
79+
switch self {
80+
case .swift(let description):
81+
description.package
82+
case .clang(let description):
83+
description.package
84+
}
85+
}
86+
87+
public var module: ResolvedModule {
88+
self.target
89+
}
90+
7691
/// Paths to the binary libraries the target depends on.
7792
var libraryBinaryPaths: Set<AbsolutePath> {
7893
switch self {
@@ -101,7 +116,7 @@ public enum ModuleBuildDescription {
101116
}
102117
}
103118

104-
var buildParameters: BuildParameters {
119+
public var buildParameters: BuildParameters {
105120
switch self {
106121
case .swift(let buildDescription):
107122
return buildDescription.buildParameters
@@ -121,7 +136,7 @@ public enum ModuleBuildDescription {
121136

122137
/// Determines the arguments needed to run `swift-symbolgraph-extract` for
123138
/// this module.
124-
package func symbolGraphExtractArguments() throws -> [String] {
139+
public func symbolGraphExtractArguments() throws -> [String] {
125140
switch self {
126141
case .swift(let buildDescription): try buildDescription.symbolGraphExtractArguments()
127142
case .clang(let buildDescription): try buildDescription.symbolGraphExtractArguments()

Sources/Build/BuildDescription/SwiftModuleBuildDescription.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,11 @@ public final class SwiftModuleBuildDescription {
639639
/// this module.
640640
package func symbolGraphExtractArguments() throws -> [String] {
641641
var args = [String]()
642+
643+
args += ["-module-name", self.target.c99name]
644+
args += try self.buildParameters.tripleArgs(for: self.target)
645+
args += ["-module-cache-path", try self.buildParameters.moduleCache.pathString]
646+
642647
args += try self.cxxInteroperabilityModeArguments(
643648
propagateFromCurrentModuleOtherSwiftFlags: true)
644649

Sources/Build/BuildPlan/BuildPlan.swift

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
216216
AnySequence(self.productMap.values.map { $0 as SPMBuildCore.ProductBuildDescription })
217217
}
218218

219+
public var buildModules: AnySequence<SPMBuildCore.ModuleBuildDescription> {
220+
AnySequence(self.targetMap.values.map { $0 as SPMBuildCore.ModuleBuildDescription })
221+
}
222+
219223
/// The results of invoking any build tool plugins used by targets in this build.
220224
public let buildToolPluginInvocationResults: [ResolvedModule.ID: [BuildToolPluginInvocationResult]]
221225

@@ -674,15 +678,6 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
674678
}
675679
}
676680

677-
/// Determines the arguments needed to run `swift-symbolgraph-extract` for
678-
/// a particular module.
679-
public func symbolGraphExtractArguments(for module: ResolvedModule) throws -> [String] {
680-
guard let description = self.targetMap[module.id] else {
681-
throw InternalError("Expected description for module \(module)")
682-
}
683-
return try description.symbolGraphExtractArguments()
684-
}
685-
686681
/// Returns the files and directories that affect the build process of this build plan.
687682
package var inputs: [Input] {
688683
var inputs: [Input] = []

Sources/Commands/PackageCommands/DumpCommands.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ struct DumpSymbolGraph: AsyncSwiftCommand {
7070

7171
// Run the tool once for every library and executable target in the root package.
7272
let buildPlan = try buildSystem.buildPlan
73+
let modulesGraph = try await buildSystem.getPackageGraph()
7374
let symbolGraphDirectory = buildPlan.destinationBuildParameters.dataPath.appending("symbolgraph")
74-
let targets = try await buildSystem.getPackageGraph().rootPackages.flatMap{ $0.modules }.filter{ $0.type == .library }
75-
for target in targets {
76-
print("-- Emitting symbol graph for", target.name)
75+
for description in buildPlan.buildModules
76+
where description.module.type == .library && modulesGraph.rootPackages[description.package.id] != nil
77+
{
78+
print("-- Emitting symbol graph for", description.module.name)
7779
let result = try symbolGraphExtractor.extractSymbolGraph(
78-
module: target,
79-
buildPlan: buildPlan,
80-
buildParameters: buildPlan.destinationBuildParameters,
80+
for: description,
8181
outputRedirection: .collect(redirectStderr: true),
8282
outputDirectory: symbolGraphDirectory,
8383
verboseOutput: swiftCommandState.logLevel <= .info
@@ -87,9 +87,9 @@ struct DumpSymbolGraph: AsyncSwiftCommand {
8787
let commandline = "\nUsing commandline: \(result.arguments)"
8888
switch result.output {
8989
case .success(let value):
90-
swiftCommandState.observabilityScope.emit(error: "Failed to emit symbol graph for '\(target.c99name)': \(String(decoding: value, as: UTF8.self))\(commandline)")
90+
swiftCommandState.observabilityScope.emit(error: "Failed to emit symbol graph for '\(description.module.c99name)': \(String(decoding: value, as: UTF8.self))\(commandline)")
9191
case .failure(let error):
92-
swiftCommandState.observabilityScope.emit(error: "Internal error while emitting symbol graph for '\(target.c99name)': \(error)\(commandline)")
92+
swiftCommandState.observabilityScope.emit(error: "Internal error while emitting symbol graph for '\(description.module.c99name)': \(error)\(commandline)")
9393
}
9494
}
9595
}

Sources/Commands/Utilities/PluginDelegate.swift

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -398,25 +398,34 @@ final class PluginDelegate: PluginInvocationDelegate {
398398
cacheBuildManifest: false
399399
)
400400

401-
// Find the target in the build operation's package graph; it's an error if we don't find it.
402-
let packageGraph = try await buildSystem.getPackageGraph()
403-
guard let target = packageGraph.module(for: targetName) else {
404-
throw StringError("could not find a target named “\(targetName)")
401+
func lookupDescription(
402+
for moduleName: String,
403+
destination: BuildParameters.Destination
404+
) throws -> ModuleBuildDescription? {
405+
try buildSystem.buildPlan.buildModules.first {
406+
$0.module.name == moduleName && $0.buildParameters.destination == destination
407+
}
405408
}
406409

407-
// FIXME: This is currently necessary because `target(for:destination:)` can
408-
// produce a module that is targeting host when `targetName`` corresponds to
409-
// a macro, plugin, or a test. Ideally we'd ask a build system for a`BuildSubset`
410-
// and get the destination from there but there are other places that need
411-
// refactoring in that way as well.
412-
let buildParameters = if target.buildTriple == .tools {
413-
try swiftCommandState.toolsBuildParameters
414-
} else {
415-
try swiftCommandState.productsBuildParameters
416-
}
410+
// FIXME: The name alone doesn't give us enough information to figure out what
411+
// the destination is, this logic prefers "target" over "host" because that's
412+
// historically how this was setup. Ideally we should be building for both "host"
413+
// and "target" if module is configured for them but that would require changing
414+
// `PluginInvocationSymbolGraphResult` to carry multiple directories.
415+
let description: ModuleBuildDescription? = if let targetDescription = try lookupDescription(for: targetName, destination: .target) {
416+
targetDescription
417+
} else if let hostDescription = try lookupDescription(for: targetName, destination: .host) {
418+
hostDescription
419+
} else {
420+
nil
421+
}
422+
423+
guard let description else {
424+
throw InternalError("could not find a target named: \(targetName)")
425+
}
417426

418427
// Build the target, if needed.
419-
try await buildSystem.build(subset: .target(target.name, for: buildParameters.destination))
428+
try await buildSystem.build(subset: .target(targetName, for: description.buildParameters.destination))
420429

421430
// Configure the symbol graph extractor.
422431
var symbolGraphExtractor = try SymbolGraphExtract(
@@ -442,21 +451,16 @@ final class PluginDelegate: PluginInvocationDelegate {
442451
symbolGraphExtractor.emitExtensionBlockSymbols = options.emitExtensionBlocks
443452

444453
// Determine the output directory, and remove any old version if it already exists.
445-
guard let package = packageGraph.package(for: target) else {
446-
throw StringError("could not determine the package for target “\(target.name)")
447-
}
448-
let outputDir = buildParameters.dataPath.appending(
454+
let outputDir = description.buildParameters.dataPath.appending(
449455
components: "extracted-symbols",
450-
package.identity.description,
451-
target.name
456+
description.package.identity.description,
457+
targetName
452458
)
453459
try swiftCommandState.fileSystem.removeFileTree(outputDir)
454460

455461
// Run the symbol graph extractor on the target.
456462
let result = try symbolGraphExtractor.extractSymbolGraph(
457-
module: target,
458-
buildPlan: try buildSystem.buildPlan,
459-
buildParameters: buildParameters,
463+
for: description,
460464
outputRedirection: .collect,
461465
outputDirectory: outputDir,
462466
verboseOutput: self.swiftCommandState.logLevel <= .info

Sources/Commands/Utilities/SymbolGraphExtract.swift

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ package struct SymbolGraphExtract {
5454
/// The `outputDirection` determines how the output from the tool subprocess is handled, and `verbosity` specifies
5555
/// how much console output to ask the tool to emit.
5656
package func extractSymbolGraph(
57-
module: ResolvedModule,
58-
buildPlan: BuildPlan,
59-
buildParameters: BuildParameters,
57+
for description: ModuleBuildDescription,
6058
outputRedirection: AsyncProcess.OutputRedirection = .none,
6159
outputDirectory: AbsolutePath,
6260
verboseOutput: Bool
@@ -65,12 +63,9 @@ package struct SymbolGraphExtract {
6563

6664
// Construct arguments for extracting symbols for a single target.
6765
var commandLine = [self.tool.pathString]
68-
commandLine += try buildPlan.symbolGraphExtractArguments(for: module)
66+
commandLine += try description.symbolGraphExtractArguments()
6967

7068
// FIXME: everything here should be in symbolGraphExtractArguments
71-
commandLine += ["-module-name", module.c99name]
72-
commandLine += try buildParameters.tripleArgs(for: module)
73-
commandLine += ["-module-cache-path", try buildParameters.moduleCache.pathString]
7469
if verboseOutput {
7570
commandLine += ["-v"]
7671
}
@@ -86,7 +81,11 @@ package struct SymbolGraphExtract {
8681
}
8782

8883
let extensionBlockSymbolsFlag = emitExtensionBlockSymbols ? "-emit-extension-block-symbols" : "-omit-extension-block-symbols"
89-
if DriverSupport.checkSupportedFrontendFlags(flags: [extensionBlockSymbolsFlag.trimmingCharacters(in: ["-"])], toolchain: buildParameters.toolchain, fileSystem: fileSystem) {
84+
if DriverSupport.checkSupportedFrontendFlags(
85+
flags: [extensionBlockSymbolsFlag.trimmingCharacters(in: ["-"])],
86+
toolchain: description.buildParameters.toolchain,
87+
fileSystem: fileSystem
88+
) {
9089
commandLine += [extensionBlockSymbolsFlag]
9190
} else {
9291
observabilityScope.emit(warning: "dropped \(extensionBlockSymbolsFlag) flag because it is not supported by this compiler version")

Sources/SPMBuildCore/BuildSystem/BuildSystem.swift

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ extension ProductBuildDescription {
8080
}
8181
}
8282

83+
public protocol ModuleBuildDescription {
84+
/// The package the module belongs to.
85+
var package: ResolvedPackage { get }
86+
87+
/// The underlying module this description is for.
88+
var module: ResolvedModule { get }
89+
90+
/// The build parameters.
91+
var buildParameters: BuildParameters { get }
92+
93+
func symbolGraphExtractArguments() throws -> [String]
94+
}
95+
8396
public protocol BuildPlan {
8497
/// Parameters used when building end products for the destination platform.
8598
var destinationBuildParameters: BuildParameters { get }
@@ -89,12 +102,10 @@ public protocol BuildPlan {
89102

90103
var buildProducts: AnySequence<ProductBuildDescription> { get }
91104

105+
var buildModules: AnySequence<ModuleBuildDescription> { get }
106+
92107
func createAPIToolCommonArgs(includeLibrarySearchPaths: Bool) throws -> [String]
93108
func createREPLArguments() throws -> [String]
94-
95-
/// Determines the arguments needed to run `swift-symbolgraph-extract` for
96-
/// a particular module.
97-
func symbolGraphExtractArguments(for module: ResolvedModule) throws -> [String]
98109
}
99110

100111
public protocol BuildSystemFactory {

Sources/_InternalTestSupport/MockBuildTestHelper.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ enum BuildError: Swift.Error {
285285

286286
public struct BuildPlanResult {
287287
public let plan: Build.BuildPlan
288-
public let targetMap: [ResolvedModule.ID: ModuleBuildDescription]
288+
public let targetMap: [ResolvedModule.ID: Build.ModuleBuildDescription]
289289
public let productMap: [ResolvedProduct.ID: Build.ProductBuildDescription]
290290

291291
public init(plan: Build.BuildPlan) throws {
@@ -316,7 +316,7 @@ public struct BuildPlanResult {
316316
XCTAssertEqual(self.plan.productMap.count, count, file: file, line: line)
317317
}
318318

319-
public func moduleBuildDescription(for name: String) throws -> ModuleBuildDescription {
319+
public func moduleBuildDescription(for name: String) throws -> Build.ModuleBuildDescription {
320320
let matchingIDs = targetMap.keys.filter({ $0.moduleName == name })
321321
guard matchingIDs.count == 1, let target = targetMap[matchingIDs[0]] else {
322322
if matchingIDs.isEmpty {
@@ -342,7 +342,7 @@ public struct BuildPlanResult {
342342
}
343343
}
344344

345-
extension ModuleBuildDescription {
345+
extension Build.ModuleBuildDescription {
346346
public func swift() throws -> SwiftModuleBuildDescription {
347347
switch self {
348348
case .swift(let description):

0 commit comments

Comments
 (0)