-
Pl
chevron_right
Christian Hergert: Libpeas and Introspection
news.movim.eu / PlanetGnome • 24 October • 5 minutes
One of the unintended side-effects of writing applications using language bindings is that you inherit the dependencies of the binding.
This made things a bit complicated when
GIRepository
moved from
gobject-introspection-1.0
to
girepository-2.0
as we very much want language bindings to move to the new API.
Where this adds great difficulty on maintainers is in projects like Libpeas which provides plug-in capabilities for GTK application developers across multiple programming languages.
In practice this has allowed applications like Gedit, Rhythmbox, and GNOME Builder to be written in C but load plugins from languages such as Python, Lua, JavaScript, Rust, C, C++, Vala, or any other language capable of producing a
.so
/
.dylib
/
.dll
.
A very early version of Libpeas, years before I took over maintaining the library, had support for GObject Introspection baked in. This allowed really interesting (at the time) tooling to perform dynamic method call dispatching using a sort of proxy object implemented at runtime. Practically nobody is using this feature from what I can tell.
But maintaining ABI being what it is, the support for it has long been part of the
libpeas-1.x
ABI.
A couple years ago I finally released a fresh
libpeas-2.x
ABI which removed a lot of legacy API. With objects implementing
GListModel
and
PleasPluginInfo
becoming a
GObject
, the need for
libpeas-gtk
dwindled. It’s extremely easy for your application to do everything provided by the library. Additionally, I removed the unused GObject Introspection support which means that
libpeas-2.x
no longer needs to link against
gobject-introspection-1.0
(nor
girepository-2.0
).
One area where those are still used is the testsuite. This can complicate testing because we want to make sure that APIs work across language bindings but if the language binding uses a specific version of GObject Introspection that does not align with what the
libpeas
project is using for tests, it will of course lead to runtime disasters.
Such is the case with some language bindings. The Lua LGI project is scarcely maintained right now and still uses
gobject-introspection-1.0
instead of
girepository-2.0
. I submitted patches upstream to port it over, but without an official maintainer well versed in C and language bindings there isn’t anyone to review and say “yes merge this”.
There is a fork now that includes some of the patches I submitted upstream, but the namespace is different so it isn’t a 1:1 replacement.
The PyGObject project has moved to
girepository-2.0
upstream and that caused some breakage with applications in Fedora 42 that were still using the legacy
libpeas-1.x
ABI. For that reason, I believe the older PyGObject was released With Fedora 42.
If you are using
libpeas-2.x
in your application, you have nothing to fear with any of the language runtimes integrated with libpeas. Since libpeas doesn’t link against either introspection libraries, it can’t hurt you. Just make sure your dependencies and language bindings are all in sync and you should be fine.
If you are using
libpeas-1.x
still (2.x was released a little over 2 years ago) then you are in a much worse shape. Language bindings are moving (or have moved) to
girepository-2.0
while libpeas cannot realistically be ported and maintain ABI. Too much is exposed as part of the library itself.
It is imperative that if you want to keep your application working that you are either on
libpeas-2.x
or you’re bundling your application in such a way that you can guarantee your dependencies are all on the same version of GObject Introspection.
Halfway ABI
There exists a sort of “half-way-ABI” that someone could work on with enough motivation which is to break ABI as a sort of
libpeas-1.38
. It would move to
girepository-2.0
and all the ABI side-effects that come with it. Since the introspection support in
libpeas-1.x
is rarely used there should be little side-effects other than recompiling against the new ABI (and the build system transitions that go along with that).
In my experience maintaining the largest application using libpeas (being Builder), that is really a lot more effort than porting your applications to
libpeas-2.x
.
Is my app effected?
So in short, here are a few questions to ask yourself to know if you’re affected by this.
-
Does my application only use embedded plug-ins or plug-ins from shared-modules such as
*.so? If so, then you are all set! - Do I use libpeas-1.x? If no, then great!
- Does my libpeas-1.x project use Python for plug-ins? If yes, port to libpeas-2.x (or alternatively work suggested halfway-ABI for libpeas).
-
Does my libpeas-1.x or libpeas-2.x project use Lua for plug-ins? If yes, make sure all your dependencies are using
gobject-introspection-1.0only. Any use ofgirepository-2.0will end in doom.
Since JavaScript support with
GJS/MozJS
was added in
libpeas-2.x
, if you’re using JavaScript plug-ins you’re already good. GJS recently transitioned to
girepository-2.0
already and continues to integrate well with libpeas. But do make sure your other dependencies have made the transition.
How this could have been avoided?
Without a time machine there are only three options besides what was done and they all create their own painful side-effects for the ecosystem.
- Never break ABI even if your library was a stop gap, never change dependencies, never let dependencies change dependencies, never fix anything.
- When pulling GObject Introspection into the GLib project, rename all symbols to a new namespace so that both libraries may co-exist in process at the same time. Symbol multi-versioning can’t fix overlapping type name registration in GType.
-
Don’t fix any of the glaring issues or inconsistencies when pulling GObject Introspection into GLib. Make
gobject-introspection-1.0map to the same thing thatgirepository-2.0does.
All of those have serious side-effects that are equal to if not worse than the status-quo.
Those that want to “ do nothing ” as maintainers of their applications can really just keep shipping them on Flatpak but with the Runtime pinned to their golden age of choice.
Moral of the story is that ABI’s are hard even when you’re good at it. Doubly so if your library does anything non-trivial.