performCommand( context: PluginContext, targets: [Target], arguments: [String] ) async throws { // We'll be creating commands that invoke `docc`, so start by locating it. let doccTool = try context.tool(named: "docc") let outputDir = context.pluginWorkDirectory.appending("Outputs") for target in targets { guard let target = target as? SourceModuleTarget else { continue } let doccCatalog = target.sourceFiles.first { $0.path.extension == "docc" } let symbolGraphInfo = try await packageManager.getSymbolGraph(for: target, options: .init( minimumAccessLevel: .public, includeSynthesized: false, includeSPI: false)) let doccExec = URL(fileURLWithPath: doccTool.path.string) var doccArgs = ["convert"] if let doccCatalog = doccCatalog { doccArgs += ["\(doccCatalog.path)"] } doccArgs += [ "--fallback-display-name", target.name, "--fallback-bundle-identifier", target.name, "--fallback-bundle-version", "0", "--additional-symbol-graph-dir", "\(symbolGraphInfo.directoryPath)", "--output-dir", "\(outputDir)", ] let process = try Process.run(doccExec, arguments: doccArgs) process.waitUntilExit() // Check whether the subprocess invocation was successful. if process.terminationReason == .exit && process.terminationStatus == 0 { print("Generated documentation at \(outputDir).") } else { let problem = "\(process.terminationReason):\(process.terminationStatus)" Diagnostics.error("docc invocation failed: \(problem)") } } } }