Add the cross-build sysroot recipe, verified on the device
packaging/make-sysroot.sh populates a minimal Alpine aarch64 rootfs with apk-tools-static, so a cross build needs no root, no qemu and no phone. Adapted from imsd's, plus glib-dev for the bus layer that is coming. Building against a real Alpine sysroot means the binary links dynamically against the phone's own musl and libc++ -- libc++, libc++abi, libunwind and libgcc_s are all already on pmOS. The harness this daemon replaces had to be built -static, but only because it was built with the host's glibc toolchain; that constraint was never about the target. The pipeline is proven end to end rather than assumed: the cross-built binary runs on the phone, and all five core suites pass there too -- on the real hardware, not just under qemu-aarch64. That matters for modules that are almost entirely little-endian field packing and offset arithmetic.
This commit is contained in:
parent
f2a696bbbe
commit
93692c9505
2 changed files with 67 additions and 2 deletions
16
README.md
16
README.md
|
|
@ -56,11 +56,23 @@ crafter-build test # the unit suites
|
|||
Cross-compiling for the phone:
|
||||
|
||||
```sh
|
||||
packaging/make-sysroot.sh # once; no root, no qemu, no device
|
||||
crafter-build -- --target=aarch64-alpine-linux-musl \
|
||||
--sysroot=<alpine-aarch64-sysroot> --march=armv8-a --mtune=generic
|
||||
crafter-build test --target=aarch64-alpine-linux-musl
|
||||
--sysroot=~/.cache/fingerprintd/sysroot-aarch64-alpine \
|
||||
--march=armv8-a --mtune=generic
|
||||
crafter-build test --target=aarch64-alpine-linux-musl --sysroot=... \
|
||||
--march=armv8-a --mtune=generic # runs the suites under qemu-aarch64
|
||||
```
|
||||
|
||||
The result links dynamically against the phone's own musl and libc++
|
||||
(`libc++`, `libc++abi`, `libunwind`, `libgcc_s`, all already present on pmOS).
|
||||
The research harness this replaces had to be built `-static`, but only because
|
||||
it was built with the host's glibc toolchain — that constraint does not apply
|
||||
to a real Alpine sysroot.
|
||||
|
||||
Verified on the device: all five suites pass cross-built and run **on the phone
|
||||
itself**, not only under emulation.
|
||||
|
||||
## Status
|
||||
|
||||
**The core is complete; the daemon does not run yet.** Everything was ported
|
||||
|
|
|
|||
53
packaging/make-sysroot.sh
Executable file
53
packaging/make-sysroot.sh
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
# SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
||||
# make-sysroot.sh — build an Alpine aarch64 sysroot for cross-compiling
|
||||
# fingerprintd.
|
||||
#
|
||||
# Downloads apk-tools-static + the Alpine signing keys from the CDN and
|
||||
# populates a minimal rootfs (musl, libc++, glib and their headers) that clang
|
||||
# can use via --sysroot. No root, no qemu, no device needed:
|
||||
#
|
||||
# packaging/make-sysroot.sh [dir] # default: ~/.cache/fingerprintd/sysroot-aarch64-alpine
|
||||
# crafter-build -- --target=aarch64-alpine-linux-musl --sysroot=<dir> \
|
||||
# --march=armv8-a --mtune=generic
|
||||
#
|
||||
# Cross-building against a real Alpine sysroot is why the binary links
|
||||
# DYNAMICALLY against the phone's own musl and libc++. The research harness
|
||||
# this daemon replaces had to be built -static, but only because it was built
|
||||
# with the host's glibc toolchain; that constraint does not apply here.
|
||||
set -eu
|
||||
|
||||
SYSROOT="${1:-$HOME/.cache/fingerprintd/sysroot-aarch64-alpine}"
|
||||
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
|
||||
# <sysroot>/usr/lib/gcc/<triple>/.
|
||||
# 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"
|
||||
|
||||
work=$(mktemp -d)
|
||||
trap 'rm -rf "$work"' EXIT
|
||||
|
||||
fetch_pkg() { # $1 = repo (main/community), $2 = package name -> path on stdout
|
||||
file=$(curl -fsSL "$MIRROR/$1/x86_64/" |
|
||||
grep -o "href=\"$2-[0-9][^\"]*\.apk\"" | head -n1 | cut -d'"' -f2)
|
||||
[ -n "$file" ] || { echo "cannot find $2 in $MIRROR/$1" >&2; exit 1; }
|
||||
curl -fsSL -o "$work/$file" "$MIRROR/$1/x86_64/$file"
|
||||
echo "$work/$file"
|
||||
}
|
||||
|
||||
echo ">> fetching apk-tools-static + alpine-keys"
|
||||
tar -xzf "$(fetch_pkg main apk-tools-static)" -C "$work" sbin/apk.static 2>/dev/null
|
||||
tar -xzf "$(fetch_pkg main alpine-keys)" -C "$work" usr/share/apk/keys 2>/dev/null
|
||||
|
||||
echo ">> populating $SYSROOT ($ARCH: $PKGS)"
|
||||
mkdir -p "$SYSROOT"
|
||||
"$work/sbin/apk.static" \
|
||||
--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
|
||||
|
||||
echo ">> done: $SYSROOT"
|
||||
Loading…
Reference in a new issue