Skip to content

Commit 04fceed

Browse files
authored
Merge pull request #709 from nkcsgexi/prebuilt-dump-dependencies
PrebuiltModuleGen: teach the tool to dump a .dot file for module dependency visualization
2 parents 3f5f55a + 7da6a5e commit 04fceed

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

Sources/SwiftDriver/Jobs/PrebuiltModulesJob.swift

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,57 @@ public struct SDKPrebuiltModuleInputsCollector {
239239
}
240240
}
241241

242+
extension InterModuleDependencyGraph {
243+
func dumpDotGraph(_ path: AbsolutePath, _ includingPCM: Bool) throws {
244+
func isPCM(_ dep: ModuleDependencyId) -> Bool {
245+
switch dep {
246+
case .clang:
247+
return true
248+
default:
249+
return false
250+
}
251+
}
252+
func dumpModuleName(_ stream: WritableByteStream, _ dep: ModuleDependencyId) {
253+
switch dep {
254+
case .swift(let name):
255+
stream <<< "\"\(name).swiftmodule\""
256+
case .clang(let name):
257+
stream <<< "\"\(name).pcm\""
258+
default:
259+
break
260+
}
261+
}
262+
try localFileSystem.writeFileContents(path) {Stream in
263+
Stream <<< "digraph {\n"
264+
for key in modules.keys {
265+
switch key {
266+
case .swift(let name):
267+
if name == mainModuleName {
268+
break
269+
}
270+
fallthrough
271+
case .clang:
272+
if !includingPCM && isPCM(key) {
273+
break
274+
}
275+
modules[key]!.directDependencies?.forEach { dep in
276+
if !includingPCM && isPCM(dep) {
277+
return
278+
}
279+
dumpModuleName(Stream, key)
280+
Stream <<< " -> "
281+
dumpModuleName(Stream, dep)
282+
Stream <<< ";\n"
283+
}
284+
default:
285+
break
286+
}
287+
}
288+
Stream <<< "}\n"
289+
}
290+
}
291+
}
292+
242293
extension Driver {
243294

244295
private mutating func generateSingleModuleBuildingJob(_ moduleName: String, _ prebuiltModuleDir: AbsolutePath,
@@ -285,12 +336,16 @@ extension Driver {
285336

286337
public mutating func generatePrebuitModuleGenerationJobs(with inputMap: [String: [PrebuiltModuleInput]],
287338
into prebuiltModuleDir: AbsolutePath,
288-
exhaustive: Bool) throws -> ([Job], [Job]) {
339+
exhaustive: Bool,
340+
dotGraphPath: AbsolutePath? = nil) throws -> ([Job], [Job]) {
289341
assert(sdkPath != nil)
290342
// Run the dependency scanner and update the dependency oracle with the results
291343
// We only need Swift dependencies here, so we don't need to invoke gatherModuleDependencies,
292344
// which also resolves versioned clang modules.
293345
let dependencyGraph = try performDependencyScan()
346+
if let dotGraphPath = dotGraphPath {
347+
try dependencyGraph.dumpDotGraph(dotGraphPath, false)
348+
}
294349
var jobs: [Job] = []
295350
var danglingJobs: [Job] = []
296351
var inputCount = 0

Sources/swift-build-sdk-interfaces/main.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ func getArgument(_ flag: String) -> String? {
3232
return nil
3333
}
3434

35+
func getArgumentAsPath(_ flag: String) throws -> AbsolutePath? {
36+
if let raw = getArgument(flag) {
37+
return try VirtualPath(path: raw).absolutePath
38+
}
39+
return nil
40+
}
41+
3542
guard let rawOutputDir = getArgument("-o") else {
3643
diagnosticsEngine.emit(.error("need to specify -o"))
3744
exit(1)
@@ -119,7 +126,8 @@ do {
119126
diagnosticsEngine: diagnosticsEngine,
120127
executor: executor,
121128
compilerExecutableDir: swiftcPath.parentDirectory)
122-
let (jobs, danglingJobs) = try driver.generatePrebuitModuleGenerationJobs(with: inputMap, into: outputDir, exhaustive: !coreMode)
129+
let (jobs, danglingJobs) = try driver.generatePrebuitModuleGenerationJobs(with: inputMap,
130+
into: outputDir, exhaustive: !coreMode, dotGraphPath: getArgumentAsPath("-dot-graph-path"))
123131
if verbose {
124132
Driver.stdErrQueue.sync {
125133
stderrStream <<< "job count: \(jobs.count + danglingJobs.count)\n"

0 commit comments

Comments
 (0)