Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 78 additions & 89 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# Multi-Architecture Build and Test Workflow for libcupsfilters
#
# Builds libcupsfilters against three CUPS releases - CUPS 2.x (distro
# libcups2-dev), CUPS 2.5.x (OpenPrinting/cups master) and CUPS 3.x
# (OpenPrinting/libcups master) - so the cross-version compatibility shims
# added in PR #153 stay buildable. All three versions are exercised on
# x86_64; the other architectures run the system (CUPS 2.x) leg.
name: Build and Test (Multi-Architecture)

on:
Expand All @@ -10,141 +16,124 @@ on:
- '**'
workflow_dispatch:

# Cancel an in-progress run when a newer commit is pushed to the same ref.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-matrix:
strategy:
fail-fast: false
matrix:
arch: [x86_64, arm64, armv7, riscv64]
cups: [system-2x, source-2.5.x, source-3.x]
# All three CUPS versions are exercised on x86_64; the other
# architectures only run the system (CUPS 2.x) leg.
exclude:
- { arch: arm64, cups: source-2.5.x }
- { arch: arm64, cups: source-3.x }
- { arch: armv7, cups: source-2.5.x }
- { arch: armv7, cups: source-3.x }
- { arch: riscv64, cups: source-2.5.x }
- { arch: riscv64, cups: source-3.x }
include:
# Native x86_64
- arch: x86_64
runs-on: ubuntu-latest
use-qemu: false

# Native ARM64
- arch: arm64
runs-on: ubuntu-24.04-arm
use-qemu: false

# Emulated 32-bit ARM
- arch: armv7
runs-on: ubuntu-latest
use-qemu: true

qemu-arch: armv7
# Emulated RISC-V
- arch: riscv64
runs-on: ubuntu-latest
use-qemu: true
qemu-arch: riscv64

runs-on: ${{ matrix.runs-on }}
name: Build & Test (${{ matrix.arch }})
name: ${{ matrix.arch }} / ${{ matrix.cups }}
# CUPS 2.5 (master beta) ships a half-transitioned API that libcupsfilters'
# ipp-options.c does not yet support (conflicting cupsParseOptions2 /
# cups array internals). Keep the leg running for visibility, but allow it
# to fail so it does not block the workflow until that is fixed upstream.
continue-on-error: ${{ matrix.cups == 'source-2.5.x' }}

# Keep apt fully non-interactive on native runners: needrestart's
# service-restart prompt otherwise hangs the job indefinitely.
env:
DEBIAN_FRONTEND: noninteractive
NEEDRESTART_MODE: a
NEEDRESTART_SUSPEND: "1"

steps:
- uses: actions/checkout@v4

# ==========================================
# 1. NATIVE EXECUTION (x86_64 and arm64)
# NATIVE EXECUTION (x86_64, arm64)
# ==========================================
- name: Install Dependencies (Native)
if: matrix.use-qemu == false
run: |
sudo apt-get update --fix-missing -y
sudo apt-get upgrade --fix-missing -y
# PREVENT CONFLICTS: Ensure system version doesn't override local source
sudo apt-get remove -y libcupsfilters-dev || true
sudo apt-get install -y \
libqpdf-dev \
avahi-daemon libavahi-client-dev libssl-dev libpam-dev libusb-1.0-0-dev zlib1g-dev \
autotools-dev autopoint cmake libtool pkg-config libcups2-dev libexif-dev liblcms2-dev \
libfontconfig1-dev libfreetype6-dev build-essential qtbase5-dev qtchooser libcairo2-dev \
libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-test-dev \
libopenjp2-7-dev libjpeg-dev libjxl-dev libpoppler-cpp-dev libpython3-dev libdbus-1-dev \
mupdf-tools poppler-utils ghostscript wget tar make gettext

- name: Build PDFio and libcupsfilters (Native)
- name: Build & test (native)
if: matrix.use-qemu == false
timeout-minutes: 90
env:
CC: /usr/bin/gcc
CUPS_KIND: ${{ matrix.cups }}
run: |
set -ex

