From 7748cfd04109e33e4dc30aeebd966677cbe74797 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Fri, 5 Jun 2026 21:00:16 +0530 Subject: [PATCH] ci: expand build.yml to 4-arch matrix (amd64, arm64, armhf, riscv64) --- .github/workflows/build.yml | 211 ++++++++++++++++++++++++------------ 1 file changed, 142 insertions(+), 69 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 27d866d6..e6c9ce03 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,44 +1,36 @@ # ============================================================================= -# Build and Test Workflow for libppd (x86_64 / ubuntu-latest) +# Multi-Architecture Build & Test Workflow for libppd # -# Modelled on the libcupsfilters CI in the sister OpenPrinting repository. -# Scope is intentionally restricted to a single native architecture -# (x86_64 on ubuntu-latest) so the build runs quickly and deterministically -# while still proving: +# Modelled on the QEMU-based CI used in the sister OpenPrinting repositories +# (libcupsfilters, cups-filters). Proves on every push / PR / manual dispatch +# that libppd compiles end-to-end (libppd.la + every check_PROGRAMS binary) +# and that every registered TEST in Makefile.am passes under +# `make check V=1 VERBOSE=1` on FOUR architectures: # -# * The complete repository compiles end-to-end (libppd.la plus all -# declared programs and tests under check_PROGRAMS) — not just that -# the test binaries link against an already-built library. -# * All registered TESTS pass (the 8 native C unit tests added in this -# cycle: testppd, test_ppd_localize, test_ppd_cache, test_ppd_ipp, -# test_ppd_mark, test_ppd_custom, test_ppd_attr, test_ppd_page, -# test_ppd_conflicts). test_ppd_load_profile is intentionally -# deregistered in Makefile.am pending mentor review of a latent -# bug in ppdLutLoad(). +# * amd64 - native, ubuntu-latest +# * arm64 - native, ubuntu-24.04-arm +# * armhf - emulated via QEMU (armv7) +# * riscv64 - emulated via QEMU # -# The apt package list was derived from a direct scan of configure.ac: +# The hermetic C unit tests exercised: testppd, test_ppd_localize, +# test_ppd_cache, test_ppd_ipp, test_ppd_mark, test_ppd_custom, +# test_ppd_attr, test_ppd_page, test_ppd_conflicts. # -# * PKG_CHECK_MODULES([LIBCUPSFILTERS], [libcupsfilters]) -> libcupsfilters-dev -# * PKG_CHECK_MODULES([ZLIB], [zlib]) -> zlib1g-dev -# * AC_PATH_TOOL(CUPSCONFIG, [cups-config]) (cups3 absent -# on ubuntu-latest, falls back to libcups2) -> libcups2-dev -# * AC_CHECK_PROG(CUPS_GHOSTSCRIPT, gs) -> ghostscript -# * AC_CHECK_PROG(CUPS_PDFTOPS, pdftops) -> poppler-utils -# * AC_CHECK_PROG(CUPS_MUTOOL, mutool) -> mupdf-tools -# * pdftocairo (Poppler renderer) -> poppler-utils -# * AM_GNU_GETTEXT([external]) / AM_ICONV -> gettext, autopoint -# * AC_PROG_CC, AC_PROG_CXX, AX_CXX_COMPILE_STDCXX([11]) -> build-essential -# * LT_INIT -> libtool -# * PKG_PROG_PKG_CONFIG -> pkg-config -# * AC_PROG_INSTALL -> (provided by build-essential) -# -# All three of ghostscript / poppler-utils / mupdf-tools are installed so -# the default ./configure (no --disable-* flags) succeeds — that gives us -# the maximum-coverage build the user asked for ("comprehensive build, -# rather than just checking if the unit tests run"). +# apt package list derived from libppd's configure.ac: +# PKG_CHECK_MODULES([LIBCUPSFILTERS]) -> libcupsfilters-dev +# PKG_CHECK_MODULES([ZLIB]) -> zlib1g-dev +# AC_PATH_TOOL(CUPSCONFIG) -> libcups2-dev +# AC_CHECK_PROG(gs / pdftops / mutool) -> ghostscript, poppler-utils, +# mupdf-tools +# AM_GNU_GETTEXT([external]) -> gettext, autopoint +# AC_PROG_CC / CXX / LT_INIT / pkg-config -> build-essential, autoconf, +# automake, libtool, +# libtool-bin, pkg-config +# transitive (poppler / qpdf renderers) -> libqpdf-dev, libpoppler-dev, +# libpoppler-cpp-dev # ============================================================================= -name: Build and Test (libppd) +name: Build and Test (libppd, multi-arch) on: push: @@ -51,73 +43,154 @@ on: jobs: build: - name: Build & Test (x86_64) - runs-on: ubuntu-latest + name: Build & Test (${{ matrix.arch }}) + runs-on: ${{ matrix.runs-on }} + + strategy: + fail-fast: false + matrix: + include: + - arch: amd64 + runs-on: ubuntu-latest + use-qemu: false + - arch: arm64 + runs-on: ubuntu-24.04-arm + use-qemu: false + - arch: armhf + runs-on: ubuntu-latest + use-qemu: true + qemu-arch: armv7 + - arch: riscv64 + runs-on: ubuntu-latest + use-qemu: true + qemu-arch: riscv64 steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Save workspace directory + run: echo "REPO_DIR=$(pwd)" >> $GITHUB_ENV + # ----------------------------------------------------------------------- - # System dependencies — derived from configure.ac (see header comment). + # NATIVE LEG (amd64 on ubuntu-latest, arm64 on ubuntu-24.04-arm) # ----------------------------------------------------------------------- - - name: Install build & runtime dependencies + - name: Install dependencies (native) + if: matrix.use-qemu == false run: | set -ex - sudo apt-get update --fix-missing -y + sudo apt-get clean + sudo apt-get update --fix-missing -y -o Acquire::Retries=3 + # Drop any pre-shipped libppd-dev so our local build wins + sudo apt-get remove -y libppd-dev || true sudo apt-get install -y --no-install-recommends \ build-essential \ autoconf \ automake \ autopoint \ libtool \ + libtool-bin \ pkg-config \ gettext \ + git \ + wget \ + tar \ libcups2-dev \ libcupsfilters-dev \ + libqpdf-dev \ + libpoppler-dev \ + libpoppler-cpp-dev \ zlib1g-dev \ ghostscript \ poppler-utils \ mupdf-tools - # ----------------------------------------------------------------------- - # Full build — autogen.sh regenerates configure / Makefile.in from the - # autotools sources; configure runs without --disable-* flags so every - # external renderer (gs / pdftops / mutool / pdftocairo) is exercised; - # make -j$(nproc) builds the library AND every check_PROGRAMS binary, - # surfacing any compiler errors or warnings as build output. - # ----------------------------------------------------------------------- - - name: autogen.sh - run: ./autogen.sh - - - name: configure - run: ./configure - - - name: make - run: make -j$(nproc) V=1 + - name: Build & test libppd (native) + if: matrix.use-qemu == false + run: | + set -ex + cd "$REPO_DIR" + ./autogen.sh + ./configure + make -j$(nproc) V=1 + make check V=1 VERBOSE=1 || { + echo "==== test-suite.log ====" + test -f test-suite.log && cat test-suite.log + echo "==== per-test logs ====" + for f in $(find . -name '*.log' -not -name 'config.log'); do + echo "---- $f ----"; cat "$f" + done + exit 1 + } # ----------------------------------------------------------------------- - # Run the registered TESTS. V=1 and VERBOSE=1 expose both the - # compile-line per object AND each test's stderr in the workflow log - # on failure, matching the libcupsfilters CI pattern. We deliberately - # do NOT pipe stderr away — a failing test prints its full diagnostic - # before the step exits non-zero, and the test-suite.log artifact (see - # next step) preserves the full automake summary for download. + # EMULATED LEG (armhf via QEMU armv7, riscv64 via QEMU) # ----------------------------------------------------------------------- - - name: make check - id: check - run: make check V=1 VERBOSE=1 + - name: Set up QEMU + if: matrix.use-qemu == true + uses: docker/setup-qemu-action@v3 + with: + platforms: ${{ matrix.qemu-arch }} + + - name: Build & test libppd (emulated) + if: matrix.use-qemu == true + uses: uraimo/run-on-arch-action@v3 + with: + arch: ${{ matrix.qemu-arch }} + distro: ubuntu24.04 + dockerRunArgs: | + --volume "${{ github.workspace }}:/workspace" + install: | + apt-get clean + apt-get update --fix-missing -y -o Acquire::Retries=3 + DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata + apt-get remove -y libppd-dev 2>/dev/null || true + apt-get install -y --no-install-recommends \ + build-essential \ + gcc g++ \ + autoconf \ + automake \ + autopoint \ + libtool \ + libtool-bin \ + pkg-config \ + gettext \ + git \ + wget \ + tar \ + libcups2-dev \ + libcupsfilters-dev \ + libqpdf-dev \ + libpoppler-dev \ + libpoppler-cpp-dev \ + zlib1g-dev \ + ghostscript \ + poppler-utils \ + mupdf-tools + run: | + set -ex + cd /workspace + ./autogen.sh + ./configure + make -j$(nproc) V=1 + make check V=1 VERBOSE=1 || { + echo "==== test-suite.log ====" + test -f test-suite.log && cat test-suite.log + echo "==== per-test logs ====" + for f in $(find . -name '*.log' -not -name 'config.log'); do + echo "---- $f ----"; cat "$f" + done + exit 1 + } # ----------------------------------------------------------------------- - # Artifact upload — only fires when `make check` failed. Captures the - # top-level test-suite.log automake produces plus any per-test .log / - # .trs files so the failure can be diagnosed offline. + # ARTIFACT UPLOAD (all four legs, only on failure) # ----------------------------------------------------------------------- - - name: Upload test-suite.log on failure - if: failure() && steps.check.conclusion == 'failure' + - name: Upload test logs on failure + if: failure() uses: actions/upload-artifact@v4 with: - name: libppd-test-suite-log-x86_64 + name: libppd-test-logs-${{ matrix.arch }} path: | test-suite.log **/*.log