1
0
Fork 0
gobject-generator/Sources/SwiftGtkGenBuildPlugin/BuildToolPlugin.swift
Brendan Szymanski 1330f2bd25 Initial commit: SwiftGtkGen GIR-to-Swift binding generator
Extracted from gtk-swift monorepo. Previous history
contains 38 commits across the full Phase 1 development
including GIR XML parsing, IR model, analysis engine,
code generation, CLI, plugins, and documentation.
2026-07-01 03:27:41 -04:00

75 lines
2.9 KiB
Swift

import PackagePlugin
import Foundation
/// SwiftPM build tool plugin that automatically generates Swift GIR bindings.
///
/// Inspects each target for a `Config.swift` file and `.gir` files, then
/// invokes the `swift-gtk-gen` executable to produce Swift source before compilation.
/// Targets without a config or GIR files are silently skipped.
@main
struct SwiftGtkGenBuildPlugin: BuildToolPlugin {
/// Creates build commands for GIR code generation for the given target.
///
/// Returns a single `.buildCommand` that runs `swift-gtk-gen` with the target's
/// config and GIR files as inputs. If the target has no `Config.swift` or
/// no `.gir` files, returns an empty array.
///
/// - Parameters:
/// - context: The plugin context providing access to tools and work directories.
/// - target: The target to generate bindings for.
/// - Returns: An array of build commands (empty if no GIR files present).
func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
let targetDir = target.directoryURL
let configURL = targetDir.appending(path: "Config.swift")
guard FileManager.default.fileExists(atPath: configURL.path()) else {
return []
}
let executable = try context.tool(named: "swift-gtk-gen")
let girFiles = findGIRFiles(in: targetDir)
guard !girFiles.isEmpty else { return [] }
let outputDir = context.pluginWorkDirectoryURL
return [
.buildCommand(
displayName: "Generating \(target.name) GIR bindings...",
executable: executable.url,
arguments: [
"--config", configURL.path(),
"--library", target.name,
"--version", "4.0",
"--output", outputDir.appending(path: target.name).path(),
],
inputFiles: [configURL] + girFiles,
outputFiles: [
outputDir.appending(path: "\(target.name)/Generated.swift")
]
)
]
}
/// Recursively finds all `.gir` files in the given directory.
///
/// Uses a directory enumerator to walk the file tree and collect URLs
/// whose path extension is `"gir"`.
///
/// - Parameter directory: The root directory to search.
/// - Returns: An array of URLs pointing to discovered `.gir` files.
private func findGIRFiles(in directory: URL) -> [URL] {
guard let enumerator = FileManager.default.enumerator(
at: directory, includingPropertiesForKeys: [.isRegularFileKey]
) else {
return []
}
var girFiles: [URL] = []
for case let fileURL as URL in enumerator {
if fileURL.pathExtension == "gir" {
girFiles.append(fileURL)
}
}
return girFiles
}
}