mirror of
https://github.com/Klipper4FlashForge/firmware.git
synced 2026-10-21 21:02:16 -05:00
The software component existed to give the mod one exec hook. It is not needed for that any more, so a release now carries our installer and our payload and nothing else: 26MB smaller, 21MB of which was FlashForge's own firmwareExe travelling back to the partition it was already on, along with their klippy tree, their wifi module and their configs. WHAT IT GIVES BACK. /usr/prog/PROGRAM/software is no longer rewritten, so the version directory there stays FlashForge's with their genuine firmwareExe inside it -- and app_startup.sh's five-second watchdog, which copies one out of that directory when nothing by that name is running, has something to copy again. A printer whose payload fails to install now comes up on the stock UI instead of a blank screen. That recovery has been broken since we started deleting their binary out of a component we shipped; docs/how-it-works.md claimed it worked throughout. THE ROOT PASSWORD moves with it, because it used to ride in the component's shadow file. bin/pack.sh bakes ROOT_PW_HASH into the installer, single-quoted -- an unquoted $6$... would have the printer's shell expand $6 as a positional parameter and ship a truncated hash -- and the installer writes it to /usr/prog/etc/shadow. The random-password path asks one question instead of four: FlashForge ship the same root hash on every machine, so a live shadow still carrying it means nobody has set a password and it is ours to set. The .prev-root-hash recording, the shipped-vs-live comparison and the restore-it- afterwards step were all machinery for surviving a file that nothing overwrites any more, and are gone. pack.sh checks the hardcoded constant against the stock package it built from, because getting it wrong is silent and total: every printer would read as "already set" and none would ever get a password. bin/patch.sh is bin/payload.sh. It patched nothing any more -- no splice, no shadow edit, no firmwareExe deletion -- and what is left is the payload: the feed installed by the printer's own opkg, the seeded config, the manifest. Its sections are renumbered 1-5 with no gaps, and the five tombstone comments marking where removed sections used to be are gone with them. test_recipe_layout.py loses six of its nine tests. Each compared the tree against a description of the tree -- no fourth directory kind, each kind still used, 3rdparty carries no files of ours, installer/ holds exactly two named files -- and none could go red for a reason a printer would notice, while all six went red the moment the layout legitimately changed. The two that bite are kept: a payload/ path escaping $MODDIR, and a recipe name at both levels, which makes pkg_dir silently build the wrong package. SW_VER is deleted from config.env.example and both workflows: it stamped a component that is not built. Gates: 112 static tests pass. The generated installer is verified after substitution -- all four lines present, and `sh -n` over the result, because a hash with a stray character in it would otherwise reach a printer as a syntax error whose only symptom is a package that installs nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CH7Yb4wuPhnppHAB25UX7e
519 lines
32 KiB
Bash
519 lines
32 KiB
Bash
# Pinned third-party payload pieces.
|
|
#
|
|
# These are NOT vendored in the repo: bin/fetch-assets.sh downloads them into
|
|
# vendor/ (gitignored) and refuses anything whose sha256 does not match. Bump
|
|
# a version here and the next build picks it up; the old file stays cached.
|
|
#
|
|
# To bump: edit the version -- for HelixScreen that means HELIX_FILE too,
|
|
# which embeds it, and for the PYPKG_* python packages the FILE is
|
|
# the only place the version appears -- set the matching sha256 to
|
|
# SKIP, then run
|
|
# `make vendor`. It prints the real hash to paste back over SKIP.
|
|
# With a stale hash left in place fetch-assets.sh exits 1 instead of
|
|
# printing anything.
|
|
|
|
MAINSAIL_VERSION="v2.18.2"
|
|
MAINSAIL_SHA256="df2ba7c301f7bfc8ac9f122741a6ba08356d679ecfa1f62f898d0337802d5de5"
|
|
|
|
# Klipper: the creator5 branch of Klipper4FlashForge/klipper -- upstream
|
|
# v0.13.0 plus the FlashForge commits the printer actually needs (see the
|
|
# fork's README-creator5.md). A COMMIT, because the branch moves; bump it by
|
|
# pasting the new head sha here and re-hashing.
|
|
#
|
|
# This pin is the ONLY source. pkg/klipper extracts this tarball and builds
|
|
# c_helper.so from ITS sources with the pinned toolchain below, so the .so can
|
|
# never be older than the klippy tree beside it. The v20260824 release shipped
|
|
# without any of that: config.env's KLIPPER_FORK -- a second, unhashed source
|
|
# that pointed at a local checkout -- was empty in CI, bin/payload.sh silently
|
|
# kept the stock 0.12-era tree, and the package half-overwrote the fork on
|
|
# updated printers, where klippy died at connect with a cffi arg-count error.
|
|
# KLIPPER_FORK is gone with the migration to pkg/: a recipe names its source
|
|
# once, so there is no configuration in which a fork build has no fork.
|
|
KLIPPER_VERSION="b722a4c8b1aedfb939a7688a9b30e7864fddd505"
|
|
KLIPPER_SHA256="dbd81ad75701a56562708a398be9efda1cfa9af84211445e5c86f0683c2326e4"
|
|
|
|
# The cross-toolchain that builds c_helper.so: Ingenic's gcc 7.2.0 /
|
|
# glibc 2.29 for the X2000 (mips32r2, little-endian, o32, nan2008 -- the
|
|
# printer's kernel refuses anything else, and Debian's mips cross-compilers
|
|
# produce big-endian or legacy-nan objects). The same toolchain the K1
|
|
# community uses for the identical SoC family; mirrored as a release asset
|
|
# by ballaswag/k1-discovery. ~203MB, so fetch-assets.sh only pulls it when
|
|
# the build actually needs to compile chelper.
|
|
MIPS_TOOLCHAIN_VERSION="1.0.0"
|
|
MIPS_TOOLCHAIN_FILE="mips-gcc720-glibc229.tar.gz"
|
|
MIPS_TOOLCHAIN_SHA256="c0415a857c6b384820ec61b8a30c89e528585f3ef07d580fc856e80313c9d2e8"
|
|
|
|
HELIX_VERSION="v0.99.115-creator5.2"
|
|
HELIX_FILE="helixscreen-creator5-v0.99.115.tar.gz"
|
|
HELIX_SHA256="dd66dd9b1bdd73f77d7c7f7d76003b14121c5cf102a755083ef7506fbdb22d7d"
|
|
|
|
# Moonraker. The stock one is a 2022 build (API 1.0.5) that predates the
|
|
# webcam "enabled" flag that modern Mainsail requires -- see bin/payload.sh.
|
|
#
|
|
# A COMMIT, NOT A RELEASE, and not a matter of taste. FlashForge built python
|
|
# 3.8.2 WITHOUT the _sqlite3 module and shipped no libsqlite3 anywhere on the
|
|
# printer, so every Moonraker from v0.9.0 onward dies at startup with
|
|
# "ModuleNotFoundError: No module named '_sqlite3'" -- v0.9.0 is where the
|
|
# database moved from lmdb to sqlite. The last release that still uses lmdb is
|
|
# v0.8.0, and that one predates the webcam flag. No release has both, so this
|
|
# pins the newest commit that has the webcam fix and still uses lmdb: 9d0d09d,
|
|
# 2023-12-05, the commit before 80c7620 "database: migrate from lmdb to
|
|
# sqlite". lmdb 1.3.0 is installed, so the existing database is read in place
|
|
# and nothing is converted.
|
|
#
|
|
# Before moving this pin: the blocker is native modules, not the python
|
|
# version (Moonraker still supports >=3.7). Check every dependency of a newer
|
|
# build against what is actually in Python-3.8.2/lib/python3.8/lib-dynload and
|
|
# site-packages on the factory image -- a missing C extension is fatal and a
|
|
# pure-python one is not.
|
|
#
|
|
# CHECK IT BEFORE YOU SHIP IT. Nothing on the printer checks this any more and
|
|
# there is no stock build to fall back to: the installer replaces Moonraker
|
|
# unconditionally, so a pin the interpreter cannot load leaves the machine
|
|
# without a web UI until the next flash. `make test-moonraker` is where that is
|
|
# caught -- it imports every configured component on the printer's own
|
|
# interpreter, in the replica, before anything ships.
|
|
MOONRAKER_VERSION="9d0d09de8063922696359c1b88c86a86d6fdb296"
|
|
MOONRAKER_SHA256="6ddcba08a1a41f173fc6ee393a24e41f27b25f079e7c49921b87273ecff595a8"
|
|
|
|
# ---------------------------------------------------------------- s6
|
|
# The process supervisor and its service manager. skarnet releases these four
|
|
# as a matched set and they will not build against each other across
|
|
# generations, so they are pinned together and bumped together.
|
|
#
|
|
# EXECLINE IS HERE NOW, AND IT USED TO BE DELIBERATELY ABSENT. The argument
|
|
# for leaving it out was that `run` scripts are plain `#!/bin/sh` and execline
|
|
# would be "another 53 binaries / 2.1MB for nothing". The first half is still
|
|
# true and the second half was wrong twice over:
|
|
#
|
|
# * s6-rc has no --disable-execline. It links -lexecline unconditionally,
|
|
# and s6-rc-compile writes execline scripts into every compiled database
|
|
# it produces -- s6rc-oneshot-runner and s6rc-fdholder are generated
|
|
# whether or not any of OUR services need them. So the moment s6-rc is in
|
|
# the picture, execline is not optional.
|
|
# * 2.1MB was measured unstripped and statically linked against musl. Built
|
|
# the way everything is built now -- Ingenic glibc, dynamic libc, cross
|
|
# stripped -- all 53 binaries come to 1008KB. There is no longer a size
|
|
# worth writing a selection list for, and a selection list would be a
|
|
# trap: which execline programs a compiled database references depends on
|
|
# the service definitions, so a subset that works today fails the day
|
|
# somebody adds a pipeline, at boot, naming a program nobody chose.
|
|
#
|
|
# THREE things about this build are load-bearing, all of them measured on the
|
|
# replica rather than reasoned about (see tools/supervisor/README.md):
|
|
#
|
|
# * It is configured --prefix=/usr/data/anvil, because s6 bakes its
|
|
# libexecdir in AT COMPILE TIME: every waiting verb (s6-svc -w,
|
|
# s6-svwait) execs s6-svlisten, which spawns s6-ftrigrd from that baked-in
|
|
# path. Built for any other prefix, `s6-svstat` and respawn keep working
|
|
# and only the waiting verbs fail -- so it fails late and partially, which
|
|
# is the worst way for a supervisor to fail. Moving $MODDIR means
|
|
# rebuilding s6.
|
|
# * It is compiled with -D_FILE_OFFSET_BITS=64. Without it readdir()
|
|
# returns EOVERFLOW on this box (32-bit build, 64-bit inodes) and
|
|
# s6-svscan cannot see its own service directory: it starts cleanly and
|
|
# then supervises nothing.
|
|
# * It links libc DYNAMICALLY, against the printer's own glibc 2.29 -- the
|
|
# same libc.so.6 the interpreter already links, so this adds no dependency
|
|
# the payload did not have. It used to be linked statically against musl,
|
|
# on the strength of a real measurement: static glibc came to 73MB against
|
|
# musl's 3.6MB. That measurement compared two STATIC builds and dynamic
|
|
# glibc was never in it. Measured now: the whole supervision stack --
|
|
# s6's 21 binaries, execline's 53, s6-rc's 5 -- is under 2MB. The musl
|
|
# toolchain, and with it the only second libc in this tree, is gone.
|
|
#
|
|
# ONE MORE THING THAT IS NOT OBVIOUS AND COST AN AFTERNOON: s6 and s6-rc do
|
|
# not link against glibc 2.29 without -lpthread. skalibs' pthread_mutex_tailock
|
|
# reaches pthread_mutex_timedlock, which glibc kept in libpthread until 2.34
|
|
# merged it into libc. Upstream never hits this and musl never had the split.
|
|
# pkg/s6 and pkg/s6-rc pass it through PKG_MAKE_ARGS; the consequence is that
|
|
# every s6 binary carries a NEEDED libpthread.so.0, which a stock glibc rootfs
|
|
# has.
|
|
SKALIBS_VERSION="2.15.1.0"
|
|
SKALIBS_SHA256="f9c905e74935c6fe911c7e344e3e89d5fbd2014c1a04650b524b15ce9b5635d1"
|
|
S6_VERSION="2.15.1.0"
|
|
S6_SHA256="eab9c46e22b66b16135f9a05ec68a0ea287d9060b84d10defaaa2caad158ab52"
|
|
EXECLINE_VERSION="2.9.9.2"
|
|
EXECLINE_SHA256="908ed4db3a6b3a23a205d8fd4cf2a71089156f2aeae0f54656045aafad2dee32"
|
|
S6RC_VERSION="0.7.0.0"
|
|
S6RC_SHA256="bf5b8ce0da5a4ee70d642b818b61d9916a7a9b64a457595f388113e54a188688"
|
|
|
|
# THE musl CROSS-TOOLCHAIN WAS PINNED HERE, and the note is kept because the
|
|
# mistake it records is worth not relearning.
|
|
#
|
|
# It built s6 -- mipsel-buildroot-linux-musl, from Bootlin rather than
|
|
# musl.cc, which is a single volunteer-run host with no CDN that went
|
|
# unreachable from CI more than once. The first target chosen was mips32el:
|
|
# plain mips32r1, whose musl crt and libc are legacy-NaN by construction. This
|
|
# printer's kernel refuses a legacy-NaN binary, and the failure was not a
|
|
# refusal to run but a supervisor that started and then did nothing. It
|
|
# shipped once. The fix was mips32r5el, whose toolchain is nan2008 throughout.
|
|
#
|
|
# The lesson survives its cause: THE TOOLCHAIN DECIDES THE ABI AS MUCH AS THE
|
|
# SOURCES DO, which is why the toolchain filename is part of every recipe's
|
|
# cache stamp (pkg_stamp) and why the ABI gate exists at all. The toolchain
|
|
# itself is gone -- the supervision stack builds with the Ingenic glibc
|
|
# toolchain like everything else, and this tree has one libc again.
|
|
|
|
# ---------------------------------------------------------------- CPython
|
|
# A SECOND Python for the printer, cross-compiled here and SHIPPED AND USED:
|
|
# $FF_PYTHON names it, so Moonraker, klippy, ff-startup.py, ffscreen.py and the
|
|
# MCU bring-up all run on it -- see payload/anvil-env.sh.
|
|
#
|
|
# WHY IT EXISTS AT ALL. FlashForge built 3.8.2 without _sqlite3 and shipped no
|
|
# libsqlite3 anywhere on the rootfs, which is the single fact that pins
|
|
# MOONRAKER_VERSION above to a 2023 commit: every Moonraker from v0.9.0 on
|
|
# stores its database in sqlite and dies at startup on this interpreter. An
|
|
# interpreter that can `import sqlite3` is what unpins that, and it is 3.13
|
|
# rather than a 3.8 with one module added because a from-source build costs
|
|
# the same either way. Measured on the replica: the stock 3.8.2 cannot import
|
|
# sqlite3 and this one creates a database, writes it, closes it and reads it
|
|
# back. That standalone measurement was retired with the case scripts; what is
|
|
# run on every replica now is qa/replica/test_web.py, which brings real
|
|
# Moonraker up on this interpreter and waits for s6's `ready`. It exercises the
|
|
# interpreter harder and says nothing about sqlite3 directly -- the pinned
|
|
# Moonraker predates the sqlite database, which is the whole reason it is
|
|
# pinned.
|
|
#
|
|
# EVERY VERSION BELOW IS PINNED WITH A sha256 FOR THE SAME REASON THE REST OF
|
|
# THIS FILE IS: nothing binary is vendored, so the only thing standing between
|
|
# a source URL and code the printer executes is the hash. python.org, sqlite.org
|
|
# and skarnet are not equally trustworthy, but they are equally irrelevant once
|
|
# the hash is checked.
|
|
#
|
|
# What each pin is load-bearing for, because "bump to latest" is wrong for at
|
|
# least four of them:
|
|
#
|
|
# PY_VERSION The interpreter, and the ONLY version this build works
|
|
# for as written: cross-building CPython needs a build
|
|
# python of the SAME version (configure hard-errors
|
|
# otherwise), so payload.sh builds an x86-64 3.13.7 from this
|
|
# same tarball first. Bump it and both halves move
|
|
# together, which is why there is one variable.
|
|
# OPENSSL_VERSION 3.0.x DELIBERATELY, not 3.1/3.2/3.5. Two things about
|
|
# 3.0.15 are relied on and both were hit for real: `no-docs`
|
|
# does not exist before 3.1 (payload.sh must not pass it), and
|
|
# the linux-mips32 target bakes `-mips2` into its cflags,
|
|
# which this toolchain -- default -mfp64 -- rejects unless
|
|
# an explicit -mips32r2 lands after it on the command line.
|
|
# 3.0 is also the LTS branch (security fixes to 2026-09).
|
|
# Moving to 3.5 means re-deriving the target flags.
|
|
# SQLITE_* THE reason the whole build exists. The amalgamation
|
|
# ("autoconf") tarball, not the source tree: one .c file, no
|
|
# tcl, no fossil. Note the URL carries a YEAR directory that
|
|
# does not appear in the version number, hence SQLITE_YEAR.
|
|
# ZLIB_VERSION zlib.net serves current releases from /fossils/ once they
|
|
# are superseded, so the URL below is the stable one for an
|
|
# old version as well as a current one. Needed by the zlib
|
|
# module and by OpenSSL's compression.
|
|
# LIBFFI_VERSION _ctypes. Nothing on the rootfs can stand in: it ships
|
|
# libffi.so.7 and FlashForge's own /usr/prog carries .so.8,
|
|
# which is exactly the mess a static libffi.a avoids.
|
|
# XZ_VERSION lzma. 5.4.7 and not 5.6.x ON PURPOSE: 5.6.0/5.6.1 are the
|
|
# backdoored releases (CVE-2024-3094). 5.4.7 is the
|
|
# maintained branch that never carried it.
|
|
# BZIP2_VERSION bz2. Last release was 2019; this is not a stale pin, it is
|
|
# the whole project.
|
|
# EXPAT_* pyexpat, and with it every stdlib XML parser. Built here
|
|
# rather than left to CPython's bundled copy so there is one
|
|
# expat to patch when the next parser CVE lands. The tag has
|
|
# its own spelling (R_2_6_4) because libexpat's git tags use
|
|
# underscores; both appear in the URL.
|
|
#
|
|
# IF ONE OF THESE MOVES AND THE HASH IS NOT UPDATED, fetch-assets.sh stops the
|
|
# build. If a hash is updated without re-running the gate, the failure is
|
|
# silent and lands on a printer: a dependency that quietly stops linking makes
|
|
# CPython record the module as "missing" rather than fail, which is precisely
|
|
# how _sqlite3 disappeared during the spike. `make qa-replica` is the check.
|
|
PY_VERSION="3.13.7"
|
|
PY_SHA256="6c9d80839cfa20024f34d9a6dd31ae2a9cd97ff5e980e969209746037a5153b2"
|
|
OPENSSL_VERSION="3.0.15"
|
|
OPENSSL_SHA256="23c666d0edf20f14249b3d8f0368acaee9ab585b09e1de82107c66e1f3ec9533"
|
|
SQLITE_VERSION="3460100"
|
|
SQLITE_YEAR="2024"
|
|
SQLITE_SHA256="67d3fe6d268e6eaddcae3727fce58fcc8e9c53869bdd07a0c61e38ddf2965071"
|
|
ZLIB_VERSION="1.3.1"
|
|
ZLIB_SHA256="9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23"
|
|
LIBFFI_VERSION="3.4.6"
|
|
LIBFFI_SHA256="b0dea9df23c863a7a50e825440f3ebffabd65df1497108e5d437747843895a4e"
|
|
XZ_VERSION="5.4.7"
|
|
XZ_SHA256="8db6664c48ca07908b92baedcfe7f3ba23f49ef2476864518ab5db6723836e71"
|
|
BZIP2_VERSION="1.0.8"
|
|
BZIP2_SHA256="ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269"
|
|
EXPAT_VERSION="2.6.4"
|
|
EXPAT_TAG="R_2_6_4"
|
|
EXPAT_SHA256="fd03b7172b3bd7427a3e7a812063f74754f24542429b634e0db6511b53fb2278"
|
|
|
|
# ------------------------------------------- CPython's third-party packages
|
|
# The 18 sdists that become $MODDIR/lib/python3.13/site-packages -- what
|
|
# Moonraker and klippy import, cross-built for mipsel against the interpreter
|
|
# pinned above -- one pkgs/3rdparty/python-* recipe and one .ipk each. They are
|
|
# live, exactly like the interpreter itself: payload/anvil-env.sh points
|
|
# FF_PYTHON at it and klippy is among its callers.
|
|
#
|
|
# THE LIST IS NOT moonraker-requirements.txt, and that is a decision rather
|
|
# than an omission. That file installs every OPTIONAL component's
|
|
# dependencies -- apprise, ldap3, paho-mqtt, zeroconf, python-periphery. None
|
|
# of those components is enabled in assets/moonraker.conf, so none of them is
|
|
# built. What is here is the closure of what the ENABLED set imports
|
|
# (moonraker.conf's sections plus server.CORE_COMPONENTS) plus klippy's, and
|
|
# nothing else. msgspec and uvloop are absent on purpose: Moonraker guards
|
|
# both with contextlib.suppress(ImportError) and falls back to the stdlib,
|
|
# which was measured rather than assumed.
|
|
#
|
|
# Every one is an SDIST, and bin/payload.sh builds them with `--no-binary :all:`
|
|
# for a reason that is recorded here because it cost real time to find: pip
|
|
# will HELPFULLY download a prebuilt manylinux wheel when one exists, and on
|
|
# the first run of the spike it did exactly that for cffi, greenlet and
|
|
# tornado. Three x86-64 .so files went into the tree, built cleanly, imported
|
|
# cleanly on the build host, and would have failed at import on the printer
|
|
# with nothing but ENOEXEC to explain themselves. Only the ABI gate caught
|
|
# them. A wheel is not a build; it is somebody else's build.
|
|
#
|
|
# WHERE THE URLS COME FROM. bin/fetch-assets.sh composes
|
|
# files.pythonhosted.org/packages/source/<initial>/<project>/<file>, the
|
|
# stable path form, rather than the hashed /packages/<a>/<b>/<64 hex>/ one a
|
|
# browser copies out of PyPI -- that path embeds a digest of the file and
|
|
# changes shape with no version bump, which is a URL nobody can maintain by
|
|
# hand. So the FILE is what is pinned here: it carries the version, the way
|
|
# HELIX_FILE does, and its SPELLING is upstream's business (MarkupSafe,
|
|
# dbus_next and streaming_form_data are not the names their projects use).
|
|
#
|
|
# PYPKG_LIST IS THE SHIP LIST AND THE FETCH LIST -- no longer the build order,
|
|
# which pkg_order derives from each recipe's PKG_BUILD_DEPENDS. Each entry is a
|
|
# recipe: `distro` is pkg/python-distro, which produces anvil-python-distro.
|
|
# bin/fetch-assets.sh fetches from this list and bin/payload.sh stages from it,
|
|
# and qa/static checks the list against the recipe directories both ways, so an
|
|
# entry added here and nowhere else fails a test rather than being fetched,
|
|
# hashed and silently never built. The variable names are the list entry
|
|
# uppercased with - as _, which is how every reader finds them; the VERSION is
|
|
# not pinned separately, it is read out of the FILE name (see pypkg_version).
|
|
PYPKG_LIST="distro inotify-simple libnacl dbus-next preprocess-cancellation
|
|
pyserial pyserial-asyncio pycparser smart-open jinja2 setuptools
|
|
tornado markupsafe cffi greenlet lmdb streaming-form-data pillow"
|
|
|
|
# ---- pure python. No compiler is invoked; they are here to be PRESENT. ----
|
|
PYPKG_DISTRO_FILE="distro-1.9.0.tar.gz"
|
|
PYPKG_DISTRO_SHA256="2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"
|
|
PYPKG_INOTIFY_SIMPLE_FILE="inotify_simple-1.3.5.tar.gz"
|
|
PYPKG_INOTIFY_SIMPLE_SHA256="8440ffe49c4ae81a8df57c1ae1eb4b6bfa7acb830099bfb3e305b383005cc128"
|
|
# libnacl is pure python and reaches libsodium through ctypes -- which is why
|
|
# SODIUM_VERSION at the bottom of this file exists at all, and why a bump to
|
|
# either one is a reason to re-run the ed25519 half of the moonraker gate.
|
|
PYPKG_LIBNACL_FILE="libnacl-2.1.0.tar.gz"
|
|
PYPKG_LIBNACL_SHA256="f3418da7df29e6d9b11fd7d990289d16397dc1020e4e35192e11aee826922860"
|
|
PYPKG_DBUS_NEXT_FILE="dbus_next-0.2.3.tar.gz"
|
|
PYPKG_DBUS_NEXT_SHA256="f4eae26909332ada528c0a3549dda8d4f088f9b365153952a408e28023a626a5"
|
|
# preprocess-cancellation 0.2.1 is a poetry project whose sdist declares NO
|
|
# [build-system] table at all and ships no setup.py, so there is no backend to
|
|
# call and pip's legacy fallback would have to guess. It is also ONE FILE, so
|
|
# pkg/python-preprocess-cancellation copies preprocess_cancellation.py into
|
|
# site-packages rather than building it -- see the comment there. (The same release also declares
|
|
# version 0.0.0 in its own metadata, a broken upstream release, so a version
|
|
# specifier would be refused by pip even if there were something to build.)
|
|
PYPKG_PREPROCESS_CANCELLATION_FILE="preprocess_cancellation-0.2.1.tar.gz"
|
|
PYPKG_PREPROCESS_CANCELLATION_SHA256="e2f1224e1ba1603bdfdbf6937caaf91082dc849e5122e80a5328aa999433ce79"
|
|
PYPKG_PYSERIAL_FILE="pyserial-3.4.tar.gz"
|
|
PYPKG_PYSERIAL_SHA256="6e2d401fdee0eab996cf734e67773a0143b932772ca8b42451440cfed942c627"
|
|
PYPKG_PYSERIAL_ASYNCIO_FILE="pyserial-asyncio-0.6.tar.gz"
|
|
PYPKG_PYSERIAL_ASYNCIO_SHA256="b6032923e05e9d75ec17a5af9a98429c46d2839adfaf80604d52e0faacd7a32f"
|
|
PYPKG_PYCPARSER_FILE="pycparser-2.22.tar.gz" # cffi's only runtime dep
|
|
PYPKG_PYCPARSER_SHA256="491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"
|
|
# smart_open is not optional, whatever the name suggests, and it is not
|
|
# Moonraker that wants it: streaming-form-data's targets.py imports it at
|
|
# MODULE SCOPE, so `import streaming_form_data` raises ModuleNotFoundError
|
|
# without it. Measured in the replica, where every other package imported and
|
|
# that one did not. moonraker-requirements.txt pins it for the same reason.
|
|
PYPKG_SMART_OPEN_FILE="smart_open-6.4.0.tar.gz"
|
|
PYPKG_SMART_OPEN_SHA256="be3c92c246fbe80ebce8fbacb180494a481a77fcdcb7c1aadb2ea5b9c2bee8b9"
|
|
PYPKG_JINJA2_FILE="jinja2-3.1.4.tar.gz"
|
|
PYPKG_JINJA2_SHA256="4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"
|
|
# setuptools/pkg_resources are a runtime dependency of nothing in this list.
|
|
# They are the fix for a MEASURED failure: a tree without them made lmdb fall
|
|
# back to its cffi path and try to invoke mips-linux-gnu-gcc ON THE PRINTER at
|
|
# Moonraker startup, and there is no compiler on a printer. (Installing lmdb
|
|
# as a wheel rather than as an egg removes that path as well, so this is now
|
|
# belt and braces -- 4.9MB of it, 36% of site-packages, and the one obvious
|
|
# thing to drop if the data partition ever gets tight.)
|
|
#
|
|
# It is ALSO the host-side build backend for most of this list:
|
|
# pkg_buildpython installs this same sdist into the shared x86-64
|
|
# build-python. One pin, both jobs -- so the setuptools that generates the
|
|
# shipped .so files is the setuptools whose hash is checked here.
|
|
PYPKG_SETUPTOOLS_FILE="setuptools-75.6.0.tar.gz"
|
|
PYPKG_SETUPTOOLS_SHA256="8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6"
|
|
|
|
# ---- native: twelve mipsel extension modules come out of these six -------
|
|
# tornado's C speedup is optional and its published wheel carries an x86-64
|
|
# copy of it, which is exactly what --no-binary :all: above is for.
|
|
PYPKG_TORNADO_FILE="tornado-6.4.tar.gz"
|
|
PYPKG_TORNADO_SHA256="72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"
|
|
# markupsafe -- jinja2's escape accelerator, on the path of every gcode macro
|
|
# klippy renders. A pure-python fallback (_native.py) exists if it ever fights.
|
|
PYPKG_MARKUPSAFE_FILE="MarkupSafe-2.1.5.tar.gz"
|
|
PYPKG_MARKUPSAFE_SHA256="d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"
|
|
# cffi -- klippy's chelper, and the package that justifies the whole glibc
|
|
# decision: this is what dlopens FlashForge's own c_helper.so, measured. Wants
|
|
# libffi, and gets the static -fPIC one payload.sh already built for _ctypes.
|
|
PYPKG_CFFI_FILE="cffi-1.17.1.tar.gz"
|
|
PYPKG_CFFI_SHA256="1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"
|
|
# greenlet -- klippy's reactor. The MIPS stack-switching assembly was never
|
|
# the problem; C++ designated initializers were. greenlet 3.x writes its
|
|
# PyTypeObjects as designated initializers, which gcc 7.2 -- the only compiler
|
|
# that produces this printer's ABI -- accepts ONLY in declaration order with
|
|
# no gaps, and refuses anything else with "sorry, unimplemented: non-trivial
|
|
# designated initializers not supported". pkg/python-greenlet runs
|
|
# tools/python-packages/fill-designators.py over the sources first. Bumping
|
|
# this pin means re-running that, and it fails loudly rather than quietly: the
|
|
# script refuses to guess when a designator is not in the target's own headers.
|
|
PYPKG_GREENLET_FILE="greenlet-3.1.1.tar.gz"
|
|
PYPKG_GREENLET_SHA256="4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467"
|
|
# lmdb -- Moonraker's database AT THE PIN ABOVE, and the package that
|
|
# disappears the moment MOONRAKER_VERSION moves past 80c7620 (lmdb -> sqlite),
|
|
# which is the whole reason for having built an interpreter with _sqlite3.
|
|
# pkg/python-lmdb sets LMDB_FORCE_CPYTHON=1; do not "fix" that with
|
|
# LMDB_FORCE_CFFI=0 -- setup.py tests the variable for PRESENCE, so the string
|
|
# "0" selects cffi.
|
|
PYPKG_LMDB_FILE="lmdb-1.4.1.tar.gz"
|
|
PYPKG_LMDB_SHA256="1f4c76af24e907593487c904ef5eba1993beb38ed385af82adb25a858f2d658d"
|
|
# streaming-form-data -- Moonraker's upload parser, Cython.
|
|
#
|
|
# NOT 1.13.0, which is what moonraker-requirements.txt pins. That release
|
|
# ships a PREGENERATED _parser.c from a Cython that predates 3.13: it calls
|
|
# the four-argument _PyLong_AsByteArray, which grew a fifth parameter in
|
|
# 3.13, so every integer conversion in the file fails to compile. 1.19.1
|
|
# ships C that is already regenerated, which is also why no Cython is pinned
|
|
# among the host backends below. Moonraker asks five names of it
|
|
# (StreamingFormDataParser, ParseFailedException, FileTarget, ValueTarget,
|
|
# SHA256Target), all present throughout the 1.x line -- and this pin is why
|
|
# smart_open above is in the list at all.
|
|
PYPKG_STREAMING_FORM_DATA_FILE="streaming_form_data-1.19.1.tar.gz"
|
|
PYPKG_STREAMING_FORM_DATA_SHA256="8172dd509a42ac0d1033deb1d13acb68f0cbae7e1492257d13af0922bdc4dd9b"
|
|
# pillow -- Moonraker's ONLY use of it is components/file_manager/metadata.py,
|
|
# which runs as a SUBPROCESS to pull thumbnails out of gcode, so it is not on
|
|
# the startup path: without it Moonraker runs and Mainsail shows no thumbnails.
|
|
#
|
|
# NOT 10.3.0, which is what moonraker-requirements.txt pins, and not for any
|
|
# reason to do with this target: 10.3.0 CANNOT BE BUILT BY ANY 3.13, cross or
|
|
# native. Its setup.py reads its own version with exec(...) followed by
|
|
# locals()["__version__"], and PEP 667 (new in 3.13) made a function's
|
|
# locals() a snapshot -- so the name exec() defined is not there any more and
|
|
# setup.py dies with KeyError: '__version__' before it compiles a single file.
|
|
# 11.0.0 is the first line that supports 3.13. Moonraker asks PIL for
|
|
# Image.open, resize and save, all unchanged across that gap.
|
|
PYPKG_PILLOW_FILE="pillow-11.0.0.tar.gz"
|
|
PYPKG_PILLOW_SHA256="72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739"
|
|
|
|
# ---- host-side build backends. THESE NEVER SHIP. -------------------------
|
|
# Two of the sdists above name a PEP 517 backend that is not setuptools, and
|
|
# pkg_pywheel builds everything with --no-build-isolation -- which is not a
|
|
# preference either: with isolation ON, pip rewrites PYTHONPATH for the build
|
|
# subprocess, the cross _sysconfigdata module stops being importable, and the
|
|
# build either dies outright ("No module named
|
|
# '_sysconfigdata__linux_mipsel-linux-gnu'") or, far worse, silently answers
|
|
# every sysconfig question for x86-64 and produces host objects. So every
|
|
# backend has to be present in advance, and every one is pinned by hash for
|
|
# the same reason the compilers are: this is code that runs on the build
|
|
# machine and decides what the printer executes.
|
|
#
|
|
# Both bootstrap themselves (their sdists declare backend-path), so no third
|
|
# package is needed to install them, and neither is on PYPKG_LIST -- they go
|
|
# into the shared x86-64 build-python that pkg_buildpython caches under
|
|
# work/.py-host, and never leave it. setuptools, the third backend, is on the
|
|
# ship list above and ships as a package of its own as well.
|
|
PYPKG_HOST_LIST="flit-core poetry-core"
|
|
PYPKG_FLIT_CORE_FILE="flit_core-3.10.1.tar.gz" # jinja2's backend
|
|
PYPKG_FLIT_CORE_SHA256="66e5b87874a0d6e39691f0e22f09306736b633548670ad3c09ec9db03c5662f7"
|
|
PYPKG_POETRY_CORE_FILE="poetry_core-1.9.1.tar.gz" # libnacl's backend
|
|
PYPKG_POETRY_CORE_SHA256="7a2d49214bf58b4f17f99d6891d947a9836c9899a67a5069f52d7b67217f61b8"
|
|
|
|
# --------------------------------------------------------------- libsodium
|
|
# The LAST /usr/prog string in the picture. libnacl -- and with it Moonraker's
|
|
# `authorization` component, which signs its JWTs with ed25519 -- is pure
|
|
# python and loads libsodium through ctypes.cdll.LoadLibrary, i.e. dlopen. So
|
|
# unlike the interpreter's seven static dependencies this one MUST be shared,
|
|
# and it is the only library of ours that lands in $MODDIR/lib as a .so.
|
|
#
|
|
# It costs anvil-env.sh nothing, which is the pleasant part and worth writing
|
|
# down because it is an accident: libnacl's third fallback is
|
|
# __file__[0:__file__.find("lib")+3] + "/libsodium.so", and __file__ is
|
|
# $MODDIR/lib/python3.13/site-packages/libnacl/__init__.py -- so it resolves
|
|
# $MODDIR/lib/libsodium.so BY ABSOLUTE PATH, measured working with
|
|
# LD_LIBRARY_PATH unset entirely. That works because the prefix happens to
|
|
# contain the string "lib"; a prefix without it would break silently. Adding
|
|
# $MODDIR/lib to ANVIL_LIBS also works and is the belt-and-braces option, but
|
|
# it would put our libraries in front of everything for every mod process,
|
|
# which is the kind of entry this file's own history argues against.
|
|
#
|
|
# 1.0.20 is the current stable release and there is nothing exotic about the
|
|
# pin. It cross-builds in 24 seconds and is cached on this version string in
|
|
# work/.sodium, the same shape as work/.s6 and work/.py313.
|
|
SODIUM_VERSION="1.0.20"
|
|
SODIUM_SHA256="ebb65ef6ca439333c2bb41a0c1990587288da07f6c7fd07cb3a18cc18d30ce19"
|
|
|
|
# ------------------------------------------------------------------- opkg
|
|
# The package manager, cross-built by pkg/opkg/ and shipped as ONE static
|
|
# binary. See docs/notes/85-packaging.md for why opkg and not apk; the short
|
|
# version is that neither has usable binaries for this target (Alpine has no
|
|
# mips port at all, OpenWrt's is musl against our glibc), so the choice came
|
|
# down to which format is cheapest to produce, and an .ipk is an ar archive of
|
|
# two tarballs.
|
|
#
|
|
# Fetched from downloads.yoctoproject.org, which is opkg's actual home -- the
|
|
# project moved from openmoko to Yocto years ago and the old URLs are gone
|
|
# rather than stale.
|
|
#
|
|
# 0.7.0 AND NOT 0.6.3, which this was pinned to first, for a reason that is
|
|
# specifically about building it against musl. Two files in 0.6.3 --
|
|
# opkg_remove.c and opkg_archive.c -- call basename() without including
|
|
# <libgen.h>, and get away with it only because glibc's <string.h> also
|
|
# declares a (differently-behaved) basename. musl does not, so gcc 14 stops at
|
|
# "implicit declaration of function 'basename'" and, worse, would have silently
|
|
# truncated the returned pointer through an implicit int on a compiler that
|
|
# only warned. 0.7.0 adds both includes. That is the whole delta that matters
|
|
# here, and it is the difference between a pin bump and carrying a patch.
|
|
#
|
|
# THE PREFIX IS BAKED IN AT COMPILE TIME. opkg resolves its own state directory
|
|
# from the --prefix it was configured with, NOT from --offline-root, so it must
|
|
# be built --prefix=/usr/data/anvil or it will look in the wrong place and
|
|
# conclude nothing is installed. Measured on the build host against this exact
|
|
# release. Same class of trap as s6's libexecdir and execline's shebangdir
|
|
# above; three for three, and the reason $MODDIR now lives in bin/common.sh
|
|
# where a recipe cannot spell it differently.
|
|
OPKG_VERSION="0.7.0"
|
|
OPKG_SHA256="d973fd0f1568f58f87d6aecd9aa95e3e1f60214a45cee26704bf8fe757c54567"
|
|
|
|
# libarchive is what opkg reads .ipk files with, and it is NOT optional: opkg's
|
|
# ./configure hard-fails at the pkg-config check for it (measured -- there is
|
|
# no internal tar fallback any more, that went in 0.3.0). BUILD-ONLY and never
|
|
# shipped, like skalibs: it is linked into the static binary and there is no
|
|
# libarchive.so anywhere in the payload.
|
|
#
|
|
# Cut down to almost nothing by pkg/opkg/build.sh -- an .ipk is gzip and tar
|
|
# and that is the whole requirement, so every other codec is configured out
|
|
# rather than cross-built. Bumping this is safe as long as those --without
|
|
# flags still name real options; libarchive renames them occasionally, and a
|
|
# flag it no longer recognises is only a warning, so check the configure log
|
|
# for "unrecognized options" after a bump rather than trusting the exit code.
|
|
LIBARCHIVE_VERSION="3.7.9"
|
|
LIBARCHIVE_SHA256="aa90732c5a6bdda52fda2ad468ac98d75be981c15dde263d7b5cf6af66fd009f"
|
|
|
|
# opkg-utils: opkg-build and opkg-make-index, the UPSTREAM tools that build an
|
|
# .ipk and index a feed. bin/build-packages.sh drives them rather than
|
|
# assembling packages itself -- an earlier revision of this work hand-rolled an
|
|
# ar-and-two-tarballs script, and the answer to "is there not already something
|
|
# for this" is yes, this.
|
|
#
|
|
# PINNED BY COMMIT, NOT BY TARBALL, and that is upstream's doing rather than a
|
|
# preference: opkg-utils has no release tarball anywhere. git.yoctoproject.org
|
|
# is its home and has cgit snapshots DISABLED (every format returns "Unsupported
|
|
# snapshot format"), downloads.yoctoproject.org carries opkg but not opkg-utils,
|
|
# and the GitHub mirror at shr-project/opkg-utils last saw a commit in 2012 and
|
|
# carries no tags. So this is a git sha -- which is a content hash of the whole
|
|
# tree, the same guarantee the sha256s above give, expressed in git's own
|
|
# spelling. bin/fetch-assets.sh clones and then verifies HEAD against it.
|
|
#
|
|
# 68a969f is tag 0.7.0. Bump by moving the tag and the sha together.
|
|
OPKG_UTILS_VERSION="0.7.0"
|
|
OPKG_UTILS_COMMIT="68a969f0e867ace0d94faf8ebe7c7bb67f59d386"
|