# Build pdfio
cd /tmp
wget -q https://github.com/michaelrsweet/pdfio/releases/download/v1.6.4/pdfio-1.6.4.tar.gz
tar -xzf pdfio-1.6.4.tar.gz && cd pdfio-1.6.4
./configure --prefix=/usr --enable-shared
make all
sudo make install
sudo ldconfig

# Build and Test libcupsfilters
cd "$GITHUB_WORKSPACE"
./autogen.sh
./configure
make -j$(nproc)
# V=1 shows compiler commands; VERBOSE=1 restores full internal test details
make check V=1 VERBOSE=1 || (test -f test-suite.log && cat test-suite.log; exit 1)

- name: Upload test artifacts (Native)
if: matrix.use-qemu == false && always()
uses: actions/upload-artifact@v4
with:
name: libcupsfilters-test-artifacts-${{ matrix.arch }}
path: |
**/*.log
if-no-files-found: warn
chmod +x ci/ci-setup.sh
sudo -E ci/ci-setup.sh deps
sudo -E ci/ci-setup.sh cups "$CUPS_KIND"
sudo -E ci/ci-setup.sh pdfio
ci/ci-setup.sh build-libcupsfilters
# Downstream autopkgtests against the staged tree (env overrides;
# no privilege, no bind mounts).
make test-autopkgtest V=1

# ==========================================
# 2. EMULATED EXECUTION (armv7 and riscv64)
# EMULATED EXECUTION (armv7, riscv64)
# ==========================================
- name: Build and Test (Emulated)
- name: Build & test (emulated)
if: matrix.use-qemu == true
timeout-minutes: 120
uses: uraimo/run-on-arch-action@v3
with:
arch: ${{ matrix.arch }}
arch: ${{ matrix.qemu-arch }}
distro: ubuntu24.04
githubToken: ${{ github.token }}
env: |
CUPS_KIND: ${{ matrix.cups }}
EMULATED: 1
DEBIAN_FRONTEND: noninteractive
NEEDRESTART_MODE: a
NEEDRESTART_SUSPEND: 1
install: |
apt-get update --fix-missing -y
DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata
# PREVENT CONFLICTS: Ensure system version doesn't override local source
apt-get remove -y libcupsfilters-dev || true
apt-get install -y \
libqpdf-dev \
avahi-daemon libavahi-client-dev libssl-dev libpam-dev libusb-1.0-0-dev zlib1g-dev \
autotools-dev autopoint cmake libtool pkg-config libcups2-dev libexif-dev liblcms2-dev \
libfontconfig1-dev libfreetype6-dev build-essential qtbase5-dev qtchooser libcairo2-dev \
libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-test-dev \
libopenjp2-7-dev libjpeg-dev libjxl-dev libpoppler-cpp-dev libpython3-dev libdbus-1-dev \
mupdf-tools poppler-utils ghostscript wget tar make gettext gcc g++
DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata git sudo
run: |
set -ex
REPO_DIR=$(pwd)

# Build pdfio
cd /tmp
wget -q https://github.com/michaelrsweet/pdfio/releases/download/v1.6.4/pdfio-1.6.4.tar.gz
tar -xzf pdfio-1.6.4.tar.gz && cd pdfio-1.6.4
./configure --prefix=/usr --enable-shared
make all
make install
ldconfig

# Build and Test libcupsfilters
cd $REPO_DIR
export CC=/usr/bin/gcc
./autogen.sh
./configure
make -j$(nproc)

# Mark test-pclm-overflow.sh as XFAIL; VERBOSE=1 for full internal logs
make check V=1 VERBOSE=1 XFAIL_TESTS="cupsfilters/test-pclm-overflow.sh" || (test -f test-suite.log && cat test-suite.log; exit 1)
chmod +x ci/ci-setup.sh
ci/ci-setup.sh deps
ci/ci-setup.sh cups "$CUPS_KIND"
ci/ci-setup.sh pdfio
ci/ci-setup.sh build-libcupsfilters
make test-autopkgtest V=1

- name: Upload test artifacts (Emulated)
if: matrix.use-qemu == true && always()
- name: Upload test artifacts
if: always()
# Best-effort: never let a slow/stalled upload fail or hold the job.
continue-on-error: true
timeout-minutes: 3
uses: actions/upload-artifact@v4
with:
name: libcupsfilters-test-artifacts-${{ matrix.arch }}
name: libcupsfilters-test-artifacts-${{ matrix.arch }}-${{ matrix.cups }}
# Narrow positive globs only (no whole-tree walk, no cache, no .git).
path: |
**/*.log
if-no-files-found: warn

