During the last couple of months I’ve been learning the Meson build system. Since my personal interests in Open Source Software are around GLib and GStreamer, and they both have Meson and Autotools build systems in parallel, I’ve set as personal goal to list (and try to fix) blocker bugs preventing from switching them to Meson-only. Note that I’m neither GLib nor GStreamer maintainer, so it’s not my call whether or not they will drop Autotools.
GLIB
I opened bug #790954, a meta-bug depending on all the bugs related to meson I’ve found and are bad enough that we cannot drop Autotools unless we fix them first. Amount those bugs, I’ve been personally working on those:
Bug 788773 – meson does not install correct pc files
pkg-config files for glib/gobject/gio are currently generated from a .pc.in template but some flags (notably -pthread) are hidden internally in Meson and cannot be written in the .pc file. To fix that bug I had to use Meson’s pkg-config generator which has access to those internal compiler flags. For example the -pthread flag is hidden behind the dependency(‘threads’) object in a meson.build file. Unfortunately such object cannot be passed to the pkg-config generator, so I opened a pull request making that generator smarter:
- When generating a pc file for a library, it automatically take all dependencies and link_with values from that library and add them into the Libs.private and Requires.private fields.
- Extra dependencies (such as ‘threads’) can be added explicitly if needed. One common case is explicitly adding a public dependency that the generator would have added in private otherwise.
Bug 786796 – gtk-doc build fails with meson
Pretty easy one: gobject’s API documentation needs to pass an extra header file when compiling gtkdoc-scangobj from a non standard location. I made a patch to have include_directories argument to gnome.gtkdoc() method and use it in glib.
Bug 790837 – Meson: missing many configure options
Compared to Autotools’ configure, glib’s meson build system was missing many build options. Also existing options were not following the GNOME guideline. tl;dr: we want foo_bar instead of enable-foo-bar, and we want to avoid automatic options as much as possible.
Now configure options are on par with Autotools, except for the missing –with-thread which has a patch pending on bug #784995.
GStreamer
Both static and shared library
For GStreamer static builds are important. The number of shared libraries an Android application can link to is limited, and dlopen of plugins is forbidden on IOS (if I understood correctly). On those platforms GStreamer is built as one big shared library that statically link all its dependencies (e.g. glib).
Autotools is capable of generating both static and shared libraries and compile C files only once. Doing so with Meson is possible but requires unnecessary extra work. I created a pull request that adds both_library() method to meson, and add a global project option that turns all library() calls to build both shared and static.
Static build of gio modules
This one is not directly related to Meson, but while working on static builds, I’ve noticed that GStreamer patched glib-networking to be able to static build them. Their patch never made it upstream and it has one big downside: it needs to be built twice for static and dynamic. GStreamer itself recently fixed their plugins ABI to be able to do a single compile and produce both shared and static libraries.
The crux is you cannot have the same symbol defined in every plugin. Currently GIO modules must all define g_io_module_load/unload/query() symbols which would clash if you try to static link more than one GIO module. I wrote patches for gio and glib-networking to rename those symbols to be unique. The symbol name is derived from the shared module filename. For example when gio loads libgiognutls.so extension it will remove “libgio” prefix and “.so” suffix to get “gnutls” plugin name. Then lookup for g_io_gnutls_load/unload/query() symbols instead (and fallback to old names if not found).
The second difficulty is GIO plugins uses G_DEFINE_DYNAMIC_TYPE which needs a GTypeModule to be able to create its GType. When those plugins are static linked we don’t have any GTypeModule object. I made a patch to allow passing NULL in that case to turn a G_DEFINE_DYNAMIC_TYPE into a static GType.
Bug 733067 – cerbero: support python3
Meson being python3-only and Cerbero python2-only, if we start building meson projects in cerbero it means we require installing both pythons too. It also adds problems with PYTHONPATH environment variable because it cannot differentiate between 2 and 3 (seriously why is there no PYTHONPATH3?).
I ran 2to3 script against the whole cerbero codebase and then fixed a few remaining bugs manually. All in all it was pretty easy, the most difficult part is to actually test all build variants (linux, osx, windows, cross-android, cross-windows). it’s waiting for 1.14 to be released before merging this into master.
Bug 789316 – Add Meson support in cerbero
Cerbero already had a recipe to build meson and ninja but they were broken. I made patches to fix that and also add the needed code to be able to build recipes using meson. It also makes use of meson directly to build gst-transcoder instead of the wrapper configure and makefile it ships. Later more recipes will be able to be converted to Meson (e.g. glib). Blocking on the python3 port of cerbero.
Choose between static or shared library
One use case Olivier Crête described on Meson issue #2765 is he wants to make the smallest possible build of a GStreamer application, for IoT. That means static link everything into the executable (e.g. GStreamer, glib) but dynamic link on a few libraries provided by the platform (e.g. glibc, openssl).
With Autotools he was doing that using .la files: Libraries built inside cerbero has a “.la” file, and libraries provided by the platform don’t. Autotools has a mode to static link the former and dynamic link the latter, meson don’t.
I think the fundamental question in meson is what to do when a dependency can be provided by both a static and a shared library. Currently meson takes the decision for you and always use the shared library, unless you explicitly set static: true when you declare your dependency, with no project-wide switch.
In this pull request I fixed this by added 2 global options:
- default_link: Tells whether we prefer static or shared when both are available.
- static_paths: List of path prefixes where it is allowed to use static
libraries. By default it has “/” which means all paths are allowed. It can be set to the path where cerbero built GStreamer (e.g. /home/…) and it will static link only them, using shared library from /usr/lib for libraries not built within cerbero.
Conclusion
There is a long road ahead before getting meson build system on par with Autotools for GLib and GStreamer. But bugs and missing features are relatively easy to fix. Meson code base is easy and pleasant to hack, unlike m4 macros I’ve never understood in the past 10 years I’ve been writing Autotools projects.
I think droping Autotools from GLib is a key milestone. If we can achieve that, it proves that all weird use-cases people has been relying on can be done with Meson.
I’ve been working on this on my personal time and on Collabora’s “2h/week for personal projects” policy. I’ll continue working on that goal when possible.