| regression | ||
| scripts | ||
| Sources | ||
| Tests | ||
| .gitignore | ||
| .swift-format | ||
| LICENSE | ||
| Package.resolved | ||
| Package.swift | ||
| README.md | ||
gobject-generator - GIR-to-Swift Binding Generator
Reads GObject Introspection (.gir) XML files and produces a Swift monorepo of
low-level wrapper packages for GTK and its dependency stack (GLib, GObject, GIO,
Pango, GDK, GSK, GTK, Adwaita, Soup, GStreamer, and more).
A single invocation generates every configured package - Swift sources, C bridge
targets, re-export umbrellas, and the root Package.swift - as a buildable
SwiftPM workspace.
Usage
generator --monorepo-config config.toml --output ./Generated
Command-line arguments
| Argument | Description |
|---|---|
--monorepo-config PATH |
Required. Path to the monorepo TOML configuration file. |
--output DIR |
Root output directory for the generated monorepo (default: .). |
--skip-report |
Write per-module skip reports (skip-reports/<Module>.json) and a coverage-summary.json to the output directory. |
--smoke-target |
Add a SmokeTests test target to the generated Package.swift, depending on every generated module. |
--format-config PATH |
Path to a .swift-format configuration file used to format generated output. |
--help, -h |
Print usage information and exit. |
Monorepo configuration file
The --monorepo-config argument points to a TOML file describing every package
to generate. Each [packages.<Name>] section declares a .gir file to process
and optional per-package overrides.
# Top-level output directory (can be overridden by --output on the command line).
output_dir = "."
# Each [packages.<Name>] section becomes one Swift module.
# Packages are listed in dependency order (leaf dependencies first).
[packages.GLib]
gir = "/usr/share/gir-1.0/GLib-2.0.gir"
[packages.GObject]
gir = "/usr/share/gir-1.0/GObject-2.0.gir"
concurrency = "mainActor"
[packages.Gtk]
gir = "/usr/share/gir-1.0/Gtk-4.0.gir"
# Per-type overrides are placed under [packages.<Name>.object.<TypeName>].
[packages.Gtk.object.Gtk.Widget]
status = "generate" # "generate" | "manual" | "ignore"
finalType = true
concurrency = "mainActor" # "mainActor" | "sendable" | "none"
version = "4.0"
cfgCondition = "os(macOS)" # #if compilation condition
[packages.Gtk.object.Gtk.Builder]
generateBuilder = true
| Per-package key | Type | Description |
|---|---|---|
gir |
string | Required. Path to the .gir file to process. |
concurrency |
string | Default concurrency model for all types in this package: "mainActor", "sendable", or "none". |
Per-type override (object.<TypeName>) |
Type | Description |
|---|---|---|
status |
string | Override generation status: "generate", "manual", or "ignore". |
finalType |
bool | Mark the generated class as final. |
concurrency |
string | Per-type concurrency model (same values as the package-level key). |
version |
string | Minimum version; type is only generated when targeting this version or later. |
cfgCondition |
string | An #if compilation condition wrapping the generated code. |
generateBuilder |
bool | Emit a builder-pattern struct for constructing this type. |
Output structure
<output-dir>/
├── Package.swift
├── Sources/
│ ├── CGLib/
│ │ ├── CGLib.h # C umbrella header
│ │ └── module.modulemap # Clang module map (pkg-config driven)
│ ├── GLib/
│ │ ├── GLib.swift # Re-export umbrella (@_exported import)
│ │ └── Generated/
│ │ ├── Array.swift
│ │ ├── Error.swift
│ │ └── ...
│ ├── CGObject/
│ │ └── ...
│ ├── GObject/
│ │ ├── GObject.swift
│ │ └── Generated/
│ │ └── ...
│ ├── CGtk/
│ │ └── ...
│ └── Gtk/
│ ├── Gtk.swift
│ └── Generated/
│ └── ...
Package.swift- SwiftPM manifest with a.systemLibrarytarget per C bridge and a.targetper Swift wrapper module. Dependencies between modules are resolved automatically from the GIR<include>graph.Sources/C<Module>/- One Clang module map and umbrella header per generated Swift module, wired to the native library viapkgConfig.Sources/<Module>/Generated/- One.swiftfile per generated type (class, protocol, enum, option set, callback typealias, free function).Sources/<Module>/<Module>.swift- A re-export umbrella importing every transitive dependency, so consumers only need a singleimport Gtk.
User-defined test targets
The generated Package.swift includes marker comments that preserve custom
targets across regenerations:
// === USER TARGETS - preserved across generations ===
// BEGIN_USER_TARGETS
// END_USER_TARGETS
Add any custom target() entries (test targets, executables, plugins) between
these markers. The generator splices the existing content back into the freshly
generated Package.swift on every run. The markers must appear on their own
lines and must not be nested.
Example:
// BEGIN_USER_TARGETS
.testTarget(name: "MyIntegrationTests", dependencies: ["GLib", "Gtk"]),
// END_USER_TARGETS
Example
Input: config.toml
output_dir = "."
[packages.GLib]
gir = "/usr/share/gir-1.0/GLib-2.0.gir"
[packages.GObject]
gir = "/usr/share/gir-1.0/GObject-2.0.gir"
[packages.Gtk]
gir = "/usr/share/gir-1.0/Gtk-4.0.gir"
Command
generator --monorepo-config config.toml --output ./gen
Generated output
./gen/
├── Package.swift
├── Sources/
│ ├── CGLib/
│ │ ├── CGLib.h
│ │ └── module.modulemap
│ ├── GLib/
│ │ ├── GLib.swift
│ │ └── Generated/
│ │ ├── Array.swift
│ │ ├── Error.swift
│ │ ├── ...
│ │ └── Variant.swift
│ ├── CGObject/
│ │ ├── CGObject.h
│ │ └── module.modulemap
│ ├── GObject/
│ │ ├── GObject.swift
│ │ └── Generated/
│ │ ├── Binding.swift
│ │ ├── Object.swift
│ │ └── ...
│ ├── CGtk/
│ │ ├── CGtk.h
│ │ └── module.modulemap
│ └── Gtk/
│ ├── Gtk.swift
│ └── Generated/
│ ├── Application.swift
│ ├── Widget.swift
│ ├── Window.swift
│ └── ...
Generated code sample
// Gtk/Generated/Widget.swift
/// The base class for all widgets.
public final class Widget: GObject.InitiallyUnowned {
let pointer: UnsafeMutableRawPointer
init(takingOwnership pointer: UnsafeMutableRawPointer) {
self.pointer = pointer
}
init(retaining pointer: UnsafeMutableRawPointer) {
g_object_ref(pointer)
self.pointer = pointer
}
deinit {
g_object_unref(pointer)
}
public func show() {
gtk_widget_show(pointer)
}
public var visible: Bool {
get { gtk_widget_get_visible(pointer) != 0 }
set { gtk_widget_set_visible(pointer, newValue ? 1 : 0) }
}
}
Building for development
# Clone and build the generator
git clone <repo-url>
cd gobject-generator
swift build
# Run the test suite (unit + integration)
swift test
# Generate bindings from a config
swift run generator --monorepo-config config.toml --output ./out
# Format generated output (requires swift-format)
swift run generator --monorepo-config config.toml --format-config .swift-format
License
This project is licensed under the MIT License. See LICENSE for the full text.