Skip to content

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

CommandDescription
meson setup builddirConfigure a new build directory
meson compile -C builddirCompile the project
meson test -C builddirRun tests
meson install -C builddirInstall the project
meson configure builddirShow/change build options
meson dist -C builddirCreate a release tarball
meson introspect builddirQuery project information
meson wrapManage dependency wraps
meson subprojectsManage 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

IssueSolution
ninja: error: missing inputRun meson setup --wipe builddir to reconfigure
Dependency not foundCheck pkg-config --list-all or use a wrap
Build dir already configuredUse --reconfigure or --wipe flag
Wrong compiler selectedSet CC/CXX env vars or use a native file
Stale build artifactsDelete builddir and re-run meson setup
Cross-compile link errorsVerify 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