From 2ef1e6b96a3363b7aacab8b114923bd9c3dada71 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Wed, 14 Oct 2026 02:32:30 +0200 Subject: [PATCH] packaging, ci: build the apk with the Crafter.Build Flatpak Crafter.Build's releases carry a Flatpak and nothing else since 2026-10-02 (imsd a625248): the rolling `latest` release's crafter-build-linux-x86_64-musl-v2.tar.gz that build-package.sh fetched is gone, so the push of 0.2.6 failed at `fetch crafter-build` (run 10, 2026-10-14, three 404s) and published nothing; the registry still serves 0.2.5. The move imsd made on 2026-10-04: install the Flatpak (net.catcrafts.CrafterBuild//stable from flatpak.catcrafts.net) in the job container and run it as crafter-build. bubblewrap inside the container needs a privileged runner, so the job runs on the `flatpak` label. The host keeps clang and llvm-ar for libqcomtee, which make-libqcomtee.sh compiles against the sysroot; the daemon's compiler, lld and libc++ are the Flatpak's, so the host packages that served the native test-suite run go. The sysroot gains llvm-runtimes, the package with the std module source of its own libc++ (libc++-dev ships none), added with --upgrade so a sysroot from before this change comes out with a matching libc++ and source. The README's Build section carries the install lines. Tested: build-package.sh run end to end on this commit in a privileged alpine:edge container (podman) on the workstation: crafter-build 2.1.0 (clang 23.1.2) from `stable`, the sysroot at libc++ and llvm-runtimes 23.1.3, daemon and agent cross-built, 8 suites passed natively, the three apks built, the daemon an aarch64 PIE against the sysroot's musl and libc++ (65 s). The rehearsed copy differs from this commit by the wrapping of one comment line. --- .forgejo/workflows/package.yml | 9 ++-- README.md | 7 +++ packaging/build-package.sh | 79 +++++++++++++++++++--------------- packaging/make-sysroot.sh | 11 +++-- 4 files changed, 64 insertions(+), 42 deletions(-) diff --git a/.forgejo/workflows/package.yml b/.forgejo/workflows/package.yml index 6c18221..cd569f7 100644 --- a/.forgejo/workflows/package.yml +++ b/.forgejo/workflows/package.yml @@ -7,9 +7,10 @@ name: package # # Build: crafter-build cross-compiles against an Alpine aarch64 sysroot # (packaging/build-package.sh — the README's "Cross-compiling" flow), the test -# suite runs natively, and packaging/APKBUILD wraps the result. This needs no -# privileged runner: it runs in an alpine:edge container on the ordinary -# arch-latest runner. +# suite runs natively, and packaging/APKBUILD wraps the result. crafter-build +# is the Crafter.Build Flatpak, and bubblewrap inside the job container needs +# a privileged runner: the job runs on the `flatpak` label (the Catcrafts +# organisation's privileged runner), in an alpine:edge container. # # Release gating is the version: pkgver comes from interfaces/Fingerprintd.cppm, # the registry answers 409 for an already-published version, and the publish @@ -27,7 +28,7 @@ on: jobs: package: - runs-on: arch-latest + runs-on: flatpak container: image: alpine:edge timeout-minutes: 90 diff --git a/README.md b/README.md index d15276d..073f4dc 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,14 @@ that touches hardware. ## Build +With the [Crafter Build](https://forgejo.catcrafts.net/Catcrafts/Crafter.Build) +Flatpak, which carries the compiler: + ```sh +flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo +flatpak remote-add --if-not-exists catcrafts https://flatpak.catcrafts.net/catcrafts.flatpakrepo +flatpak install catcrafts net.catcrafts.CrafterBuild//stable +alias crafter-build='flatpak run net.catcrafts.CrafterBuild//stable' crafter-build # bin/fingerprintd--/fingerprintd crafter-build test # the unit suites ``` diff --git a/packaging/build-package.sh b/packaging/build-package.sh index 41e6d06..fe03746 100755 --- a/packaging/build-package.sh +++ b/packaging/build-package.sh @@ -5,44 +5,28 @@ # (the README's "Cross-compiling" flow), run the test suite natively, and # package the result via packaging/APKBUILD. Expects an x86_64 Alpine # environment with root — the workflow runs it in an alpine:edge job -# container on an ordinary runner. Root only installs packages and hands off -# to a scratch user: the sysroot is built with apk.static --usermode (which -# refuses root) and abuild wants a user too. +# container on the privileged `flatpak` runner: crafter-build is the +# Crafter.Build Flatpak, and bubblewrap inside the container needs the +# privilege. Root only installs packages and hands off to a scratch user: +# the sysroot is built with apk.static --usermode (which refuses root) and +# abuild wants a user too. # # Built packages land in /home/build/.local/share/abuild/*/aarch64/fingerprintd*.apk; # the workflow's publish step uploads them to the Forgejo Alpine registry. set -eu -# The musl build of crafter-build (Crafter.Build CI's release-musl job): this -# container is Alpine, and the glibc launcher cannot run on musl. v2 = SSE4.2 -# baseline: the CI box is an Intel N5105 (no AVX). Overridable for local -# rehearsals (file:// works). -CRAFTER_URL=${CRAFTER_URL:-https://forgejo.catcrafts.net/Catcrafts/Crafter.Build/releases/download/latest/crafter-build-linux-x86_64-musl-v2.tar.gz} +# crafter-build is the Crafter.Build Flatpak: it carries its own clang, lld +# and libc++, and its SDK has glib, so nothing the daemon's build compiles +# with is installed here. `stable` is the branch Crafter.Build publishes from +# its release tags (`beta` follows every push to its master), so the +# toolchain of a release moves only with a release of the toolchain. The +# branch is overridable for a rehearsal against another one. +CRAFTER_REMOTE=${CRAFTER_REMOTE:-https://flatpak.catcrafts.net/catcrafts.flatpakrepo} +CRAFTER_REF=${CRAFTER_REF:-net.catcrafts.CrafterBuild//stable} SRC=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd) -# clang cross-targets aarch64 natively and the target's libc++/glib come from -# the sysroot; llvm-runtimes/libc++-dev/glib-dev here serve the NATIVE -# test-suite run. build-base = Alpine's standard build environment (the one -# abuild implies): binutils' ld/ar for clang's default link driver, gcc's -# libgcc_s/crt objects the musl clang driver links against. -if [ "$(id -u)" = 0 ]; then - apk add -q git curl tar clang lld llvm llvm-runtimes libc++-dev llvm-libunwind-dev glib-dev \ - build-base abuild sudo - id build >/dev/null 2>&1 || adduser -D build - addgroup build abuild 2>/dev/null || true - echo 'build ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/build - # abuild in cross mode strips with $CHOST-strip; llvm-strip handles any - # ELF arch, so give it that name - ln -sf "$(command -v llvm-strip)" /usr/local/bin/aarch64-alpine-linux-musl-strip - # the CI checkout arrives root-owned; crafter-build writes bin/ into it - chown -R build "$SRC" - # -l: a login shell, so HOME really is /home/build (abuild keys + output); - # it scrubs the environment, so carry the one knob that matters across - exec su -l build -c "CRAFTER_URL='${CRAFTER_URL:-}' sh -eu '$SRC/packaging/build-package.sh'" -fi - retry() { # retry _desc=$1; shift for _i in 1 2 3; do @@ -54,18 +38,43 @@ retry() { # retry return 1 } +# clang and llvm-ar here are for libqcomtee: make-libqcomtee.sh compiles it +# with the host clang against the sysroot (C, objects and an archive, no +# link). llvm also has llvm-strip, which abuild in cross mode strips with. +if [ "$(id -u)" = 0 ]; then + apk add -q git curl tar flatpak clang llvm abuild sudo + # the Flatpak as a system installation the build user runs; its SDK + # (org.freedesktop.Sdk) comes from Flathub + flatpak remote-add --if-not-exists catcrafts "$CRAFTER_REMOTE" + flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo + retry "install crafter-build" flatpak install -y --noninteractive catcrafts "$CRAFTER_REF" + id build >/dev/null 2>&1 || adduser -D build + addgroup build abuild 2>/dev/null || true + echo 'build ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/build + # abuild in cross mode strips with $CHOST-strip; llvm-strip handles any + # ELF arch, so give it that name + ln -sf "$(command -v llvm-strip)" /usr/local/bin/aarch64-alpine-linux-musl-strip + # the CI checkout arrives root-owned; crafter-build writes bin/ into it + chown -R build "$SRC" + # -l: a login shell, so HOME really is /home/build (abuild keys + output); + # it scrubs the environment, so carry the one knob that matters across + exec su -l build -c "CRAFTER_REF='$CRAFTER_REF' sh -eu '$SRC/packaging/build-package.sh'" +fi + # interfaces/Fingerprintd.cppm is the version's single source of truth (same # derivation as make-bin-tarball.sh) VER=$(sed -n 's/.*Version = "\(.*\)".*/\1/p' "$SRC/interfaces/Fingerprintd.cppm") [ -n "$VER" ] || { echo "cannot read Version from interfaces/Fingerprintd.cppm" >&2; exit 1; } echo ">> packaging fingerprintd $VER" -# --- crafter-build: static launcher from the rolling release -mkdir -p "$HOME/crafter-build" -retry "fetch crafter-build" \ - sh -c "curl -fsSL '$CRAFTER_URL' | tar -xz -C '$HOME/crafter-build'" -PATH="$HOME/crafter-build/bin:$PATH" -export CRAFTER_BUILD_HOME="$HOME/crafter-build/share/crafter-build" +# --- crafter-build: the Flatpak, under the name the rest of this file uses. +# The build log names the build it ran with. +mkdir -p "$HOME/bin" +printf '#!/bin/sh\nexec flatpak run %s "$@"\n' "$CRAFTER_REF" > "$HOME/bin/crafter-build" +chmod +x "$HOME/bin/crafter-build" +PATH="$HOME/bin:$PATH" +flatpak info "$CRAFTER_REF" | sed -n 's/^ *\(Version\|Commit\|Date\): */crafter-build \1: /p' +crafter-build --version # --- aarch64 Alpine sysroot (unprivileged: apk.static --usermode) SYSROOT="$HOME/.cache/fingerprintd/sysroot-aarch64-alpine" diff --git a/packaging/make-sysroot.sh b/packaging/make-sysroot.sh index 3b52593..c08cbef 100755 --- a/packaging/make-sysroot.sh +++ b/packaging/make-sysroot.sh @@ -23,9 +23,14 @@ MIRROR="${MIRROR:-https://dl-cdn.alpinelinux.org/alpine/edge}" ARCH=aarch64 # gcc is in the list for its crtbeginS.o/libgcc: clang's driver for # *-alpine-linux-musl links against the GCC runtime it detects under -# /usr/lib/gcc//. +# /usr/lib/gcc//. llvm-runtimes is in it for the std module +# source of this very libc++ (usr/share/libc++/v1/std.cppm; libc++-dev ships +# none): crafter-build compiles the sysroot's own copy first. --upgrade below +# is for a run over an existing sysroot: added alone beside an older libc++, +# a newer llvm-runtimes' source does not compile against its headers +# (imsd, 2026-10-04: 23.1.2 against 22.1.8); upgraded together, it does. # glib-dev is for the GDBus bus layer (net.reactivated.Fprint). -PKGS="musl-dev libc++ libc++-dev glib-dev compiler-rt llvm-libunwind-dev gcc" +PKGS="musl-dev libc++ libc++-dev llvm-runtimes glib-dev compiler-rt llvm-libunwind-dev gcc" work=$(mktemp -d) trap 'rm -rf "$work"' EXIT @@ -48,6 +53,6 @@ mkdir -p "$SYSROOT" --arch "$ARCH" --root "$SYSROOT" --initdb --no-scripts --no-cache \ --usermode --keys-dir "$work/usr/share/apk/keys/$ARCH" \ -X "$MIRROR/main" -X "$MIRROR/community" \ - add $PKGS + add --upgrade $PKGS echo ">> done: $SYSROOT"