CMake vs Meson – a real life comparison with actual code

Meson, Meson, what about Meson? Meson has been the most requested build system for me to compare. For those who don’t know, Meson is one of the newest kids on the build system block. From their website, it’s meant to be “both extremely fast, and even more importantly, as user friendly as possible.” So their goal is to finally make a build system for C/C++ that people don’t hate. That’s a pretty ambitious goal…

Let’s see what it’s like to use compared to CMake. As with previous comparisons, here are the rules:

  • I’m going compile the same code using both build systems, and
  • I’m going to try to get both of them to do the same thing, within reason

Watch the video above to see how it went…

This is part of a series of videos comparing different C/C++ build systems. So click here to subscribe to the newsletter if you want to see the rest of the series.

To do that, I’ve borrowed code from The CMake Tutorial. The first is a simple multi-file “hello world”, while example two links to a third-party library.

I’ve been looking forward to this comparison because I’ve heard great things about Meson, and it’s popularity is growing. Let’s get started…

Building a Multi-File Project With CMake & Meson

Like CMake, Meson is a meta-build system. So, it doesn’t build the code itself, but writes build scripts for something like Ninja, and then that does the actual build.

Unsurprisingly, building a simple project with two source files (Main.cpp & Hello.cpp) is almost trivial in both. Here it is in CMake:

cmake_minimum_required(VERSION 3.24)
project(hello_world) 

add_executable(${PROJECT_NAME} Main.cpp Hello.cpp)

and here’s the Meson equivalent:

project(‘hello_world’, ‘cpp’)

executable(meson.project_name(), [‘Main.cpp’, ‘Hello.cpp’])

The two scripts are almost the same. Sure, you use single quotes for strings instead of double-quotes, and getting the project name is different.

By the way, it took a bit of digging to find out how to get the project name in Meson (i.e., meson.project_name()). That’s because every single tutorial and example I found simply duplicated the project’s name. No idea why, because it’s good practise to give the project the same name as the output program, and it’s also good to have the project name defined just once. Otherwise you have to modify it in multple places every time it changes.

Building with both build systems is easy. With CMake:

mkdir build
cd build
cmake ..
cmake –build . –parallel

And with Meson:

meson setup build
cd build
meson compile

One annoyance with Meson with VS Code on Windows, is that you have to run Meson from within the Visual Studio shell for it to use the Visual Studio compiler. This meant that I couldn’t simply use VS Code to perform the build. With CMake, I could choose which compiler or “kit” I wanted to use directly from within VS Code. This is where the VS Code CMake Tools really shines.

Linking to a Third-Party Library in CMake & Meson

Alright, that’s the first example done. Now let’s build something that links to a third-party library. The example code uses the Raylib library to open a Window and print a message.

With CMake, the FetchContent module can fetch and build third-party libraries from the internet if it’s not installed already. Here’s the code to fetch Raylib 4.5.0:

# Dependencies
include(FetchContent)

 

set(RAYLIB_VERSION 4.5.0)
FetchContent_Declare(
    raylib
    URL https://github.com/raysan5/raylib/archive/refs/tags/${RAYLIB_VERSION}.tar.gz
    FIND_PACKAGE_ARGS ${RAYLIB_VERSION} EXACT
)
set(BUILD_EXAMPLES OFFCACHEINTERNAL“”)
FetchContent_MakeAvailable(raylib)

Further down the script, Raylib is added as a dependency to the hello_window executable:

target_link_libraries(${PROJECT_NAME} raylib)

The script also has a few platform-specific workarounds that don’t really matter. If we build and run this, then we get this masterpiece (see below).

hello window example runningThe Meson build script is a bit more complicated, and Meson has rules you must follow. For starters, all dependencies must go in the subprojects/ sub-directory, whether you like it or not. Meson is what’s called an opinionated build system, and intentionally restricts you to one way of doing things.

Importing and linking to Raylib takes up the bulk of the script. The code is a bit too long to post here, so watch the video. For some reason we have to manually link to Raylib’s dependencies, and there’s also more platform-specific code. This wasn’t necessary with CMake. This could be because Raylib is built using CMake, which gives CMake the advantage.

What about downloading and building Raylib like CMake does? Can we get Meson to do the same?

Of course! Check out this raylib.wrap file that’s inside the subprojects/ directory:

[wrap-git]
url = https://github.com/raysan5/raylib.git
revision = 4.5.0
depth = 1
method = cmake

With a few lines of code, we can get it to fetch Raylib version 4.5.0 straight from GitHub, and tell it to use CMake to build it. The depth = 1 option tells Meson to download just the latest revision. We’re not interested in Raylib’s entire history, plus all its branches and tags, so no need to waste time and bandwidth on it.

And with that file in place, it’s done. We have a Meson build script does everything that the CMake script does.

Well, almost. CMake can generate multi-configuration build scripts where debug and release builds can sit side-by-side. I didn’t find a Meson equivalent, although it’s pretty easy to generate debug and release build directories using “meson setup” twice, e.g.:

meson setup build/debug
meson setup build/release –buildtype=release

How Did Meson do vs CMake?

So, how did Meson do? Quite well, I think. In about half a day I managed to go from having never used Meson to matching the CMake builds scripts for these two projects. Try doing that with Make or autotools.

Despite this, I did end up feeling slightly disappointed. That’s not Meson’s fault, though, but the fault of its fanboys. They hyped up how great Meson was so much that I expected it to be even better. I thought that everything would be awesome from the documentation and tutorials through to Meson itself.

Of course reality didn’t match those overinflated expectations. I still had to scour the internet to figure out how to get things working, and of course there are things I wish it did differently. For example, I wish that I could set the Raylib project’s options directly in the wrap file insted of the main build script.

Overinflated expectations aside. Meson did a pretty good job. Mind you, I only used Meson for about half a day, and that’s not really enough experience to be able to truly evaluate it.

What do you think? Leave a comment below

Learn How to Use CMake Properly

Want to learn how to use CMake properly? Head over to cmaketutorial.com. The CMake Tutorial goes into a lot more than I have time for here.

What About Learning Meson?

Sorry, I’ve got no course/tutorial recommendations for Meson. Maybe I’ll create a course myself, later…

Build Script Examples/Templates

The build scripts for both CMake & Make are available in the Kea Campus at Creator tier or higher (link). On the Make side there’s an even more advanced template that is ready for cross-compiling (in the Kea Campus).

Click here for more.

NOTE: This is part of a series comparing C/C++ build systems. Click here to compare more build systems.

Leave a Comment

Your email address will not be published. Required fields are marked *

 


Shopping Cart
Scroll to Top