mirror of
https://github.com/Klipper4FlashForge/firmware.git
synced 2026-10-22 13:22:16 -05:00
The previous commit proved every component IMPORTS. Importing is not serving,
so this runs it. case-moonraker313.sh starts Moonraker on the exact command
line payload/etc/s6/moonraker/run execs -- only with our interpreter --
against the mod's own assets/moonraker.conf, and asks the printer what
happened:
* bound :7125 in 3s, with /proc/PID/cmdline confirming our interpreter and
our entry point rather than a coincidence
* GET /server/info answers 200 with 23 components loaded and none failed.
/machine/system_info, a different component reading this box's own /proc,
reports cpu: mips and python 3.13.7 [GCC 7.2.0]
* the database really works, which is the entire reason for the exercise: a
POST wrote a namespace, a GET read it back, the namespace appears beside
Moonraker's own, and data.mdb is 147456 bytes on disk -- through lmdb's
CPython extension, not the compile-at-import cffi fallback that would try
to invoke a compiler this printer does not have
* still alive and still answering 120 seconds later, with no tracebacks in
its log, and SIGTERM released the port in 2s
* the RUNNING process maps zero libraries under /usr/prog, with
LD_LIBRARY_PATH completely unset -- not merely purged of /usr/prog
* negative controls: nothing on :7125 beforehand, and with site-packages
moved aside it never binds at all
libsodium was the last /usr/prog string in the picture and is now ours.
libsodium 1.0.20, cross-built with the Ingenic toolchain in 24 seconds, gated
at 0x70001407 nan2008/o32/mips32r2, needing only libpthread, libc and the
loader, 406KB stripped into $MODDIR/lib. It computes rather than merely
loading: sodium_version_string is 1.0.20, its BLAKE2b-256 matches CPython's
own _blake2 on the same kernel, and libnacl.sign.Signer/Verifier -- the exact
ed25519 pair authorization.py imports -- signs, verifies, and rejects a
tampered message.
It costs anvil-env.sh nothing, which was not obvious and had to be measured.
libnacl's third fallback builds a path out of its own __file__, so from
$MODDIR/lib/python3.13/site-packages/libnacl it resolves $MODDIR/lib/libsodium.so
by absolute path -- working with LD_LIBRARY_PATH unset entirely. Recorded in
the README, because it works only because the prefix happens to contain the
string "lib": a prefix without it would break this silently.
klippy was scanned rather than guessed at. Its module-scope third-party
imports are cffi, greenlet, jinja2, pyserial and numpy; four of the five are
built and proven, and cffi already dlopens the printer's real c_helper.so.
numpy is at module scope only in extras/stepper_resonance_tester.py, which
Klipper loads on demand, and it is a multi-day problem that costs input-shaper
calibration rather than printing. There is no removed-stdlib usage anywhere in
klippy -- no imp, distutils, asyncore, cgi or getargspec.
What is left is packaging, not capability, and the README says so in order.
The sharp one: section 5c's trim deletes include/ and config-3.13-*, which the
package build needs, so the package build has to run inside 5c against the
untrimmed stage. And the ABI gate walks the build cache rather than the
payload, so anything staged straight into $MOD_PAYLOAD would bypass it --
coverage, not logic.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
148 lines
6.2 KiB
Bash
Executable File
148 lines
6.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# ---------------------------------------------------------------------------
|
|
# Cross-build libsodium for the Creator 5 Pro (Ingenic mipsel) into the mod's
|
|
# prefix root, so that libnacl -- and therefore Moonraker's `authorization`
|
|
# component -- stops needing /usr/prog/libsodium/lib.
|
|
#
|
|
# This is the LAST /usr/prog string in the phase-6 picture. Everything else
|
|
# the 3.13 interpreter and its extensions need is either static inside the
|
|
# interpreter or built by tools/python-packages/build.sh.
|
|
#
|
|
# Unlike the interpreter's seven static dependencies, this one MUST be shared:
|
|
# libnacl is pure Python and reaches it through ctypes.cdll.LoadLibrary, which
|
|
# is dlopen. So it ships as $MODDIR/lib/libsodium.so.26.2.0 with its soname
|
|
# symlink and the `libsodium.so` development symlink -- and that last one is
|
|
# not decoration, it is the FIRST name libnacl asks dlopen for.
|
|
#
|
|
# Same gcc-wrapper trick as tools/python/build.sh: -EL -mnan=2008 baked into
|
|
# the driver, so libsodium's libtool link lines cannot lose them. Gated at
|
|
# e_flags=0x70001407 (a shared object, so EF_MIPS_PIC is set and it reads
|
|
# ...07 where the interpreter's executable reads ...05) before anything ships.
|
|
#
|
|
# ./build-libsodium.sh # in docker
|
|
# ./build-libsodium.sh --in-container # the actual build
|
|
# ---------------------------------------------------------------------------
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
REPO="${REPO:-/home/shish/firmware/.claude/worktrees/s6-vs-runit}"
|
|
TOOLCHAIN_HOST="$REPO/work/.mips-toolchain/mips-gcc720-glibc229"
|
|
SODIUM_VER="${SODIUM_VER:-1.0.20}"
|
|
SODIUM_SHA256=ebb65ef6ca439333c2bb41a0c1990587288da07f6c7fd07cb3a18cc18d30ce19
|
|
PREFIX=/usr/data/anvil
|
|
|
|
if [ "${1:-}" != "--in-container" ]; then
|
|
[ -x "$TOOLCHAIN_HOST/bin/mips-linux-gnu-gcc" ] || {
|
|
echo "!! no toolchain at $TOOLCHAIN_HOST" >&2; exit 1; }
|
|
exec docker run --rm \
|
|
-v "$TOOLCHAIN_HOST":/toolchain:ro \
|
|
-v "$HERE":/work \
|
|
-e SODIUM_VER="$SODIUM_VER" -e HOST_UID="$(id -u)" -e HOST_GID="$(id -g)" \
|
|
-w /work debian:bookworm bash /work/build-libsodium.sh --in-container
|
|
fi
|
|
|
|
# ======================================================= in the container ===
|
|
START=$(date +%s)
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
TC=/toolchain; W=/work; SRC=$W/src; B=$W/b-sodium; OUT=$W/out
|
|
rm -rf "$B"; mkdir -p "$SRC" "$B" "$OUT"
|
|
log() { echo; echo "===== $* ====="; }
|
|
|
|
log "apt"
|
|
apt-get update -qq
|
|
apt-get install -y -qq --no-install-recommends \
|
|
build-essential curl ca-certificates file xz-utils >/dev/null
|
|
|
|
# ---- the wrappers: -EL -mnan=2008 on every compile AND every link ----------
|
|
log "toolchain wrappers"
|
|
mkdir -p /opt/xw/bin
|
|
for t in gcc g++ cpp; do
|
|
cat > /opt/xw/bin/mips-linux-gnu-$t <<EOF
|
|
#!/bin/sh
|
|
exec $TC/bin/mips-linux-gnu-$t -EL -mnan=2008 "\$@"
|
|
EOF
|
|
chmod +x /opt/xw/bin/mips-linux-gnu-$t
|
|
done
|
|
for t in ar as ld nm objcopy objdump ranlib readelf strip strings size; do
|
|
ln -sf $TC/bin/mips-linux-gnu-$t /opt/xw/bin/mips-linux-gnu-$t
|
|
done
|
|
export PATH=/opt/xw/bin:$PATH
|
|
|
|
# ---- gate the wrapper before building anything on top of it ---------------
|
|
eflags() { mips-linux-gnu-readelf -h "$1" | sed -n 's/.*Flags: *\(0x[0-9a-f]*\).*/\1/p'; }
|
|
echo 'int main(void){return 0;}' > /tmp/t.c
|
|
mips-linux-gnu-gcc /tmp/t.c -o /tmp/t
|
|
[ "$(eflags /tmp/t)" = "0x70001405" ] || {
|
|
echo "!! wrapper produces $(eflags /tmp/t), not 0x70001405" >&2; exit 1; }
|
|
echo "wrapper gate ok: $(eflags /tmp/t)"
|
|
|
|
# ---- fetch ----------------------------------------------------------------
|
|
log "libsodium $SODIUM_VER"
|
|
TAR="$SRC/libsodium-$SODIUM_VER.tar.gz"
|
|
[ -f "$TAR" ] || curl -fsSL -o "$TAR" \
|
|
"https://github.com/jedisct1/libsodium/releases/download/$SODIUM_VER-RELEASE/libsodium-$SODIUM_VER.tar.gz"
|
|
echo "$SODIUM_SHA256 $TAR" | sha256sum -c - || {
|
|
echo "!! sha256 mismatch: $(sha256sum "$TAR")" >&2; exit 1; }
|
|
tar -xzf "$TAR" -C "$B"
|
|
cd "$B/libsodium-$SODIUM_VER"
|
|
|
|
# ---- configure ------------------------------------------------------------
|
|
# --disable-static: nothing links it statically and a .a would only be
|
|
# trimmed away again.
|
|
# --host is what makes autoconf reach for the mips-linux-gnu- prefixed tools
|
|
# in the wrapper directory, which is the whole point of the wrappers.
|
|
# libsodium's runtime feature probes are AC_RUN_IFELSE with cross defaults
|
|
# supplied, so nothing here needs qemu.
|
|
log "configure"
|
|
./configure \
|
|
--host=mips-linux-gnu \
|
|
--prefix="$PREFIX" \
|
|
--disable-static \
|
|
--enable-shared \
|
|
--with-pic \
|
|
CFLAGS="-O2 -fPIC" \
|
|
> "$W/sodium-configure.log" 2>&1 || { tail -40 "$W/sodium-configure.log"; exit 1; }
|
|
|
|
log "make"
|
|
make -j"$(nproc)" > "$W/sodium-make.log" 2>&1 || { tail -60 "$W/sodium-make.log"; exit 1; }
|
|
|
|
STAGE=$W/stage-sodium
|
|
rm -rf "$STAGE"; mkdir -p "$STAGE"
|
|
make install DESTDIR="$STAGE" >> "$W/sodium-make.log" 2>&1
|
|
|
|
# ---- the ABI gate, on the object that ships -------------------------------
|
|
log "ABI gate"
|
|
SO=$(readlink -f "$STAGE$PREFIX/lib/libsodium.so")
|
|
file "$SO"
|
|
mips-linux-gnu-readelf -h "$SO" | sed -n '/Class\|Data\|Type\|Flags/p'
|
|
F=$(eflags "$SO")
|
|
[ "$F" = "0x70001407" ] || { echo "!! e_flags $F, expected 0x70001407" >&2; exit 1; }
|
|
# The words that matter are decoded by readelf out of e_flags itself, on the
|
|
# header's Flags line -- `.MIPS.abiflags` (readelf -A) reports the ISA and the
|
|
# FP ABI but not the NaN encoding, so the header is where nan2008 is read.
|
|
FLAGLINE=$(mips-linux-gnu-readelf -h "$SO" | sed -n 's/.*Flags: *//p')
|
|
echo " decoded: $FLAGLINE"
|
|
for w in nan2008 o32 mips32r2; do
|
|
case ",$FLAGLINE," in
|
|
*"$w"*) ;;
|
|
*) echo "!! e_flags does not decode to $w: $FLAGLINE" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
mips-linux-gnu-readelf -A "$SO" | sed -n '/ISA\|FP ABI/p'
|
|
echo "-- SONAME / NEEDED"
|
|
mips-linux-gnu-readelf -d "$SO" | sed -n '/SONAME\|NEEDED/p'
|
|
|
|
mips-linux-gnu-strip --strip-unneeded "$SO"
|
|
|
|
# ---- what ships: lib/ only. include/ and pkgconfig are build-time. --------
|
|
log "stage"
|
|
TREE=$W/sodium-tree
|
|
rm -rf "$TREE"; mkdir -p "$TREE/lib"
|
|
cp -a "$STAGE$PREFIX"/lib/libsodium.so* "$TREE/lib/"
|
|
rm -f "$TREE"/lib/*.la
|
|
ls -l "$TREE/lib"
|
|
tar -czf "$OUT/sodium.tgz" -C "$TREE" lib
|
|
chown -R "${HOST_UID:-0}:${HOST_GID:-0}" "$OUT" "$W"/sodium-*.log "$SRC" 2>/dev/null || true
|
|
echo
|
|
echo "sodium.tgz: $(du -h "$OUT/sodium.tgz" | cut -f1) ($(($(date +%s)-START))s)"
|