Skip to content

Commit 777ff86

Browse files
committed
Rework the SymbolGraphExtract so it's more suitable for being called in the context of plugins.
This includes parameterizing the output that's printed and the output path, and applying the extractor to a target at a time and not always to all the targets in a package. The original behavior for the `dump-symbol-graph` command is unmodified, but some of the specifics are hoisted into the DumpSymbolGraph command implementation rather than in the reusable SymbolGraphExtract type.
1 parent bf733be commit 777ff86

File tree

2 files changed

+74
-80
lines changed

2 files changed

+74
-80
lines changed

Sources/Commands/SwiftPackageTool.swift

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ extension SwiftPackageTool {
531531
struct DumpSymbolGraph: SwiftCommand {
532532
static let configuration = CommandConfiguration(
533533
abstract: "Dump Symbol Graph")
534-
static let defaultMinimumAccessLevel = AccessLevel.public
534+
static let defaultMinimumAccessLevel = SymbolGraphExtract.AccessLevel.public
535535

536536
@OptionGroup(_hiddenFromHelp: true)
537537
var swiftOptions: SwiftToolOptions
@@ -542,7 +542,7 @@ extension SwiftPackageTool {
542542
@Flag(help: "Skip members inherited through classes or default implementations.")
543543
var skipSynthesizedMembers = false
544544

545-
@Option(help: "Include symbols with this access level or more. Possible values: \(AccessLevel.allValueStrings.joined(separator: " | "))")
545+
@Option(help: "Include symbols with this access level or more. Possible values: \(SymbolGraphExtract.AccessLevel.allValueStrings.joined(separator: " | "))")
546546
var minimumAccessLevel = defaultMinimumAccessLevel
547547

548548
@Flag(help: "Skip emitting doc comments for members inherited through classes or default implementations.")
@@ -552,23 +552,35 @@ extension SwiftPackageTool {
552552
var includeSPISymbols = false
553553

554554
func run(_ swiftTool: SwiftTool) throws {
555-
let symbolGraphExtract = try SymbolGraphExtract(
556-
tool: swiftTool.getToolchain().getSymbolGraphExtract())
557-
558555
// Build the current package.
559556
//
560557
// We turn build manifest caching off because we need the build plan.
561558
let buildOp = try swiftTool.createBuildOperation(cacheBuildManifest: false)
562559
try buildOp.build()
563560

564-
try symbolGraphExtract.dumpSymbolGraph(
565-
buildPlan: buildOp.buildPlan!,
566-
prettyPrint: prettyPrint,
567-
skipSynthesisedMembers: skipSynthesizedMembers,
561+
// Configure the symbol graph extractor.
562+
let symbolGraphExtractor = try SymbolGraphExtract(
563+
tool: swiftTool.getToolchain().getSymbolGraphExtract(),
564+
skipSynthesizedMembers: skipSynthesizedMembers,
568565
minimumAccessLevel: minimumAccessLevel,
569566
skipInheritedDocs: skipInheritedDocs,
570-
includeSPISymbols: includeSPISymbols
571-
)
567+
includeSPISymbols: includeSPISymbols,
568+
prettyPrintOutputJSON: prettyPrint)
569+
570+
// Run the tool once for every library and executable target in the root package.
571+
let buildPlan = buildOp.buildPlan!
572+
let symbolGraphDirectory = buildPlan.buildParameters.dataPath.appending(component: "symbolgraph")
573+
let targets = buildPlan.graph.rootPackages.flatMap{ $0.targets }.filter{ $0.type == .library || $0.type == .executable }
574+
for target in targets {
575+
print("-- Emitting symbol graph for", target.name)
576+
try symbolGraphExtractor.extractSymbolGraph(
577+
target: target,
578+
buildPlan: buildPlan,
579+
verbose: verbosity != .concise,
580+
outputDirectory: symbolGraphDirectory)
581+
}
582+
583+
print("Files written to", symbolGraphDirectory.pathString)
572584
}
573585
}
574586

Lines changed: 51 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,79 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
4+
Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See http://swift.org/LICENSE.txt for license information
88
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
import Foundation
12-
13-
import TSCBasic
14-
import TSCUtility
15-
16-
import SPMBuildCore
11+
import ArgumentParser
1712
import Build
1813
import PackageGraph
1914
import PackageModel
20-
import SourceControl
21-
import Workspace
22-
import ArgumentParser
15+
import SPMBuildCore
16+
import TSCBasic
17+
import TSCUtility
2318

2419
/// A wrapper for swift-symbolgraph-extract tool.
2520
public struct SymbolGraphExtract {
2621
let tool: AbsolutePath
27-
28-
init(tool: AbsolutePath) {
29-
self.tool = tool
22+
var skipSynthesizedMembers: Bool = false
23+
var minimumAccessLevel: AccessLevel = .public
24+
var skipInheritedDocs: Bool = false
25+
var includeSPISymbols: Bool = false
26+
var prettyPrintOutputJSON: Bool = false
27+
28+
/// Access control levels.
29+
public enum AccessLevel: String, RawRepresentable, CustomStringConvertible, CaseIterable, ExpressibleByArgument {
30+
// The cases reflect those found in `include/swift/AST/AttrKind.h` of the swift compiler (at commit 03f55d7bb4204ca54841218eb7cc175ae798e3bd)
31+
case `private`, `fileprivate`, `internal`, `public`, `open`
32+
33+
public var description: String { rawValue }
3034
}
3135

32-
public func dumpSymbolGraph(
36+
/// Creates a symbol graph for `target` in `outputDirectory` using the build information from `buildPlan`. The `outputDirection` determines how the output from the tool subprocess is handled, and `verbosity` specifies how much console output to ask the tool to emit.
37+
public func extractSymbolGraph(
38+
target: ResolvedTarget,
3339
buildPlan: BuildPlan,
34-
prettyPrint: Bool,
35-
skipSynthesisedMembers: Bool,
36-
minimumAccessLevel: AccessLevel,
37-
skipInheritedDocs: Bool,
38-
includeSPISymbols: Bool
40+
outputRedirection: Process.OutputRedirection = .none,
41+
verbose: Bool,
42+
outputDirectory: AbsolutePath
3943
) throws {
4044
let buildParameters = buildPlan.buildParameters
41-
let symbolGraphDirectory = buildPlan.buildParameters.symbolGraph
42-
try localFileSystem.createDirectory(symbolGraphDirectory, recursive: true)
43-
44-
// Run the tool for each target in the root package.
45-
let targets = buildPlan.graph.rootPackages.flatMap{ $0.targets }.filter{ $0.type == .library || $0.type == .executable }
46-
for target in targets {
47-
var args = [String]()
48-
args += ["-module-name", target.c99name]
49-
args += try buildParameters.targetTripleArgs(for: target)
50-
51-
args += buildPlan.createAPIToolCommonArgs(includeLibrarySearchPaths: true)
52-
args += ["-module-cache-path", buildParameters.moduleCache.pathString]
53-
54-
args += ["-output-dir", symbolGraphDirectory.pathString]
55-
56-
if prettyPrint { args.append("-pretty-print") }
57-
if skipSynthesisedMembers { args.append("-skip-synthesized-members") }
58-
if minimumAccessLevel != SwiftPackageTool.DumpSymbolGraph.defaultMinimumAccessLevel {
59-
args += ["-minimum-access-level", minimumAccessLevel.rawValue]
60-
}
61-
if skipInheritedDocs { args.append("-skip-inherited-docs") }
62-
if includeSPISymbols { args.append("-include-spi-symbols") }
63-
64-
print("-- Emitting symbol graph for", target.name)
65-
try runTool(args)
45+
try localFileSystem.createDirectory(outputDirectory, recursive: true)
46+
47+
// Construct arguments for extracting symbols for a single target.
48+
var commandLine = [self.tool.pathString]
49+
commandLine += ["-module-name", target.c99name]
50+
commandLine += try buildParameters.targetTripleArgs(for: target)
51+
commandLine += buildPlan.createAPIToolCommonArgs(includeLibrarySearchPaths: true)
52+
commandLine += ["-module-cache-path", buildParameters.moduleCache.pathString]
53+
if verbose {
54+
commandLine += ["-v"]
6655
}
67-
print("Files written to", symbolGraphDirectory.pathString)
68-
}
56+
commandLine += ["-minimum-access-level", minimumAccessLevel.rawValue]
57+
if skipSynthesizedMembers {
58+
commandLine += ["-skip-synthesized-members"]
59+
}
60+
if skipInheritedDocs {
61+
commandLine += ["-skip-inherited-docs"]
62+
}
63+
if includeSPISymbols {
64+
commandLine += ["-include-spi-symbols"]
65+
}
66+
if prettyPrintOutputJSON {
67+
commandLine += ["-pretty-print"]
68+
}
69+
commandLine += ["-output-dir", outputDirectory.pathString]
6970

70-
func runTool(_ args: [String]) throws {
71-
let arguments = [tool.pathString] + args
71+
// Run the extraction.
7272
let process = Process(
73-
arguments: arguments,
74-
outputRedirection: .none,
75-
verbose: verbosity != .concise
76-
)
73+
arguments: commandLine,
74+
outputRedirection: outputRedirection,
75+
verbose: verbose)
7776
try process.launch()
7877
try process.waitUntilExit()
7978
}
8079
}
81-
82-
/// Access control levels.
83-
public enum AccessLevel: String, RawRepresentable, CustomStringConvertible, CaseIterable {
84-
// The cases reflect those found in `include/swift/AST/AttrKind.h` of the swift compiler (at commit 03f55d7bb4204ca54841218eb7cc175ae798e3bd)
85-
case `private`, `fileprivate`, `internal`, `public`, `open`
86-
87-
public var description: String { rawValue }
88-
}
89-
90-
extension AccessLevel: ExpressibleByArgument {}
91-
92-
extension BuildParameters {
93-
/// The directory containing artifacts generated by the symbolgraph-extract tool.
94-
var symbolGraph: AbsolutePath {
95-
dataPath.appending(component: "symbolgraph")
96-
}
97-
}

0 commit comments

Comments
 (0)