DEV Community

Gary Kramlich
Gary Kramlich

Posted on • Originally published at patreon.com

Build Systems or How We Chose Meson

This article was originally posted on Patreon and has been brought over here to get all of the Pidgin Development/History posts into one single place.

Since the early days of Gaim we used autotools, that is autoconf, automake, and friends; as our build system.

There have always been a number of issues with autotools, but the worst is probably the combination of m4, shell, make, and other esoteric knowledge about compiling software and the libraries you were compiling against.

Determining whether or not the development files for a library were installed was an absolute nightmare until pkg-config was created. pkg-config created a standard method for determining if the development libraries were installed, but there are still some libraries today that refuse to support it. This is tragically hilarious as the pkg-config file is like a 10 line text file with some values from the build.

These issues aside, most people found a way to make them work because there really weren't a whole lot of options at the time. However, autotools required a unix like shell as well. This meant you needed to use something like Cygwin to be able to build an autotools project on Windows. This also mean that you had a hard run-time dependency on Cygwin as well which wasn't always desirable.

To avoid the Cygwin run-time dependency in Gaim/Pidgin we ended up layering in another build system in the project. You read that right. We created Makefile.mingw files everywhere to basically have a statically defined build for Windows. As you might have guessed already, this meant we constantly broke the Windows build as most of our contributors were using some form of UNIX and thus weren't able to test the Windows build.

This was the status quo for awhile, but eventually tools like CMake started to show up. I spent a lot of time trying to get CMake working for my personal projects before even considering to move the Pidgin code base to it.

Even though CMake had generators for different platforms/IDE's including Visual Studio, the syntax of the build system was at best an iteration on top of autotools. Even pkg-config was basically an after thought and features available in pkg-config weren't implemented in CMake either.

I even went as far as writing CMake modules for gettext and gobject-introspection. However, at the end of the day, CMake wasn't really supported by upstreams like GLib/GTK even though KDE had gone all in with it which meant that I just had an additional maintenance burden which actually would have been less had I left my personal projects in autotools.

At some point in here, I started tinkering around with writing my own build system generator, because of course I did. The working name was reap and it used reapfile's. The premise was pretty simple, reap as written in Python and would setup a Python and would basically eval your reapfiles to generate everything. Basically the idea was that something like Project('foo') had a whole bunch of magic that would register the project inside of reap where depending on subcommands it would attempt to build stuff.

It never got much further than the basic eval proof of concept, but I did get full blown pkg-config support implemented. But then other stuff came up and it sat.

Some time had gone by and one day I saw a news article about this new (to me) build system named Meson and it just seemed too good to be true! pkg-config is the default method for finding dependencies, it supports generating build systems, would work fine on Windows, etc.

I started discussing this with Elliott Sales de Andrade who then went ahead and converted GPlugin to meson! He would even go on to contribute to Meson itself as well as convert the Pidgin repository.

Meson gave us a lot of reasons to convert. First of all, it was a single build system that would work literally everywhere. It didn't require a POSIX compliant shell as it was just a Python application. This meant you can even run it from Command Prompt in Windows! We still have the dependency problem on Windows, but that's a topic for another blog post.

The syntax is much easier to understand and doesn't feel like it's write-once like autotools and even CMake can be. A lot of this is accomplished by having some very basic fundamental types that you end up passing to different functions and the function just figures it out. For example, say you want to build a simple GTK4 application in Meson, all you need is the following in a meson.build file.

project('test', 'C')

GTK4 = dependency('gtk4')

executable('simple-gtk-app', 'main.c', dependencies : [GTK4])
Enter fullscreen mode Exit fullscreen mode

You could argue that a static Makefile would be pretty simple too, but remember that this can generate build systems for ninja, Visual Studio, and Xcode which means it'll integrate into those platforms much easier.

This brings up another point that's a big win for Meson. They decided not to support Make at all. They did this for a number of reasons, but the biggest is that Make only works on a single directory at a time. What this amounts to is that people avoid organizing their code because it can cause Make to take longer to run. For example, if I have an 8 core machine and 10 directories with 2 files each in them that need to get compiled, Make can only compile 2 things at a time which leaves 6 of the cores idle!

This scenario is completely avoided by ninja because ninja knows about the entire project at once which means if something isn't blocked by a dependency and there's available CPU, ninja will build it. I had known about ninja for awhile and ended up being the initial packager for it for Debian because I wanted to use it with CMake on my personal projects. So when Meson announced that this was their default build system, it made me very happy!

Meson also made a lot of very smart default values/parameters for things. For example, the FindLibrary macros in CMake didn't have a REQUIRED parameter for well over a decade. In Meson, not only is there a parameter for whether or not a dependency is required, it defaults to TRUE which eliminates a TON of boiler plate. For example, if you use the example meson code above and don't have the GTK4 development files, meson setup will fail and tell you that it's missing. I know this sounds trivial, but after two plus decades of having to manually check for these conditions in autotools and CMake this is an absolute breath of fresh air.

Meson also has modules for tasks that are common for developers, but not so common that they should be in the base language spec. For example, there is a GNOME module that makes it easy to do all of the things you need to when building a GLib/GTK based application. Whether that's gobject-introspection, compiling GSettings schemas, or generating the code for registering enum and flag types, it's just an include away in Meson that will just work even when cross compiling as Meson is also setup well for cross compiling!

I could go on about all of the awesome aspects of Meson, but really if you're a developer you should go and check it out, because I have had zero complaints about it, which is saying a lot. If you're a user, just know that the developers using Meson are spending less time being afraid of their build system which means they can spend more time working on features and bug fixes for you!

I hope you're enjoying these posts! Remember they go live for patrons at 9AM CST on Mondays and go public at 12AM CST on Thursdays! If there's something specific you'd like to see me cover here, please comment below!

Top comments (0)