How GIMP Runs Cross-Platform CI on GitLab
The GNU Image Manipulation Program (GIMP) leverages the GNOME
project’s self-hosted GitLab instance to run comprehensive continuous
integration (CI) pipelines across Linux, Windows, and macOS. Through a
centrally managed .gitlab-ci.yml configuration, the project
combines containerized Linux environments, MinGW cross-compilation
toolchains, and dedicated native runners. This automated pipeline builds
dependencies, compiles the codebase using the Meson build system,
executes automated test suites, and packages release-ready artifacts for
all supported operating systems.
Centralized Configuration with GitLab CI
GIMP defines its entire multi-platform testing workflow in a root
.gitlab-ci.yml file, which is modularized using external
include files for cleaner management. The pipeline is split into logical
stages:
- Preparation: Building base container images and compiling upstream libraries.
- Build and Test: Compiling GIMP and executing automated test harnesses.
- Analysis: Running static analysis, code formatting checks, and documentation generators.
- Distribution: Bundling application packages such as Flatpaks, Windows installers, and macOS disk images.
To optimize pipeline duration, GIMP relies heavily on GitLab’s caching mechanisms and pipeline artifacts, passing compiled dependencies between stages rather than building from scratch on every commit.
Linux Testing and Native Containerization
Linux serves as the primary development and testing target. GIMP executes these jobs inside custom Docker containers hosted on the GNOME GitLab Container Registry.
- Custom Build Environments: GIMP uses specialized Debian and Fedora container images preloaded with essential build tools and system dependencies.
- Upstream Tracking: Because GIMP relies on tightly coupled libraries like GEGL and babl, the CI pipeline frequently compiles the latest Git master branches of these sub-projects within the container before building GIMP itself.
- Execution: Using the Meson build system and Ninja,
the runner compiles the software and triggers the internal test suite
via
meson test. These tests validate core functionalities, file format loaders, and plug-in communication protocols. - Flatpak Generation: GIMP runs automated Flatpak builds to verify runtime sandboxing and ensure that packaging manifests stay up to date.
Windows Cross-Compilation and Native Testing
Testing for Microsoft Windows poses unique infrastructure challenges. GIMP handles Windows CI primarily through cross-compilation, supplemented by native builds:
- Cross-Compilation via MinGW: Instead of running heavy native Windows virtual machines for every commit, GIMP uses Linux-based Docker containers equipped with the MinGW-w64 toolchain. This allows the pipeline to cross-compile 32-bit and 64-bit Windows binaries rapidly within the same infrastructure used for Linux.
- MSYS2 and Native Runners: For tests requiring genuine Windows APIs, the project utilizes native Windows runners running an MSYS2 environment. These jobs verify runtime execution, test Windows-specific integration features, and assemble the final executable installer using Inno Setup.
macOS Builds via Native Runners
Because macOS requires proprietary licensing and Apple hardware, it cannot run inside standard Linux containers. GIMP solves this using dedicated macOS runners integrated into the GNOME GitLab infrastructure:
- Shell Executors: These runners use the GitLab CI shell executor directly on macOS instances provisioned with Xcode and Clang.
- Dependency Management: Dependencies on macOS are either resolved using package managers like Homebrew or built via custom shell scripts that mirror the official GIMP macOS build scripts.
- Bundling and Notarization: Beyond standard
compilation and testing, the macOS pipeline packages the compiled
binaries, dependencies, and resources into an installable
.dmgbundle, verifying that dynamic libraries link correctly via relative paths.
Automated Merge Request Feedback
Every merge request submitted to GIMP triggers this multi-OS matrix. GitLab reports pass/fail statuses for each operating system directly on the merge request interface. If a change breaks Windows-specific paths, causes a compilation error on modern Clang on macOS, or fails a unit test on Linux, developers receive immediate feedback before code merges into the master branch.