Meson Build Template
The meson-build.yml template provides a standardized workflow for building
projects using the Meson build system across
multiple platforms and toolchains in a GitLab CI environment.
Overview
This template enables you to:
Build your project with Meson for various target platforms and architectures using the multiplatform OCI Images.
Support both native and cross-compilation via Meson cross files.
Generate build artifacts for use in Meson Test Template.
Optionally enable coverage reporting with Gcovr for supported environments, with an aggregate summary provided by Gcovr Summary Template.
Pre-built images such as llvm-meson from this repository are suitable for
most Meson-based builds (see Pre-built Images). These images include all
necessary tools for Meson, LLVM, and GNU toolchain builds. If your project
needs additional dependencies, you can extend these images by adding custom
layers or modifications in OCI Image Build Template.
Usage in CI
Typically, this template is included in CI pipelines (see Examples) to define jobs for each supported platform. Each job uses the template to set up the build environment, configure Meson, and compile the project. Coverage can be enabled for native builds.
Parallel matrix limitations
Inputs
The template accepts the following inputs:
Target
target: Build target in the formOS-TYPE-ARCH(e.g.,linux-native-amd64). This is similar to an OCI platform string but uses a hyphen instead of a slash, and includes aTYPE(eithernativeorcross). See Platform Naming for details.toolchain: Array of toolchains to test. Each toolchain should have a corresponding Meson cross file. Used to create a job matrix. Default:[gnu, llvm].qemu_cpu:QEMU_CPUenvironment variable used by the OCI runner (which uses QEMU). Not used for targets running natively on the runners. Default:"".Set this to a specific value if needed to properly discover a platform during the build.
Meson
meson_source_directory: Directory containing the Meson project. Default:"."".meson_cross_directory: Directory containing Meson cross files. Cross files should follow the format${TARGET}-${TOOLCHAIN}.meson. If the cross-file is not found in the directory, it uses the default from/opt/meson-crossfrom the OCI image. See Meson Cross Files. Default:.gitlab-ci.d/meson-cross.meson_c_args: ExtraCARGS(C compiler arguments) to pass to Meson builds. Default:"".meson_setup_args: Extra arguments passed tomeson setup. Default:"".meson_compile_args: Extra arguments passed tomeson compile. Default:"".enable_gnu_coverage: Enable coverage build flags. It can be later used to collect a coverage report for all the jobs (with Gcovr Summary Template). It should be enabled only for native build environments as they have all the optional dependencies, and are the most reliable and uniform, which is required by Gcovr to properly parse the coverage reports. Disable for cross environments. Default:true.
CI Job
allow_failure: Set theallow_failureflag for jobs expected to fail. Setretryinput to 0 to prevent unnecessary retries. Default:false.artifact_expiry_in: Set how long GitLab keeps the artifacts. Build artifacts are not strictly needed afterwards besides the test job, so it can be set to short period of time to decrease the usage of artifact storage. Default:1 day.extends: Array of jobs to extend this job template. Must include an OCI image template (see Top-level Requirements) and can include target activation pattern. Default:[.ci-multiplatform-base].job_name_prefix: Prefix for the job name. Useful for disabling or customizing jobs. Default:"".job_name_suffix: Suffix for the job name. Can be used to prevent job duplication for jobs for the same target. Default:"".oci_job: OCI image build job name. Can remain unchanged if no image is built in the pipeline. Default:oci.runner_tag: GitLab runner tag for this job. Default:"".stage: CI stage name for the job. Default:build.
Meson Cross Files
Meson cross files are configuration files used by Meson to enable cross-compilation, specify custom toolchains for native builds, or set project options. They describe the properties of the target platform, compilers, and tools, allowing Meson to generate correct build rules for different environments.
This template requires cross files even for native builds, making the template
more uniform and predictable, but if no modifications are required, the
template uses the default cross-files. In this codebase, Meson cross files are
named ${TARGET}-${TOOLCHAIN}.meson (e.g., linux-native-amd64-gnu.meson)
and stored in the directory specified by meson_cross_directory input
(default: .gitlab-ci.d/meson-cross). These files are referenced during CI
builds to select the appropriate toolchain and platform configuration.
The default cross-files are located in the Meson OCI image in
/opt/meson-cross directory, and in this repo under
oci/debian/meson-cross.
You can use them as a base for customization.
Besides use in CI, using cross files in development provides a standard target
description, allowing you to specify project options and CFLAGS. You can
use the cross file during setup, for example:
$ meson setup build \
--cross-file .gitlab-ci.d/meson-cross/linux-native-amd64-gnu.meson
You can also create a single native-gnu.meson/native-llvm.meson and
create symbolic links for all targets using the native toolchain, as done in
the Pixman project in .gitlab-ci.d/meson-cross. The following examples are from
Pixman.
Refer to the Meson documentation for more details on cross file syntax: https://mesonbuild.com/Cross-compilation.html
Native GNU (Linux)
[binaries]
c = 'gcc'
ar = 'ar'
strip = 'strip'
pkg-config = 'pkg-config'
Uses GCC and standard GNU tools for native builds. No platform section is needed, as host matches target.
Native LLVM (Linux)
[binaries]
c = 'clang'
cpp = 'clang++'
ar = 'llvm-ar'
strip = 'llvm-strip'
Uses Clang and LLVM tools for native builds. Similar to Native GNU (Linux), no platform section is needed.
Cross-Compilation GNU (Windows)
[binaries]
c = 'x86_64-w64-mingw32-gcc'
ar = 'x86_64-w64-mingw32-ar'
strip = 'x86_64-w64-mingw32-strip'
windres = 'x86_64-w64-mingw32-windres'
exe_wrapper = 'wine'
[project options]
openmp = 'disabled'
[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
Specifies the cross-compiler for Windows AMD64. Uses Wine as the
exe_wrapper to run Windows binaries on Linux. Defines project options and
target platform details. It is recommended to disable openmp for Windows
targets, as it can intermittently fail for large and concurrent test sets.
Cross-Compilation GNU (Linux)
[binaries]
c = 'mips-linux-gnu-gcc'
ar = 'mips-linux-gnu-ar'
strip = 'mips-linux-gnu-strip'
exe_wrapper = ['qemu-mips', '-L', '/usr/mips-linux-gnu/']
[host_machine]
system = 'linux'
cpu_family = 'mips32'
cpu = 'mips32'
endian = 'big'
Uses the cross-compiler for MIPS32 (big-endian) targets. Explicitly specifies
QEMU as the exe_wrapper.
Here we need to define the host_machine to indicate the target
specification to Meson.
Cross-Compilation LLVM (Linux)
[binaries]
c = ['clang', '-target', 'mips-linux-gnu', '-fPIC', '-DCI_HAS_ALL_MIPS_CPU_FEATURES']
ar = 'llvm-ar'
strip = 'llvm-strip'
exe_wrapper = ['qemu-mips', '-L', '/usr/mips-linux-gnu/']
[built-in options]
c_link_args = ['-target', 'mips-linux-gnu', '-fuse-ld=lld']
[host_machine]
system = 'linux'
cpu_family = 'mips32'
cpu = 'mips32'
endian = 'big'
Similar to the above, but for LLVM. Clang uses -target argument to specify
the cross-compilation target.
Explicit QEMU execution wrapper
To use QEMU with specific flags (e.g., CPU specification) as the
exe_wrapper, set it as follows (under [binaries]):
exe_wrapper = ['qemu-arm', '-cpu', 'arm1136']usesqemu-armand sets the CPU used by Meson.exe_wrapper = ['qemu-mips', '-L', '/usr/mips-linux-gnu/']uses an explicit ELF interpreter prefix.
Managing project options
You can explicitly set some Meson project options by specifying them as follows:
[project options]
mips-dspr2 = 'disabled'
In this example, mips-dspr2 is disabled to build with another MIPS SIMD
backend.
Adding CFLAGS
Add custom C compiler flags (CFLAGS) by modifying the c binary, e.g.:
[binaries]
c = ['gcc', '-DCI_HAS_ALL_MIPS_CPU_FEATURES']
Here, CI_HAS_ALL_MIPS_CPU_FEATURES is added as a compile define.
Job Structure
The build and test stages (see Meson Test Template) are split to two stages in the CI pipeline. This allows you to build artifacts once and test them with multiple configurations, such as different SIMD backends or QEMU flags to emulate various processor features (e.g., RVV VLEN for RISC-V). This approach improves efficiency and flexibility, enabling comprehensive testing without redundant builds.
Each job created by the template:
Sets up the build directory and enables coverage if requested.
Runs
meson setupwith the appropriate cross file and arguments.Compiles the project with
meson compile.Stores build artifacts for the testing stage in
build-${TOOLCHAIN}(e.g.,build-gnufor the GNU toolchain).
Examples
A typical job definition in build.yml:
spec:
inputs:
ci_path:
description:
Path to the ci-multiplatform meson-build component with branch name.
type: string
default: gitlab.com/riseproject/ci/ci-multiplatform/meson-build@main
runner_tag_qemu:
description: Regular x86 runner with QEMU support.
type: string
default: "saas-linux-medium-amd64"
---
include:
# Native x86_64 target.
- component: $[[ inputs.ci_path ]]
inputs:
target: linux-native-amd64
runner_tag: $[[ inputs.runner_tag_qemu ]]
# QEMU target with specific `QEMU_CPU`.
- component: $[[ inputs.ci_path ]]
inputs:
target: linux-native-mips64le
runner_tag: $[[ inputs.runner_tag_qemu ]]
qemu_cpu: Loongson-3A4000
# Target with only GNU toolchain and no coverage support.
- component: $[[ inputs.ci_path ]]
inputs:
target: linux-native-mipsel
runner_tag: $[[ inputs.runner_tag_qemu ]]
toolchain: [gnu]
qemu_cpu: 74Kf
enable_gnu_coverage: false
Adding ci_path and runner_tag_qemu as inputs makes the declaration
shorter and easier to update if any inputs change.
For a full example, see Meson Project Example.
Another example is in the Pixman project in .gitlab-ci.d/02-build.yml file.