.. _meson-build: 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 :ref:`oci-images`. - Support both native and cross-compilation via Meson cross files. - Generate build artifacts for use in :ref:`meson-test`. - Optionally enable coverage reporting with `Gcovr `_ for supported environments, with an aggregate summary provided by :ref:`gcovr-summary`. Pre-built images such as ``llvm-meson`` from this repository are suitable for most Meson-based builds (see :ref:`oci-pre-built`). 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 :ref:`oci-build`. Usage in CI ----------- Typically, this template is included in CI pipelines (see :ref:`meson-build-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. .. _ci-matrix-limitations-meson-build: Parallel matrix limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. note:: Currently, full CI parallel matrix support is limited due to the following GitLab CI issues: `#396845 `_, `#423553 `_, `#255311 `_. At present, the build matrix is only used to build for different toolchains. Only GNU and LLVM toolchains are supported at this point. Inputs ------ The template accepts the following inputs: Target ^^^^^^ - ``target``: Build target in the form ``OS-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 a ``TYPE`` (either ``native`` or ``cross``). See :ref:`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_CPU`` environment 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-cross`` from the OCI image. See :ref:`meson-cross-files`. Default: ``.gitlab-ci.d/meson-cross``. - ``meson_c_args``: Extra ``CARGS`` (C compiler arguments) to pass to Meson builds. Default: ``""``. - ``meson_setup_args``: Extra arguments passed to ``meson setup``. Default: ``""``. - ``meson_compile_args``: Extra arguments passed to ``meson compile``. Default: ``""``. - ``enable_gnu_coverage``: Enable coverage build flags. It can be later used to collect a coverage report for all the jobs (with :ref:`gcovr-summary`). 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 the ``allow_failure`` flag for jobs expected to fail. Set ``retry`` input 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 :ref:`top-level-reqs`) 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 ----------------- 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 :ci_project_url:`oci/debian/meson-cross <-/blob/main/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: .. code-block:: console $ 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 :pixman_url:`.gitlab-ci.d/meson-cross <-/tree/ci-external/.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-meson: Native GNU (Linux) ^^^^^^^^^^^^^^^^^^ .. code-block:: ini :caption: native-gnu.meson [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) ^^^^^^^^^^^^^^^^^^^ .. code-block:: ini :caption: native-llvm.meson [binaries] c = 'clang' cpp = 'clang++' ar = 'llvm-ar' strip = 'llvm-strip' Uses Clang and LLVM tools for native builds. Similar to :ref:`native-gnu-meson`, no platform section is needed. Cross-Compilation GNU (Windows) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: ini :caption: windows-cross-amd64-gnu.meson [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) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: ini :caption: linux-cross-mips-gnu.meson [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) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: ini :caption: linux-cross-mips-llvm.meson [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']`` uses ``qemu-arm`` and 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: .. code-block:: ini [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.: .. code-block:: ini [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 :ref:`meson-test`) 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 setup`` with 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-gnu`` for the GNU toolchain). .. _meson-build-examples: Examples -------- A typical job definition in ``build.yml``: .. code-block:: yaml 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 :ref:`examples-meson`. Another example is in the Pixman project in :pixman_url:`.gitlab-ci.d/02-build.yml <-/blob/ci-external/.gitlab-ci.d/02-build.yml>` file.