1
0
Fork
You've already forked puregotk
0
forked from puregotk/puregotk
Autogenerated GTK4+Adwaita bindings for Go leveraging ebitengine/purego
  • Go 100%
Felicitas Pojtinger 6e5c8f15d6 Examples: Add GNOME Builder support where possible
Signed-off-by: Felicitas Pojtinger <felicitas@pojtinger.com>
2026年04月28日 10:42:16 +02:00
docs Examples: Add documentation for mylib-gtk-meson-go, myapp-gnome-meson and myapp-gnome-gomod 2026年01月15日 11:06:45 +01:00
examples Examples: Add GNOME Builder support where possible 2026年04月28日 10:42:16 +02:00
internal GIR: Document where Homebrew and MacPorts store libraries 2026年04月23日 12:45:55 +02:00
pkg GIR: Drop dependency on goimports and track imports in-process instead 2026年04月13日 22:53:19 -07:00
templates GIR: Drop dependency on goimports and track imports in-process instead 2026年04月13日 22:53:19 -07:00
v4 Gen: Re-run script 2026年04月23日 12:51:31 +02:00
copygir.sh Switch copygir.sh script from using Alpine Linux downstream to extracting GIR files to extracting them from the upstream runtime directly 2025年10月22日 09:48:24 +02:00
gen.go GIR: Drop dependency on goimports and track imports in-process instead 2026年04月13日 22:53:19 -07:00
gen.sh GIR: Drop dependency on goimports and track imports in-process instead 2026年04月13日 22:53:19 -07:00
go.mod GIR: Format withgofumpt in-process instead of calling it in gen.sh 2026年04月13日 22:52:51 -07:00
go.sum GIR: Format withgofumpt in-process instead of calling it in gen.sh 2026年04月13日 22:52:51 -07:00
LICENSE initial commit 2023年08月15日 12:50:14 +02:00
README.md README: Use new integer widths in example 2026年03月16日 22:04:35 -07:00

Puregotk

NOTE: This library is currently expiremental and needs thorough testing. Some APIs might be incorrectly exposed

Autogenerated GTK4+Adwaita bindings for Go leveraging purego

Motivation

I created this library because I found that alternative libraries using Cgo had much too slow compilation speed. For my laptop around 15 minutes to build a simple example (without build cache) for gotk3 and also gotk4. Whilst this is maybe not a big problem for development, I found it annoying for CI and package building where you would not want to rely on a cache. Additionally, having Cgo involved means harder cross compilation.

This is not a fault for these libraries as CGo compilation is just inherently slow in Go. In this project I want to test a new approach by levering purego which allows you to load libraries using dlopen without needing cgo.

Compilation speed currently is around 40 seconds for me on basic examples.

Available libraries

Bindings for the following GObject-introspectable libraries are currently generated from the GNOME Flatpak SDK:

If you want to add bindings for another GObject-introspectable library to puregotk, you can either add the GIR file to internal/gir/spec in this repository or generate the bindings in your own external repository (see examples/mylib-gtk-meson-go).

Advantages

No Cgo needed, thus:

  • Easy cross compilation
  • No C toolchain needed
  • Much faster compile times than alternatives like gotk3 & gotk4

Disadvantages

Limitations of this library as compared to the alternatives using cgo:

  • Some APIs are not possible due to purego not currently supporting struct arguments (that are not pointers)

Planned features

In order of priority:

  • General code cleanup
  • Support for OS other than Linux (I only test on Linux currently)
  • GTK 3 support
  • Architectures other than AMD64/ARM64

Basic example

You can find more examples for advanced features, such as GObject subclassing for custom widgets, writing GObject GTK libraries in Go, generating bindings from external GIR files, using Meson and Flatpak, Blueprint files and more in examples

packagemainimport("os""codeberg.org/puregotk/puregotk/v4/gio""codeberg.org/puregotk/puregotk/v4/gtk")funcmain(){app:=gtk.NewApplication("page.codeberg.puregotk.Gtk4Hello",gio.GApplicationFlagsNoneValue)// cleanup, no finalizers are used in this librarydeferapp.Unref()// functions with callback arguments take function pointers// this is for internal re-use of callbacksactcb:=func(_gio.Application){activate(app)}app.ConnectActivate(&actcb)ifcode:=app.Run(int32(len(os.Args)),os.Args);code>0{os.Exit(int(code))}}funcactivate(app*gtk.Application){window:=gtk.NewApplicationWindow(app)window.SetTitle("purego")label:=gtk.NewLabel("Hello, World!")window.SetChild(&label.Widget)// cleanup, no finalizers are used in this librarylabel.Unref()window.SetDefaultSize(500,500)window.Present()}

Save this to a main.go and then build & run with

go run main.go

NOTE: You can also use CGO_ENABLED=0 to build without cgo!

Library loading

Because the GTK libs are loading at runtime (in init), we have to know where your libs are located. The default configuration is a "just works" configuration, we hardcode some paths that are common.

However, for systems such as NixOS or distros that use other paths the following environment variables might help:

  • PUREGOTK_LIB_FOLDER, set this to the root folder where all libs are stored e.g. /some/path/
  • PUREGOTK_LIBNAME_PATH where LIBNAME is the name of the library, e.g. PUREGOTK_GTK_PATH for the file path to GTK e.g. /some/path/libgtk-4.so. You have to do this for all deps, e.g. cairo, pango, etc

See https://codeberg.org/puregotk/puregotk/blob/main/internal/core/core.go for exact implementation details.

Additionally we also have a fallback to pkg-config, but I would say only rely on this as a last effort due to the increased startup time. When packaging code, always make sure that correct paths are used by e.g. using the aforementioned environment variables.

Generating the library

This library is automatically generated by reading GIR files.

To generate the library, run:

./gen.sh

In the root of the project. This needs:

License

MIT

Acknowledgements

  • Purego and the ebitengine team for their great work
  • gotk4 for some GIR type definitions
  • gtk of course