import PackagePlugin import Foundation /// SwiftPM command plugin for manual GIR binding regeneration. /// /// Invoked via `swift package generate-gir-bindings`. Forwards all /// user-provided arguments directly to the `swift-gtk-gen` monorepo CLI, /// defaulting `--output` to the package directory when the caller omits it. /// The generator itself decides what to plan, render, and write from the /// monorepo TOML config passed via `--monorepo-config`. @main struct SwiftGtkGenCommandPlugin: CommandPlugin { /// Runs `swift-gtk-gen` as a subprocess with the caller's arguments. /// /// Stdout and stderr are piped through to the caller. Throws if the /// subprocess exits non-zero. /// /// - Parameters: /// - context: The plugin context providing access to tools and the package directory. /// - arguments: User-provided arguments forwarded to the generator, e.g. /// `--monorepo-config configs/tier1.toml --format-config .swift-format`. func performCommand(context: PluginContext, arguments: [String]) async throws { guard !arguments.isEmpty else { print("Usage: swift package generate-gir-bindings --monorepo-config [--skip-report] [--smoke-target] [--format-config ]") return } let executable = try context.tool(named: "swift-gtk-gen") var procArgs = arguments if !procArgs.contains("--output") { procArgs.append(contentsOf: ["--output", context.package.directoryURL.path()]) } let process = Process() process.executableURL = executable.url process.arguments = procArgs let stdoutPipe = Pipe() let stderrPipe = Pipe() process.standardOutput = stdoutPipe process.standardError = stderrPipe try process.run() process.waitUntilExit() let stdoutData = stdoutPipe.fileHandleForReading.readDataToEndOfFile() let stderrData = stderrPipe.fileHandleForReading.readDataToEndOfFile() if let stdoutStr = String(data: stdoutData, encoding: .utf8), !stdoutStr.isEmpty { print(stdoutStr, terminator: "") } if let stderrStr = String(data: stderrData, encoding: .utf8), !stderrStr.isEmpty { FileHandle.standardError.write(Data(stderrStr.utf8)) } guard process.terminationStatus == 0 else { throw SwiftGtkGenPluginError.generationFailed } } } /// Errors that can occur during command-plugin GIR generation. enum SwiftGtkGenPluginError: Error { /// The `swift-gtk-gen` subprocess exited non-zero. case generationFailed } extension SwiftGtkGenPluginError: CustomStringConvertible { /// A human-readable description of the error. var description: String { switch self { case .generationFailed: return "swift-gtk-gen generation failed; see output above for details." } } }