Meson Cheat Sheet
Overview
Meson is a modern, open-source build system designed for maximum speed and ease of use. It generates build files for Ninja (by default), Visual Studio, and Xcode, and supports C, C++, Fortran, Java, Rust, and many other languages. Meson emphasizes a clean, readable syntax with its custom DSL and provides first-class support for cross-compilation.
Unlike traditional build systems like Make or CMake, Meson separates the build directory from the source directory by design, supports unity builds out of the box, and provides built-in dependency management through wraps and pkg-config. It is widely adopted by projects like GNOME, systemd, X.org, and Mesa.
Installation
Linux
# Ubuntu/Debian
sudo apt update
sudo apt install meson ninja-build
# Fedora
sudo dnf install meson ninja-build
# Via pip (latest version)
pip3 install meson
sudo apt install ninja-build
macOS
# Homebrew
brew install meson ninja
# Via pip
pip3 install meson
brew install ninja
Windows
# Via pip
pip3 install meson
# Download ninja from https://ninja-build.org and add to PATH
# Or use chocolatey
choco install meson ninja
Project Setup
Initialize a New Project
# Create a new project directory
mkdir myproject && cd myproject
# Create meson.build file
cat > meson.build << 'EOF'
project('myproject', 'c',
version : '1.0.0',
default_options : ['warning_level=3', 'c_std=c11'])
executable('myapp', 'src/main.c')
EOF
# Configure the build directory
meson setup builddir
# Configure with specific options
meson setup builddir --buildtype=release
meson setup builddir --buildtype=debug --prefix=/usr/local
Build Types
# Debug build (default)
meson setup builddir --buildtype=debug
# Release build with optimizations
meson setup builddir --buildtype=release
# Release with debug info
meson setup builddir --buildtype=debugoptimized
# Minimal size build
meson setup builddir --buildtype=minsize
Core Commands
| Command | Description |
|---|---|
meson setup builddir | Configure a new build directory |
meson compile -C builddir | Compile the project |
meson test -C builddir | Run tests |
meson install -C builddir | Install the project |
meson configure builddir | Show/change build options |
meson dist -C builddir | Create a release tarball |
meson introspect builddir | Query project information |
meson wrap | Manage dependency wraps |
meson subprojects | Manage subprojects |
Building and Testing
# Build the project
meson compile -C builddir
# Build with verbose output
meson compile -C builddir -v
# Run all tests
meson test -C builddir
# Run specific test suite
meson test -C builddir --suite unit
# Run tests with verbose output
meson test -C builddir -v
# Install to prefix
meson install -C builddir
# Install to custom DESTDIR
DESTDIR=/tmp/staging meson install -C builddir
Build File Syntax (meson.build)
Libraries and Executables
# Shared library
mylib = shared_library('mylib',
'src/lib.c',
'src/utils.c',
version : '1.2.0',
install : true)
# Static library
mylib_static = static_library('mylib',
'src/lib.c',
'src/utils.c')
# Executable linking against a library
executable('myapp',
'src/main.c',
link_with : mylib,
install : true)
# Both shared and static from same sources
mylib_both = both_libraries('mylib',
'src/lib.c',
install : true)
Dependencies
# Find system dependency via pkg-config
glib_dep = dependency('glib-2.0', version : '>=2.56')
# Optional dependency
json_dep = dependency('json-c', required : false)
if json_dep.found()
add_project_arguments('-DHAVE_JSON', language : 'c')
endif
# Use dependency in target
executable('myapp', 'src/main.c',
dependencies : [glib_dep, json_dep])
# Declare dependency for consumers
mylib_dep = declare_dependency(
include_directories : include_directories('include'),
link_with : mylib)
Subdirectories and Options
# Include subdirectory
subdir('src')
subdir('tests')
# meson.options file (or meson_options.txt)
# option('enable_feature', type : 'boolean', value : false)
# option('backend', type : 'combo', choices : ['sqlite', 'postgres'], value : 'sqlite')
# Reading options
if get_option('enable_feature')
subdir('feature')
endif
Configuration
Cross Compilation
# cross-file.ini
[binaries]
c = 'arm-linux-gnueabihf-gcc'
cpp = 'arm-linux-gnueabihf-g++'
ar = 'arm-linux-gnueabihf-ar'
strip = 'arm-linux-gnueabihf-strip'
[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'armv7l'
endian = 'little'
# Use cross file
meson setup builddir --cross-file cross-file.ini
Reconfiguring
# Change option after initial setup
meson configure builddir -Dbuildtype=release
meson configure builddir -Dprefix=/opt/myapp
meson configure builddir -Denable_feature=true
# Wipe and reconfigure
meson setup --wipe builddir
Advanced Usage
Wrap Dependency System
# Search for wraps
meson wrap search zlib
# Install a wrap
meson wrap install zlib
# Update all wraps
meson wrap update
# Wrap file example (subprojects/zlib.wrap)
# [wrap-file]
# directory = zlib-1.2.13
# source_url = https://zlib.net/zlib-1.2.13.tar.gz
# source_hash = abc123...
# [provide]
# zlib = zlib_dep
Custom Targets and Generators
# Custom target
custom_target('generate-header',
output : 'config.h',
command : [find_program('gen-config.py'), '@OUTPUT@'],
build_by_default : true)
# Generator for repeated transformations
gen = generator(find_program('protoc'),
output : ['@BASENAME@.pb.cc', '@BASENAME@.pb.h'],
arguments : ['--cpp_out=@BUILD_DIR@', '@INPUT@'])
gen_src = gen.process('proto/message.proto')
executable('myapp', 'src/main.cc', gen_src)
Unity Builds
# Enable unity build for faster compilation
meson setup builddir --unity=on
# Per-target unity build in meson.build
executable('myapp', sources, unity : true)
Troubleshooting
| Issue | Solution |
|---|---|
ninja: error: missing input | Run meson setup --wipe builddir to reconfigure |
| Dependency not found | Check pkg-config --list-all or use a wrap |
| Build dir already configured | Use --reconfigure or --wipe flag |
| Wrong compiler selected | Set CC/CXX env vars or use a native file |
| Stale build artifacts | Delete builddir and re-run meson setup |
| Cross-compile link errors | Verify cross-file paths and sysroot settings |
# Debug build system issues
meson introspect builddir --targets
meson introspect builddir --dependencies
meson introspect builddir --buildoptions
# Check meson version
meson --version
# Verbose compilation to see exact commands
meson compile -C builddir -v