ARG BASE_IMAGE=docker.io/debian
ARG BASE_IMAGE_TAG=bookworm-slim
FROM ${BASE_IMAGE}:${BASE_IMAGE_TAG} AS base-image

ENV APT_UPDATE="apt-get update" \
    APT_INSTALL="env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends" \
    APT_CLEANUP="rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*"

FROM base-image AS base

LABEL org.opencontainers.image.title="Pixman build environment for platform coverage" \
      org.opencontainers.image.authors="Marek Pikuła <m.pikula@partner.samsung.com>"

ARG GCOVR_VERSION="~=7.2"
ARG MESON_VERSION="~=1.7"
RUN echo "deb http://deb.debian.org/debian bookworm-backports main" >  /etc/apt/sources.list.d/debian-12-backports.list \
    && ${APT_UPDATE} \
    && ${APT_INSTALL} \
        # Build dependencies.
        build-essential \
        ninja-build \
        pkg-config \
        # pipx dependencies.
        python3-argcomplete \
        python3-packaging \
        python3-pip \
        python3-platformdirs \
        python3-userpath \
        python3-venv \
        # gcovr dependencies.
        python3-lxml \
    # User bookworm-backports for QEMU, as it has version 7 by default, which
    # has some issues.
    && ${APT_INSTALL} \
        $(grep bookworm /etc/os-release >/dev/null && echo -t bookworm-backports) \
        qemu-user \
    && ${APT_CLEANUP} \
    # Install pipx using pip to have a more recent version of pipx, which
    # supports the `--global` flag.
    && pip install pipx --break-system-packages \
    # Install a recent version of meson and gcovr using pipx to have the same
    # version across all variants regardless of base.
    && pipx install --global --system-site-packages \
        gcovr${GCOVR_VERSION} \
        meson${MESON_VERSION} \
    && gcovr --version \
    && echo Meson version: \
    && meson --version

FROM base AS llvm-base
# LLVM 16 is the highest available in Bookworm. Preferably, we should use the
# same version for all platforms, but it's not possible at the moment.
ARG LLVM_VERSION=16
RUN ${APT_UPDATE} \
    && ${APT_INSTALL} \
        clang-${LLVM_VERSION} \
        libclang-rt-${LLVM_VERSION}-dev \
        lld-${LLVM_VERSION} \
        llvm-${LLVM_VERSION} \
    && ${APT_CLEANUP} \
    && ln -f /usr/bin/clang-${LLVM_VERSION} /usr/bin/clang \
    && ln -f /usr/bin/lld-${LLVM_VERSION} /usr/bin/lld \
    && ln -f /usr/bin/llvm-ar-${LLVM_VERSION} /usr/bin/llvm-ar \
    && ln -f /usr/bin/llvm-strip-${LLVM_VERSION} /usr/bin/llvm-strip

FROM llvm-base AS native-base
ARG LLVM_VERSION=16
RUN ${APT_UPDATE} \
    && ${APT_INSTALL} \
        # Runtime library dependencies.
        libglib2.0-dev \
        libgtk-3-dev \
        libpng-dev \
    # Install libomp-dev if available (OpenMP support for LLVM). It's done only
    # for the native images, as OpenMP support in cross-build environment is
    # tricky for LLVM.
    && (${APT_INSTALL} libomp-${LLVM_VERSION}-dev \
        || echo "OpenMP not available on this platform.") \
    && ${APT_CLEANUP}

# The following targets differ in BASE_IMAGE.
FROM native-base AS linux-386
FROM native-base AS linux-amd64
FROM native-base AS linux-arm-v5
FROM native-base AS linux-arm-v7
FROM native-base AS linux-arm64-v8
FROM native-base AS linux-mips64le
FROM native-base AS linux-mipsel
FROM native-base AS linux-ppc64le
FROM native-base AS linux-riscv64

# The following targets should have a common BASE_IMAGE.
FROM llvm-base AS linux-mips
RUN ${APT_UPDATE} \
    && ${APT_INSTALL} gcc-multilib-mips-linux-gnu \
    && ${APT_CLEANUP}