config.log
test-suite.log
cupsfilters/*.log
if-no-files-found: ignore
108 changes: 105 additions & 3 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -246,13 +246,17 @@ testcmyk_SOURCES = \
testcmyk_LDADD = \
libcupsfilters.la \
-lm
testcmyk_CFLAGS = \
$(CUPS_CFLAGS)

testdither_SOURCES = \
cupsfilters/testdither.c \
$(pkgfiltersinclude_DATA)
testdither_LDADD = \
libcupsfilters.la \
-lm
testdither_CFLAGS = \
$(CUPS_CFLAGS)

testimage_SOURCES = \
cupsfilters/testimage.c \
Expand All @@ -266,14 +270,17 @@ testimage_LDADD = \
testimage_CFLAGS = \
$(LIBJPEG_CFLAGS) \
$(LIBPNG_CFLAGS) \
$(TIFF_CFLAGS)
$(TIFF_CFLAGS) \
$(CUPS_CFLAGS)

testrgb_SOURCES = \
cupsfilters/testrgb.c \
$(pkgfiltersinclude_DATA)
testrgb_LDADD = \
libcupsfilters.la \
-lm
testrgb_CFLAGS = \
$(CUPS_CFLAGS)

test1284_SOURCES = \
cupsfilters/test1284.c
Expand All @@ -289,7 +296,8 @@ testpdf1_SOURCES = \
cupsfilters/fontembed-private.h
testpdf1_CFLAGS = \
-I$(srcdir)/cupsfilters/fontembed/ \
-I$(srcdir)/cupsfilters/
-I$(srcdir)/cupsfilters/ \
$(CUPS_CFLAGS)
testpdf1_LDADD = \
libcupsfilters.la

Expand All @@ -298,18 +306,22 @@ testpdf2_SOURCES = \
cupsfilters/fontembed-private.h
testpdf2_CFLAGS = \
-I$(srcdir)/cupsfilters/fontembed/ \
-I$(srcdir)/cupsfilters/
-I$(srcdir)/cupsfilters/ \
$(CUPS_CFLAGS)
testpdf2_LDADD = \
libcupsfilters.la

test_analyze_SOURCES = cupsfilters/fontembed/test-analyze.c
test_analyze_LDADD = libcupsfilters.la
test_analyze_CFLAGS = $(CUPS_CFLAGS)

test_pdf_SOURCES = cupsfilters/fontembed/test-pdf.c
test_pdf_LDADD = libcupsfilters.la
test_pdf_CFLAGS = $(CUPS_CFLAGS)

test_ps_SOURCES = cupsfilters/fontembed/test-ps.c
test_ps_LDADD = libcupsfilters.la
test_ps_CFLAGS = $(CUPS_CFLAGS)

testfilters_SOURCES = \
cupsfilters/testfilters.c \
Expand Down Expand Up @@ -380,3 +392,93 @@ uninstall-hook:
$(RM) $(DESTDIR)$(pkgcharsetdir)/pdf.utf-8

SUBDIRS =

# =============================================================================
# Downstream Debian autopkgtest harness (DESTDIR staging)
#
# Builds, DESTDIR-installs into an ephemeral $(CIROOT) tree, tops up the
# test-only programs/data that `make install` does not ship, rewrites the
# staged libcupsfilters.pc so a consumer resolves THIS build, then runs the
# vendored downstream scripts against it. No privilege, no bind mounts, no
# proot -> identical on native and QEMU-emulated architectures.
# =============================================================================
CIROOT = $(abs_top_builddir)/_ciroot

EXTRA_DIST += \
ci/autopkgtest/run.sh \
ci/autopkgtest/debian-tests/control \
ci/autopkgtest/debian-tests/libcupsfilters-2-dev \
ci/autopkgtest/debian-tests/libcupsfilters-2-functionality

# Fix A: these are check_PROGRAMS (build-only; never copied by `make install`).
# The functionality test executes them as installed binaries (/usr/bin/...),
# so build them and stage them into $(CIROOT)$(bindir). libtool --mode=install
# relinks each cleanly against $(libdir) (LD_LIBRARY_PATH then forces the
# staged library at run time).
STAGED_TEST_BINARIES = \
testdither \
testpdf1 \
testpdf2 \
test-analyze \
test-pdf \
test-ps \
testcmyk \
testrgb

install-test-programs: $(STAGED_TEST_BINARIES)
$(MKDIR_P) "$(CIROOT)$(bindir)"
@for p in $(STAGED_TEST_BINARIES); do \
echo " STAGE $$p -> $(CIROOT)$(bindir)/$$p"; \
$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) "$$p" "$(CIROOT)$(bindir)/$$p" || exit 1; \
done

# Fix C (data seeding): the functionality test copies its input images from
# $(datadir)/libcupsfilters-tests, which upstream `make install` does not ship.
# Seed image.pgm and image.ppm (both are cupsfilters/image.pgm, matching the
# downstream packaging) so the unmodified script finds them.
install-test-data:
$(MKDIR_P) "$(CIROOT)$(datadir)/libcupsfilters-tests"
@echo " STAGE cupsfilters/image.pgm -> $(CIROOT)$(datadir)/libcupsfilters-tests/image.pgm"
$(INSTALL_DATA) "$(srcdir)/cupsfilters/image.pgm" "$(CIROOT)$(datadir)/libcupsfilters-tests/image.pgm"
@echo " STAGE cupsfilters/image.pgm -> $(CIROOT)$(datadir)/libcupsfilters-tests/image.ppm"
$(INSTALL_DATA) "$(srcdir)/cupsfilters/image.pgm" "$(CIROOT)$(datadir)/libcupsfilters-tests/image.ppm"

stage-ciroot: all
rm -rf "$(CIROOT)"
$(MAKE) $(AM_MAKEFLAGS) install DESTDIR="$(CIROOT)"
$(MAKE) $(AM_MAKEFLAGS) install-test-programs install-test-data
@pc="$(CIROOT)$(libdir)/pkgconfig/libcupsfilters.pc"; \
if [ -f "$$pc" ]; then \
sed -i.bak -E "s#^(prefix|exec_prefix|libdir|includedir)=(/.*)#\1=$(CIROOT)\2#" "$$pc"; \
rm -f "$$pc.bak"; \
echo "stage-ciroot: rewrote staged-tree paths in $$pc"; \
fi

# Common environment for the wrapper. LIBCUPSFILTERS_BINDIR / LIBCUPSFILTERS_TESTDIR
# point the functionality test at the staged binaries and data instead of the
# system /usr paths, so it needs no absolute-path redirection (no root, no proot)
# and runs identically on native and QEMU-emulated architectures.
CIROOT_ENV = \
CIROOT="$(CIROOT)" \
CIPREFIX="$(exec_prefix)" \
TOP_BUILDDIR="$(abs_top_builddir)" \
LIBCUPSFILTERS_BINDIR="$(CIROOT)$(bindir)" \
LIBCUPSFILTERS_TESTDIR="$(CIROOT)$(datadir)/libcupsfilters-tests"

# Full downstream suite in a single wrapper invocation -> one aggregate
# PASS/FAIL summary across both tests. Identical on every architecture.
test-autopkgtest: stage-ciroot
$(CIROOT_ENV) \
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libcupsfilters-2-dev libcupsfilters-2-functionality

# Single-test convenience targets (handy for debugging one case in isolation).
test-autopkgtest-dev: stage-ciroot
$(CIROOT_ENV) \
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libcupsfilters-2-dev

test-autopkgtest-func: stage-ciroot
$(CIROOT_ENV) \
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libcupsfilters-2-functionality

.PHONY: stage-ciroot install-test-programs install-test-data \
test-autopkgtest test-autopkgtest-dev test-autopkgtest-func
Loading
Loading