mirror of
https://github.com/Klipper4FlashForge/firmware.git
synced 2026-10-22 05:12:16 -05:00
The evaluation asked for apk vs opkg. The comparison turns on one fact that makes most of the usual argument irrelevant here: Alpine has no MIPS port at all, and OpenWrt's mipsel_24kc is musl against this printer's glibc 2.29. So no upstream repository is reachable either way, every package is cross-built here regardless, and a package manager buys packaging and installing -- not software. That reduces the choice to which format is cheapest to PRODUCE on every build, and .ipk wins by a distance: ar + two tarballs + a three-byte version file, no keypair, no Alpine host, no abuild. apk would need the signed three-concatenated-gzip layout implemented by hand or abuild imported into a Debian build image, paid per recipe forever, for a format with an in-progress v2->v3 transition and no users on our architecture. The full table, the two honest points for apk, and the phased plan are in docs/notes/85-packaging.md. The proof of concept is libsodium, end to end and measured rather than described: make packages -> libsodium_1.0.20-1_mipsel_xburst2.ipk + a feed index Verified against real opkg 0.6.3 built from source -- offline-root install, both symlinks preserved as symlinks, list-installed, files, remove leaving nothing behind. dpkg-deb reads it too; the container format is Debian's. A full recompile from a cold cache produces a byte-identical package, so a pin bump is reviewable as a hash diff. libsodium is now compiled ONCE. patch.sh section 5d's build block moved to pkg/libsodium/build.sh and patch.sh runs it, so the tarball's copy and the packaged copy cannot become different libraries wearing one version number -- asserted, not trusted. MODDIR, PY_HOST, PY_TOOLCHAIN_DIR and mips_abi_gate moved to common.sh for the same reason: a package is a shipping vehicle and gets ABI-gated like one, on a machine that may never run patch.sh. Nothing ships. make build is unchanged and still produces one anvil.tar.xz; make packages needs no stock FlashForge package, which is the point -- a packaging gate that only runs where the proprietary firmware is stops being a gate. Two findings worth more than the code. opkg bakes its state directory in at COMPILE time, so a phase-2 opkg must be configured --prefix=/usr/data/anvil or it comes up believing nothing is installed -- the s6 libexecdir trap one layer up. And opkg 0.6.3 will not configure without libarchive, which is what phase 2 actually costs; the opkg binary itself is 33KB. So pkg/ipk-install walks the ar headers with tail/head instead: this busybox is 1.31.1 built small, with no timeout, nc or ionice applet, and betting an installer on an ar nobody has checked for is how an update fails at the last step. qa/static/test_ipk.py is 18 tests that build their own package from a synthetic tree -- no toolchain, no firmware -- so the lane keeps the property qa/conftest.py insists on and can never be skipped into looking green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>