FROM llvm-base AS linux-ppc
RUN ${APT_UPDATE} \
    && ${APT_INSTALL} gcc-multilib-powerpc-linux-gnu \
    && ${APT_CLEANUP}

FROM llvm-base AS linux-ppc64
RUN ${APT_UPDATE} \
    && ${APT_INSTALL} gcc-multilib-powerpc64-linux-gnu \
    && ${APT_CLEANUP}

# Windows base image with a pre-built LLVM MinGW toolchain.
FROM base-image AS windows-llvm-base-build
ARG LLVM_MINGW_RELEASE=20250402
ARG LLVM_MINGW_VARIANT=llvm-mingw-${LLVM_MINGW_RELEASE}-ucrt-ubuntu-20.04
RUN ${APT_UPDATE} \
    && ${APT_INSTALL} \
        ca-certificates \
        wget \
        xz-utils \
    && ${APT_CLEANUP} \
    && wget https://github.com/mstorsjo/llvm-mingw/releases/download/${LLVM_MINGW_RELEASE}/${LLVM_MINGW_VARIANT}-`uname -m`.tar.xz \
        -O - | tar -xJ -C /opt \
    && mv /opt/llvm* /opt/llvm

FROM base AS windows-llvm-base
RUN ${APT_UPDATE} \
    && ${APT_INSTALL} procps \
    && ${APT_CLEANUP}
COPY --from=windows-llvm-base-build /opt/llvm /opt/llvm
ENV PATH=/opt/llvm/bin:${PATH} \
    # Inspired by https://code.videolan.org/videolan/docker-images
    WINE_BOOT='wine wineboot --init \
        && while pgrep wineserver > /dev/null; do \
            echo "waiting ..."; \
            sleep 1; \
        done \
        && rm -rf /tmp/wine-*'

FROM windows-llvm-base AS windows-686
ENV WINEPATH=/opt/llvm/i686-w64-mingw32/bin \
    WINEARCH=win32
RUN dpkg --add-architecture i386 \
    && ${APT_UPDATE} \
    && ${APT_INSTALL} \
        libwine:i386 \
        wine \
        wine32 \
    && ${APT_CLEANUP} \
    && ${WINE_BOOT}

# Dependencies needed both for Wine build and the final image.
FROM windows-llvm-base AS windows-wine-build-base
RUN ${APT_UPDATE} \
    && ${APT_INSTALL} \
        libfreetype-dev \
        libgnutls28-dev \
        libkrb5-dev \
        libx11-dev \
        libxcomposite-dev \
        libxcursor-dev \
        libxext-dev \
        libxfixes-dev \
        libxi-dev \
        libxrandr-dev \
        libxrender-dev \
    && ${APT_CLEANUP}

# Wine build intermediate target, not going into the final image.
FROM windows-wine-build-base AS windows-wine-build
RUN ${APT_UPDATE} \
    && ${APT_INSTALL} \
        bison \
        ca-certificates \
        clang \
        flex \
        git \
        lld \
        llvm \
    && ${APT_CLEANUP}
ARG WINE_VERSION=10.5
RUN git clone https://gitlab.winehq.org/wine/wine.git \
        -b wine-${WINE_VERSION} \
        --depth 1
RUN cd wine \
    && ./configure --enable-win64 --disable-tests --without-unwind --prefix=/opt/wine \
    && make -j`nproc` \
    && make install

FROM windows-llvm-base AS windows-amd64
COPY --from=windows-wine-build /opt/wine /opt/wine
ENV PATH=/opt/wine/bin:${PATH} \
    WINEPATH=/opt/llvm/x86_64-w64-mingw32/bin
RUN ${WINE_BOOT}

FROM windows-wine-build-base AS windows-arm64-v8
COPY --from=windows-wine-build /opt/wine /opt/wine
ENV PATH=/opt/wine/bin:${PATH} \
    WINEPATH=/opt/llvm/aarch64-w64-mingw32/bin
RUN ${WINE_BOOT}
