|
1 | 1 | # ============================================================================= |
2 | | -# Build and Test Workflow for libppd (x86_64 / ubuntu-latest) |
| 2 | +# Multi-Architecture Build & Test Workflow for libppd |
3 | 3 | # |
4 | | -# Modelled on the libcupsfilters CI in the sister OpenPrinting repository. |
5 | | -# Scope is intentionally restricted to a single native architecture |
6 | | -# (x86_64 on ubuntu-latest) so the build runs quickly and deterministically |
7 | | -# while still proving: |
| 4 | +# Modelled on the QEMU-based CI used in the sister OpenPrinting repositories |
| 5 | +# (libcupsfilters, cups-filters). Proves on every push / PR / manual dispatch |
| 6 | +# that libppd compiles end-to-end (libppd.la + every check_PROGRAMS binary) |
| 7 | +# and that every registered TEST in Makefile.am passes under |
| 8 | +# `make check V=1 VERBOSE=1` on FOUR architectures: |
8 | 9 | # |
9 | | -# * The complete repository compiles end-to-end (libppd.la plus all |
10 | | -# declared programs and tests under check_PROGRAMS) — not just that |
11 | | -# the test binaries link against an already-built library. |
12 | | -# * All registered TESTS pass (the 8 native C unit tests added in this |
13 | | -# cycle: testppd, test_ppd_localize, test_ppd_cache, test_ppd_ipp, |
14 | | -# test_ppd_mark, test_ppd_custom, test_ppd_attr, test_ppd_page, |
15 | | -# test_ppd_conflicts). test_ppd_load_profile is intentionally |
16 | | -# deregistered in Makefile.am pending mentor review of a latent |
17 | | -# bug in ppdLutLoad(). |
| 10 | +# * amd64 - native, ubuntu-latest |
| 11 | +# * arm64 - native, ubuntu-24.04-arm |
| 12 | +# * armhf - emulated via QEMU (armv7) |
| 13 | +# * riscv64 - emulated via QEMU |
18 | 14 | # |
19 | | -# The apt package list was derived from a direct scan of configure.ac: |
| 15 | +# The hermetic C unit tests exercised: testppd, test_ppd_localize, |
| 16 | +# test_ppd_cache, test_ppd_ipp, test_ppd_mark, test_ppd_custom, |
| 17 | +# test_ppd_attr, test_ppd_page, test_ppd_conflicts. |
20 | 18 | # |
21 | | -# * PKG_CHECK_MODULES([LIBCUPSFILTERS], [libcupsfilters]) -> libcupsfilters-dev |
22 | | -# * PKG_CHECK_MODULES([ZLIB], [zlib]) -> zlib1g-dev |
23 | | -# * AC_PATH_TOOL(CUPSCONFIG, [cups-config]) (cups3 absent |
24 | | -# on ubuntu-latest, falls back to libcups2) -> libcups2-dev |
25 | | -# * AC_CHECK_PROG(CUPS_GHOSTSCRIPT, gs) -> ghostscript |
26 | | -# * AC_CHECK_PROG(CUPS_PDFTOPS, pdftops) -> poppler-utils |
27 | | -# * AC_CHECK_PROG(CUPS_MUTOOL, mutool) -> mupdf-tools |
28 | | -# * pdftocairo (Poppler renderer) -> poppler-utils |
29 | | -# * AM_GNU_GETTEXT([external]) / AM_ICONV -> gettext, autopoint |
30 | | -# * AC_PROG_CC, AC_PROG_CXX, AX_CXX_COMPILE_STDCXX([11]) -> build-essential |
31 | | -# * LT_INIT -> libtool |
32 | | -# * PKG_PROG_PKG_CONFIG -> pkg-config |
33 | | -# * AC_PROG_INSTALL -> (provided by build-essential) |
34 | | -# |
35 | | -# All three of ghostscript / poppler-utils / mupdf-tools are installed so |
36 | | -# the default ./configure (no --disable-* flags) succeeds — that gives us |
37 | | -# the maximum-coverage build the user asked for ("comprehensive build, |
38 | | -# rather than just checking if the unit tests run"). |
| 19 | +# apt package list derived from libppd's configure.ac: |
| 20 | +# PKG_CHECK_MODULES([LIBCUPSFILTERS]) -> libcupsfilters-dev |
| 21 | +# PKG_CHECK_MODULES([ZLIB]) -> zlib1g-dev |
| 22 | +# AC_PATH_TOOL(CUPSCONFIG) -> libcups2-dev |
| 23 | +# AC_CHECK_PROG(gs / pdftops / mutool) -> ghostscript, poppler-utils, |
| 24 | +# mupdf-tools |
| 25 | +# AM_GNU_GETTEXT([external]) -> gettext, autopoint |
| 26 | +# AC_PROG_CC / CXX / LT_INIT / pkg-config -> build-essential, autoconf, |
| 27 | +# automake, libtool, |
| 28 | +# libtool-bin, pkg-config |
| 29 | +# transitive (poppler / qpdf renderers) -> libqpdf-dev, libpoppler-dev, |
| 30 | +# libpoppler-cpp-dev |
39 | 31 | # ============================================================================= |
40 | 32 |
|
41 | | -name: Build and Test (libppd) |
| 33 | +name: Build and Test (libppd, multi-arch) |
42 | 34 |
|
43 | 35 | on: |
44 | 36 | push: |
|
51 | 43 |
|
52 | 44 | jobs: |
53 | 45 | build: |
54 | | - name: Build & Test (x86_64) |
55 | | - runs-on: ubuntu-latest |
| 46 | + name: Build & Test (${{ matrix.arch }}) |
| 47 | + runs-on: ${{ matrix.runs-on }} |
| 48 | + |
| 49 | + strategy: |
| 50 | + fail-fast: false |
| 51 | + matrix: |
| 52 | + include: |
| 53 | + - arch: amd64 |
| 54 | + runs-on: ubuntu-latest |
| 55 | + use-qemu: false |
| 56 | + - arch: arm64 |
| 57 | + runs-on: ubuntu-24.04-arm |
| 58 | + use-qemu: false |
| 59 | + - arch: armhf |
| 60 | + runs-on: ubuntu-latest |
| 61 | + use-qemu: true |
| 62 | + qemu-arch: armv7 |
| 63 | + - arch: riscv64 |
| 64 | + runs-on: ubuntu-latest |
| 65 | + use-qemu: true |
| 66 | + qemu-arch: riscv64 |
56 | 67 |
|
57 | 68 | steps: |
58 | 69 | - name: Checkout repository |
59 | 70 | uses: actions/checkout@v4 |
60 | 71 |
|
| 72 | + - name: Save workspace directory |
| 73 | + run: echo "REPO_DIR=$(pwd)" >> $GITHUB_ENV |
| 74 | + |
61 | 75 | # ----------------------------------------------------------------------- |
62 | | - # System dependencies — derived from configure.ac (see header comment). |
| 76 | + # NATIVE LEG (amd64 on ubuntu-latest, arm64 on ubuntu-24.04-arm) |
63 | 77 | # ----------------------------------------------------------------------- |
64 | | - - name: Install build & runtime dependencies |
| 78 | + - name: Install dependencies (native) |
| 79 | + if: matrix.use-qemu == false |
65 | 80 | run: | |
66 | 81 | set -ex |
67 | | - sudo apt-get update --fix-missing -y |
| 82 | + sudo apt-get clean |
| 83 | + sudo apt-get update --fix-missing -y -o Acquire::Retries=3 |
| 84 | + # Drop any pre-shipped libppd-dev so our local build wins |
| 85 | + sudo apt-get remove -y libppd-dev || true |
68 | 86 | sudo apt-get install -y --no-install-recommends \ |
69 | 87 | build-essential \ |
70 | 88 | autoconf \ |
71 | 89 | automake \ |
72 | 90 | autopoint \ |
73 | 91 | libtool \ |
| 92 | + libtool-bin \ |
74 | 93 | pkg-config \ |
75 | 94 | gettext \ |
| 95 | + git \ |
| 96 | + wget \ |
| 97 | + tar \ |
76 | 98 | libcups2-dev \ |
77 | 99 | libcupsfilters-dev \ |
| 100 | + libqpdf-dev \ |
| 101 | + libpoppler-dev \ |
| 102 | + libpoppler-cpp-dev \ |
78 | 103 | zlib1g-dev \ |
79 | 104 | ghostscript \ |
80 | 105 | poppler-utils \ |
81 | 106 | mupdf-tools |
82 | 107 |
|
83 | | - # ----------------------------------------------------------------------- |
84 | | - # Full build — autogen.sh regenerates configure / Makefile.in from the |
85 | | - # autotools sources; configure runs without --disable-* flags so every |
86 | | - # external renderer (gs / pdftops / mutool / pdftocairo) is exercised; |
87 | | - # make -j$(nproc) builds the library AND every check_PROGRAMS binary, |
88 | | - # surfacing any compiler errors or warnings as build output. |
89 | | - # ----------------------------------------------------------------------- |
90 | | - - name: autogen.sh |
91 | | - run: ./autogen.sh |
92 | | - |
93 | | - - name: configure |
94 | | - run: ./configure |
95 | | - |
96 | | - - name: make |
97 | | - run: make -j$(nproc) V=1 |
| 108 | + - name: Build & test libppd (native) |
| 109 | + if: matrix.use-qemu == false |
| 110 | + run: | |
| 111 | + set -ex |
| 112 | + cd "$REPO_DIR" |
| 113 | + ./autogen.sh |
| 114 | + ./configure |
| 115 | + make -j$(nproc) V=1 |
| 116 | + make check V=1 VERBOSE=1 || { |
| 117 | + echo "==== test-suite.log ====" |
| 118 | + test -f test-suite.log && cat test-suite.log |
| 119 | + echo "==== per-test logs ====" |
| 120 | + for f in $(find . -name '*.log' -not -name 'config.log'); do |
| 121 | + echo "---- $f ----"; cat "$f" |
| 122 | + done |
| 123 | + exit 1 |
| 124 | + } |
98 | 125 |
|
99 | 126 | # ----------------------------------------------------------------------- |
100 | | - # Run the registered TESTS. V=1 and VERBOSE=1 expose both the |
101 | | - # compile-line per object AND each test's stderr in the workflow log |
102 | | - # on failure, matching the libcupsfilters CI pattern. We deliberately |
103 | | - # do NOT pipe stderr away — a failing test prints its full diagnostic |
104 | | - # before the step exits non-zero, and the test-suite.log artifact (see |
105 | | - # next step) preserves the full automake summary for download. |
| 127 | + # EMULATED LEG (armhf via QEMU armv7, riscv64 via QEMU) |
106 | 128 | # ----------------------------------------------------------------------- |
107 | | - - name: make check |
108 | | - id: check |
109 | | - run: make check V=1 VERBOSE=1 |
| 129 | + - name: Set up QEMU |
| 130 | + if: matrix.use-qemu == true |
| 131 | + uses: docker/setup-qemu-action@v3 |
| 132 | + with: |
| 133 | + platforms: ${{ matrix.qemu-arch }} |
| 134 | + |
| 135 | + - name: Build & test libppd (emulated) |
| 136 | + if: matrix.use-qemu == true |
| 137 | + uses: uraimo/run-on-arch-action@v3 |
| 138 | + with: |
| 139 | + arch: ${{ matrix.qemu-arch }} |
| 140 | + distro: ubuntu24.04 |
| 141 | + dockerRunArgs: | |
| 142 | + --volume "${{ github.workspace }}:/workspace" |
| 143 | + install: | |
| 144 | + apt-get clean |
| 145 | + apt-get update --fix-missing -y -o Acquire::Retries=3 |
| 146 | + DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata |
| 147 | + apt-get remove -y libppd-dev 2>/dev/null || true |
| 148 | + apt-get install -y --no-install-recommends \ |
| 149 | + build-essential \ |
| 150 | + gcc g++ \ |
| 151 | + autoconf \ |
| 152 | + automake \ |
| 153 | + autopoint \ |
| 154 | + libtool \ |
| 155 | + libtool-bin \ |
| 156 | + pkg-config \ |
| 157 | + gettext \ |
| 158 | + git \ |
| 159 | + wget \ |
| 160 | + tar \ |
| 161 | + libcups2-dev \ |
| 162 | + libcupsfilters-dev \ |
| 163 | + libqpdf-dev \ |
| 164 | + libpoppler-dev \ |
| 165 | + libpoppler-cpp-dev \ |
| 166 | + zlib1g-dev \ |
| 167 | + ghostscript \ |
| 168 | + poppler-utils \ |
| 169 | + mupdf-tools |
| 170 | + run: | |
| 171 | + set -ex |
| 172 | + cd /workspace |
| 173 | + ./autogen.sh |
| 174 | + ./configure |
| 175 | + make -j$(nproc) V=1 |
| 176 | + make check V=1 VERBOSE=1 || { |
| 177 | + echo "==== test-suite.log ====" |
| 178 | + test -f test-suite.log && cat test-suite.log |
| 179 | + echo "==== per-test logs ====" |
| 180 | + for f in $(find . -name '*.log' -not -name 'config.log'); do |
| 181 | + echo "---- $f ----"; cat "$f" |
| 182 | + done |
| 183 | + exit 1 |
| 184 | + } |
110 | 185 |
|
111 | 186 | # ----------------------------------------------------------------------- |
112 | | - # Artifact upload — only fires when `make check` failed. Captures the |
113 | | - # top-level test-suite.log automake produces plus any per-test .log / |
114 | | - # .trs files so the failure can be diagnosed offline. |
| 187 | + # ARTIFACT UPLOAD (all four legs, only on failure) |
115 | 188 | # ----------------------------------------------------------------------- |
116 | | - - name: Upload test-suite.log on failure |
117 | | - if: failure() && steps.check.conclusion == 'failure' |
| 189 | + - name: Upload test logs on failure |
| 190 | + if: failure() |
118 | 191 | uses: actions/upload-artifact@v4 |
119 | 192 | with: |
120 | | - name: libppd-test-suite-log-x86_64 |
| 193 | + name: libppd-test-logs-${{ matrix.arch }} |
121 | 194 | path: | |
122 | 195 | test-suite.log |
123 | 196 | **/*.log |
|
0 commit comments