Files
firmware/config.env.example
Oleksandr ShyshatskyiandClaude Fable 5 212d3a1efd A fork build without a fork is now impossible to ship
v20260824-nova-kakhovka went out without the Klipper fork: release.yml set
KLIPPER_FORK="", bin/patch.sh answered with "(skip) Klipper: keeping stock
tree", and every gate stayed green because every Klipper check was
conditional on files the broken package simply did not contain. On an
already-modded printer the stock 0.12-era overlay half-overwrote the v0.13
tree and klippy died at connect: "'void(*)(struct stepper_kinematics *,
double, double, double)' expects 4 arguments, got 3" -- a v0.12 caller
against the v0.13 cdef of extruder_set_pressure_advance (upstream
c84d78f3f). Note for the next reader of such a traceback: an arg-count
TypeError is a MIXED KLIPPY TREE, python against python; a stale
c_helper.so shows up as AttributeError instead, because cffi resolves
symbols lazily.

The fork now travels like every other asset. versions.env pins the creator5
commit and the Ingenic gcc 7.2.0/glibc 2.29 toolchain (the X2000's own;
Debian's mips crosses are big-endian or legacy-nan), fetch-assets.sh
downloads both by sha256, and patch.sh extracts the pinned tarball whenever
KLIPPER_FORK is not a local checkout -- which is exactly what CI now does,
with the KLIPPER_FORK="" lines gone from both workflows and vendor/ cached
on the pin file. c_helper.so is cross-compiled from the chelper sources of
the very tree being shipped whenever it is missing or older than them, so
the stale-.so class dies too; test/test-chelper.py returns from 3a28fdf's
grave to prove every cdef'd function is exported, and runs both in patch.sh
and in verify.sh against the extracted package. BUILD_KLIPPER=fork with no
tree is a hard build failure now; stock has to be asked for by name.

verify.sh also stops trusting `echo "$LIST" | grep -q`: under pipefail,
grep exiting at an early match SIGPIPEs the echo and the check reports 141
-- a race that stayed invisible until the fork tree tripled the payload
listing, then intermittently declared Mainsail and Moonraker missing from a
package that carried both. Herestrings have no pipe to break.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 13:52:20 +03:00

113 lines
5.9 KiB
Bash

# creator5-fw-builder — build configuration
# Edit paths to match your machine, then run `make build`.
# ---- identity of the package you are building -------------------------------
MOD_NAME=anvil # goes into the .tgz filename
MOD_VER="" # empty = today's UTC date, e.g. 20260823.
# Pin it to rebuild an old release, or for a
# second release on the same day (20260823b).
# Version stamped on the software component. Empty = keep the stock number
# (recommended). The installer wipes every other version dir before renaming
# its temp dir, so a collision is not a problem; a suffix like 1.9.7-mod is
# only useful if you want to see at a glance that a machine is modded.
SW_VER=""
# ---- which printer is this for? --------------------------------------------
# Creator5Pro / 0029 or Creator5 / 0028
# Find it on the printer: Settings -> About, or in
# /usr/data/firmwareRes/config/general.json ("machineName").
#
# This MUST match the model the stock package was built for. A package's
# runFirmwareExe.sh carries its own MACHINE=/PID= gate and refuses to install
# on the other model, so a Pro cannot be recovered or modded with a non-Pro
# package (and vice versa).
TARGET_MACHINE=Creator5Pro
# Override for one command: MODEL=Creator5 make build
# Build both at once: make release
# ---- inputs (sources you already have on this machine) ----------------------
# Everything below is relative to this. Point it wherever you keep the
# firmware and the source repos; nothing here is committed (config.env is
# gitignored, this file is the template).
DESKTOP="$HOME/Desktop"
# Stock OTA packages, ONE PER MODEL. They are not interchangeable: each
# carries a different firmwareExe and refuses to install on the other model.
# The one matching TARGET_MACHINE (or MODEL=) is selected automatically.
STOCK_TGZ_CREATOR5PRO="$DESKTOP/Creator5-1.9.7-1.2.9-20260810/Creator5Pro-1.9.7-1.2.9-20260810.tgz"
STOCK_TGZ_CREATOR5="$DESKTOP/Creator5-1.9.7-1.2.9-20260810/Creator5-1.9.7-1.2.9-20260810.tgz"
# Set this only to force one specific package regardless of model.
STOCK_TGZ=""
# A local checkout of the Klipper fork (branch creator5), for working on the
# fork itself. LEAVE IT UNSET to build what a release builds: the commit
# pinned in versions.env, fetched into vendor/ by bin/fetch-assets.sh, with
# c_helper.so cross-compiled from those same sources by the pinned Ingenic
# toolchain. A checkout gets the same treatment -- its c_helper.so is rebuilt
# whenever it is missing or older than the chelper sources beside it.
#KLIPPER_FORK="$DESKTOP/klipper"
# The toolchanger mod (klippy-extras + configs + helixscreen db entry) used to
# be a TOOLCHANGE= path to a creator5-toolchange checkout. It now lives in this
# repo under payload/klipper/, so there is nothing to set. BUILD_TOOLCHANGE=0
# here still turns it off.
# Mainsail, the HelixScreen build for the Creator 5 (MIPS static) and Moonraker
# are NOT set here. They are downloaded on demand into vendor/ by
# bin/fetch-assets.sh, pinned by version and sha256 in versions.env, so the
# repo carries no binaries. Set any of these ONLY to build against your own
# local copy.
# NOTE: the path is still checksummed against versions.env, and on a mismatch
# fetch-assets.sh OVERWRITES it with the pinned release -- SKIP does not save
# you, it re-downloads too. To build against your own file, also put ITS
# sha256 in versions.env; only an exact match is left alone ("cached"):
#HELIX_TGZ="$DESKTOP/helixscreen-creator5-v0.99.115.tar.gz"
#MAINSAIL_ZIP="$DESKTOP/mainsail.zip"
#MOONRAKER_TGZ="$DESKTOP/moonraker-v0.9.3.tar.gz"
# Optional extras -- leave empty to skip that feature
BUSYBOX_BIN="$DESKTOP/creator5/busybox" # optional richer busybox
# ---- what the installed image does at boot (baked into anvil.conf) ----------
# RUNTIME switches: they are written into /usr/data/anvil/anvil.conf, which the
# printer re-reads at every boot, so they can be changed over ssh afterwards.
#
# The BUILD_* flags that decide what goes INTO a package (BUILD_KLIPPER,
# BUILD_MAINSAIL, BUILD_MOONRAKER, BUILD_HELIX, BUILD_TOOLCHANGE) are not set
# here: bin/common.sh defaults them to the full firmware, and setting one in
# this file overrides that. Only touch them if you want a piece left out.
MOD_WEB=1 # 1 = start nginx (Mainsail) + moonraker
MOD_CAM=1 # 1 = start mjpg-streamer on :8080 (firmwareExe used to)
MOD_UI=1 # 1 = start HelixScreen on the touchscreen
MOD_SSH=1 # build-time only: 1 = set a root password.
# ssh itself is stock S50dropbear, always up.
MOD_WIFI=1 # 1 = bring up wlan0 (firmwareExe used to do this)
# ---- root login shipped in the image ---------------------------------------
# This is the whole "enable ssh" feature. The stock rootfs already runs
# dropbear from /etc/init.d/S50dropbear, so port 22 is ALREADY open on a
# stock printer -- there is simply no published root password.
#
# Empty = the INSTALLER picks a random password on the printer -- on the
# FIRST install only, updates keep the one the machine already has -- and
# writes it to anvil-password.txt on the USB stick you flashed from. Every
# machine gets a different one, which a hash baked into a shared package
# never could.
# Set one here to choose your own: make passwd
# (it prompts, and runs inside the build image -- the same python everywhere,
# where a host openssl may lack `passwd -6` entirely)
ROOT_PW_HASH=""
# ---- crypto (from /usr/prog/bin/unTar on the printer) -----------------------
FF_KEY='FFP0331&*%root'
# ---- the printer replica -----------------------------------------------------
# Nothing here. The replica's settings -- the factory image, the partition
# sizes, a prebuilt printer image -- live in test.env, because they exist only
# for the tests and must never reach a printer:
#
# cp test.env.example test.env