diff --git a/README.md b/README.md index 2d62fcf..3bbbbbd 100644 --- a/README.md +++ b/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= --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 diff --git a/packaging/make-sysroot.sh b/packaging/make-sysroot.sh new file mode 100755 index 0000000..3b52593 --- /dev/null +++ b/packaging/make-sysroot.sh @@ -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= \ +# --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 +# /usr/lib/gcc//. +# 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"