Skip to content

Commit 0284c97

Browse files
committed
Build documentation for targets in reverse dependency order
rdar://116698361
1 parent 5d7ff6d commit 0284c97

File tree

1 file changed

+50
-15
lines changed

1 file changed

+50
-15
lines changed

Plugins/Swift-DocC Convert/SwiftDocCConvert.swift

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This source file is part of the Swift.org open source project
22
//
3-
// Copyright (c) 2022 Apple Inc. and the Swift project authors
3+
// Copyright (c) 2022-2024 Apple Inc. and the Swift project authors
44
// Licensed under Apache License v2.0 with Runtime Library Exception
55
//
66
// See https://swift.org/LICENSE.txt for license information
@@ -56,14 +56,9 @@ import PackagePlugin
5656
let snippetExtractor: SnippetExtractor? = nil
5757
#endif
5858

59-
60-
// Iterate over the Swift source module targets we were given.
61-
for (index, target) in swiftSourceModuleTargets.enumerated() {
62-
if index != 0 {
63-
// Emit a line break if this is not the first target being built.
64-
print()
65-
}
66-
59+
// An inner function that defines the work to build documentation for a given target.
60+
func performBuildTask(_ task: DocumentationBuildGraph<SwiftSourceModuleTarget>.Task) throws {
61+
let target = task.target
6762
print("Generating documentation for '\(target.name)'...")
6863

6964
let symbolGraphs = try packageManager.doccSymbolGraphs(
@@ -88,12 +83,11 @@ import PackagePlugin
8883
// We're building multiple targets, just throw a warning for this
8984
// one target that does not produce documentation.
9085
Diagnostics.warning(message)
91-
continue
9286
} else {
9387
// This is the only target being built so throw an error
9488
Diagnostics.error(message)
95-
return
9689
}
90+
return
9791
}
9892
}
9993

@@ -138,15 +132,56 @@ import PackagePlugin
138132
let describedOutputPath = doccArguments.outputPath ?? "unknown location"
139133
print("Generated DocC archive at '\(describedOutputPath)'")
140134
} else {
141-
Diagnostics.error("""
142-
'docc convert' invocation failed with a nonzero exit code: '\(process.terminationStatus)'
143-
"""
144-
)
135+
Diagnostics.error("'docc convert' invocation failed with a nonzero exit code: '\(process.terminationStatus)'")
145136
}
137+
146138
}
147139

140+
// Create a build graph for all the documentation build tasks.
141+
let buildGraph = DocumentationBuildGraph(targets: swiftSourceModuleTargets)
142+
// Create a serial queue to perform each documentation build task
143+
let queue = OperationQueue()
144+
queue.maxConcurrentOperationCount = 1
145+
146+
// Operations can't raise errors. Instead we catch the error from 'performBuildTask(_:)'
147+
// and cancel the remaining tasks.
148+
let errorLock = NSLock()
149+
var caughtError: Error?
150+
151+
let operations = buildGraph.makeOperations { [performBuildTask] task in
152+
do {
153+
try performBuildTask(task)
154+
} catch {
155+
errorLock.withLock {
156+
caughtError = error
157+
queue.cancelAllOperations()
158+
}
159+
}
160+
}
161+
// If any of the build tasks raised an error. Rethrow that error.
162+
if let caughtError {
163+
throw caughtError
164+
}
165+
166+
// Run all the documentation build tasks in reverse dependency order (dependencies before dependents).
167+
queue.addOperations(operations, waitUntilFinished: true)
168+
148169
if swiftSourceModuleTargets.count > 1 {
149170
print("\nMultiple DocC archives generated at '\(context.pluginWorkDirectory.string)'")
150171
}
151172
}
152173
}
174+
175+
// We add the conformance here so that 'DocumentationBuildGraphTarget' doesn't need to know about 'SwiftSourceModuleTarget' or import 'PackagePlugin'.
176+
extension SwiftSourceModuleTarget: DocumentationBuildGraphTarget {
177+
var dependencyIDs: [String] {
178+
// List all the target dependencies in a flat list.
179+
dependencies.flatMap {
180+
switch $0 {
181+
case .target(let target): return [target.id]
182+
case .product(let product): return product.targets.map { $0.id }
183+
@unknown default: return []
184+
}
185+
}
186+
}
187+
}

0 commit comments

Comments
 (0)