-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Symbol graph support for swiftbuild build system #8923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
7807e68
Symbol graph support for swiftbuild build system
cmcgee1024 b17042c
Merge branch 'main' of https://github.com/swiftlang/swift-package-man…
cmcgee1024 6ac1fbc
Tidy up build result construction
cmcgee1024 b7b01f2
Tidy more
cmcgee1024 c797b79
Add todos for the symbol graph generation options
cmcgee1024 a386fd7
Skip pretty print symbol graph test until swift build supports it
cmcgee1024 cf9b61c
Move the symbol graph output for a target into the buid system abstra…
cmcgee1024 d28059b
Mark test as intermittent
cmcgee1024 34c0372
Skip dump symbol graph test with swiftbuild on Windows
cmcgee1024 542ddb3
Merge branch 'main' into symbol_graph_extract
bkhouri File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,54 +52,79 @@ struct DumpSymbolGraph: AsyncSwiftCommand { | |
// | ||
// We turn build manifest caching off because we need the build plan. | ||
let buildSystem = try await swiftCommandState.createBuildSystem( | ||
explicitBuildSystem: .native, | ||
// We are enabling all traits for dumping the symbol graph. | ||
traitConfiguration: .init(enableAllTraits: true), | ||
cacheBuildManifest: false | ||
) | ||
try await buildSystem.build() | ||
// TODO pass along the various flags as associated values to the symbol graph build output (e.g. includeSPISymbols) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question: do we have a GitHub issue tracking this TODO? |
||
let buildResult = try await buildSystem.build(subset: .allExcludingTests, buildOutputs: [.symbolGraph, .buildPlan]) | ||
|
||
// Configure the symbol graph extractor. | ||
let symbolGraphExtractor = try SymbolGraphExtract( | ||
fileSystem: swiftCommandState.fileSystem, | ||
tool: swiftCommandState.getTargetToolchain().getSymbolGraphExtract(), | ||
observabilityScope: swiftCommandState.observabilityScope, | ||
skipSynthesizedMembers: skipSynthesizedMembers, | ||
minimumAccessLevel: minimumAccessLevel, | ||
skipInheritedDocs: skipInheritedDocs, | ||
includeSPISymbols: includeSPISymbols, | ||
emitExtensionBlockSymbols: extensionBlockSymbolBehavior == .emitExtensionBlockSymbols, | ||
outputFormat: .json(pretty: prettyPrint) | ||
) | ||
let symbolGraphDirectory = try swiftCommandState.productsBuildParameters.dataPath.appending("symbolgraph") | ||
|
||
// Run the tool once for every library and executable target in the root package. | ||
let buildPlan = try buildSystem.buildPlan | ||
let modulesGraph = try await buildSystem.getPackageGraph() | ||
let symbolGraphDirectory = buildPlan.destinationBuildParameters.dataPath.appending("symbolgraph") | ||
for description in buildPlan.buildModules { | ||
guard description.module.type == .library, | ||
modulesGraph.rootPackages[description.package.id] != nil | ||
else { | ||
continue | ||
} | ||
let fs = swiftCommandState.fileSystem | ||
|
||
try? fs.removeFileTree(symbolGraphDirectory) | ||
try fs.createDirectory(symbolGraphDirectory, recursive: true) | ||
|
||
if let symbolGraph = buildResult.symbolGraph { | ||
// The build system produced symbol graphs for us, one for each target. | ||
let buildPath = try swiftCommandState.productsBuildParameters.buildPath | ||
|
||
print("-- Emitting symbol graph for", description.module.name) | ||
let result = try symbolGraphExtractor.extractSymbolGraph( | ||
for: description, | ||
outputRedirection: .collect(redirectStderr: true), | ||
outputDirectory: symbolGraphDirectory, | ||
verboseOutput: swiftCommandState.logLevel <= .info | ||
// Copy the symbol graphs from the target-specific locations to the single output directory | ||
for rootPackage in try await buildSystem.getPackageGraph().rootPackages { | ||
for module in rootPackage.modules { | ||
let sgDir = symbolGraph.outputLocationForTarget(module.name, try swiftCommandState.productsBuildParameters) | ||
|
||
if case let sgDir = buildPath.appending(components: sgDir), fs.exists(sgDir) { | ||
for sgFile in try fs.getDirectoryContents(sgDir) { | ||
try fs.copy(from: sgDir.appending(components: sgFile), to: symbolGraphDirectory.appending(sgFile)) | ||
} | ||
} | ||
} | ||
} | ||
} else if let buildPlan = buildResult.buildPlan { | ||
// Otherwise, with a build plan we can run the symbol graph extractor tool on the built targets. | ||
let symbolGraphExtractor = try SymbolGraphExtract( | ||
fileSystem: swiftCommandState.fileSystem, | ||
tool: swiftCommandState.getTargetToolchain().getSymbolGraphExtract(), | ||
observabilityScope: swiftCommandState.observabilityScope, | ||
skipSynthesizedMembers: skipSynthesizedMembers, | ||
minimumAccessLevel: minimumAccessLevel, | ||
skipInheritedDocs: skipInheritedDocs, | ||
includeSPISymbols: includeSPISymbols, | ||
emitExtensionBlockSymbols: extensionBlockSymbolBehavior == .emitExtensionBlockSymbols, | ||
outputFormat: .json(pretty: prettyPrint) | ||
) | ||
|
||
if result.exitStatus != .terminated(code: 0) { | ||
let commandline = "\nUsing commandline: \(result.arguments)" | ||
switch result.output { | ||
case .success(let value): | ||
swiftCommandState.observabilityScope.emit(error: "Failed to emit symbol graph for '\(description.module.c99name)': \(String(decoding: value, as: UTF8.self))\(commandline)") | ||
case .failure(let error): | ||
swiftCommandState.observabilityScope.emit(error: "Internal error while emitting symbol graph for '\(description.module.c99name)': \(error)\(commandline)") | ||
// Run the tool once for every library and executable target in the root package. | ||
let modulesGraph = try await buildSystem.getPackageGraph() | ||
for description in buildPlan.buildModules { | ||
guard description.module.type == .library, | ||
modulesGraph.rootPackages[description.package.id] != nil | ||
else { | ||
continue | ||
} | ||
|
||
print("-- Emitting symbol graph for", description.module.name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question: should we be using ObservabilityScope for emitting message to the console? |
||
let result = try symbolGraphExtractor.extractSymbolGraph( | ||
for: description, | ||
outputRedirection: .collect(redirectStderr: true), | ||
outputDirectory: symbolGraphDirectory, | ||
verboseOutput: swiftCommandState.logLevel <= .info | ||
) | ||
|
||
if result.exitStatus != .terminated(code: 0) { | ||
let commandline = "\nUsing commandline: \(result.arguments)" | ||
switch result.output { | ||
case .success(let value): | ||
swiftCommandState.observabilityScope.emit(error: "Failed to emit symbol graph for '\(description.module.c99name)': \(String(decoding: value, as: UTF8.self))\(commandline)") | ||
case .failure(let error): | ||
swiftCommandState.observabilityScope.emit(error: "Internal error while emitting symbol graph for '\(description.module.c99name)': \(error)\(commandline)") | ||
} | ||
} | ||
} | ||
} else { | ||
throw InternalError("Build system \(buildSystem) cannot produce a symbol graph.") | ||
} | ||
|
||
print("Files written to", symbolGraphDirectory.pathString) | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: From my understanding, a build plan is a native build system concept, but I believe the API Diff supports SwiftBuild Build System. Should we be aborting here? Also, should the destinationBuildParameter and
toolsBuildParameters
always be available as "build outputs"?