mirror of
https://github.com/Klipper4FlashForge/firmware.git
synced 2026-10-21 12:52:16 -05:00
worktree-timelapse-test-gcode
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b98552386b |
No FlashForge component ships; patch.sh is payload.sh
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 |
||
|
|
4850be432c |
Docs: say what is there now, not what the last three commits removed
Deleting test/ and anvil.conf left claims behind in nine files. Every one of
these was present tense about something that no longer exists.
THE CHELPER SYMBOL GATE, in three places that each described it as live:
notes/20-klipper-fork.md said pkgs/klipper gates the .so on "both the ELF
flags and test-chelper.py's symbol check". It
gates on neither now: the ABI is asked once of the
installed filesystem in qa/replica/test_abi.py,
and the single-source rule -- the .so is compiled
from the chelper sources of the tree it ships -- is
the whole defence. The page says that instead.
notes/85-packaging.md described the KLIPPER_FORK fallback the script no
longer had; the script itself is gone too.
qa-migration.md "What survives in test/" listed both the 28 unit
tests and test-chelper.py as surviving. It is
"What survived in test/, and then did not", and it
names what went uncovered rather than leaving that
to be discovered.
ANVIL.CONF, in the two notes that still read it at runtime:
notes/80-s6-migration.md is a dated plan, so it keeps its phases and gains
a "Where this ended up" note: anvil.conf and every
MOD_* switch were removed, so the phases that
source it describe an intermediate state, and the
case-*.sh gates they name are qa/replica/ modules.
notes/85-packaging.md predicted seed/ emptying via a postinst that seeds
anvil.conf.default. It emptied by anvil.conf being
deleted instead. Its payload allowlist said six
entries including anvil.conf and bin/busybox; the
real one in test_ipk.py has five and neither.
THE TWO STANDALONE TREES under tools/, stale before any of this and now fixed:
tools/python/README.md and tools/supervisor/README.md both told the reader to
run their gate with `test/integration/printer-exec.py` over a case-*.sh, and
one offered a `make test-python` target. None of the three has existed for
several commits. Both now point at qa/replica/, which installs the real package
and asks more than hand-feeding a tarball to a case script could. The four
places tools/python/README.md narrates what case-python.sh proves are past
tense, since that is now a record of how the measurements were taken.
versions.env's sqlite3 note pointed at the same dead target.
NAV: every notes/ page was listed except 85-packaging.md, and qa-migration.md
was reachable only by following a link out of Testing, Building or How it
works. Both are in the nav now, which also clears the two "not included in the
nav" lines from every build. .venv/ is gitignored -- docs/requirements.txt
tells you to make one right there in the tree.
Verified: `mkdocs build --strict` is clean and no longer reports pages outside
the nav. qa/static is 123 passed, its 110 errors the same missing
vendor/opkg-utils as before. No .md file is read by any lane, so the check that
matters here is the build.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bLGYpVAeVzAX6NeAxcU42
|
||
|
|
4ce928f160 |
The last two artefact ABI gates go; the toolchain check stays
Follow-on to |
||
|
|
214a4e58b9 |
anvil-core owns firmwareExe and start.sh; kill the 3.8.2 myth
Three things, all downstream of klippy having moved to $MODDIR and our own
CPython 3.13.
SECTIONS 8 AND 9 ARE GONE. Both files install at $MODDIR/prog/ and
anvil-link-prog.sh points the stock paths at them -- from run-append.sh on a
flash and from anvil-core's postinst on `opkg upgrade anvil-core`. Nothing
execs either between run.sh distributing the component and link-prog running,
so the component copy bought no ordering. It cost, though: our firmwareExe
with no payload behind it logs "no anvil-env.sh", finds no s6-svscan and then
`while true; do sleep 3600; done` -- a printer that boots to a blank screen for
ever and never reaches app_startup.sh's own recovery. Absent, that recovery
restores a firmwareExe from a version directory. So patch.sh now REMOVES both
from the component: the stock component carries them, and deleting the two cp
lines alone would have shipped FlashForge's originals.
SECTION 5c IS GONE. It did no work -- two du prints and a comment whose first
line was the falsehood below.
THE FALSEHOOD. "klippy runs on the stock 3.8.2, started by
/usr/prog/klipper/start.sh" had spread well past patch.sh, and it had reached
things people follow:
- docs/toolchange.md told owners to scp the ff_*.py extras to
/usr/prog/klipper/klippy/extras/ -- the wrong partition -- and warned that
an OTA would delete them there. Same wrong path in three ff-*.cfg headers
and in ff_toolchange.py.
- versions.env labelled our CPython 3.13 and its eighteen packages
"SHIPPED BUT NOT USED".
- docs/how-it-works.md said Moonraker runs on python3.8, contradicting line
126 of the same file.
All corrected. Historical notes keep their history and get a [Superseded: ...]
marker instead -- including 80-s6-migration.md's "s6-rc-compile is not
shipped", which pkgs/3rdparty/s6-rc/build.sh contradicts deliberately.
Found while reviewing: every docs/ reference to the ff-*.cfg pointed at
pkgs/anvil-core/payload/config/, which does not exist -- they are
anvil-klipper-config's. 28 references across 9 files, several of them broken
markdown links on the published site. All 24 relative links under docs/ now
resolve.
Gates: verify.sh syntax-checks prog/start.sh and prog/firmwareExe out of the
payload (firmwareExe was never syntax-checked before) and fails if the
component carries either. A new replica test asserts both stock paths are
symlinks into $MODDIR/prog and do not dangle. One existing replica test stubbed
firmwareExe by redirecting into $FE, which now writes THROUGH the symlink into
the packaged wrapper; it moves the link aside instead.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01La5MaDKqTW675k5fsXsP6S
|
||
|
|
8cc92e8266 |
A wheel could only be built while three scratch trees happened to coexist
That is why bin/patch.sh section 5c was 825 lines and why a Pillow bump
rebuilt CPython. Cross-building an extension module needs the untrimmed
staging tree (INCLUDEPY points into it), the private sysroot of static C
libraries (pillow links zlib, cffi links libffi) and an x86-64 build-python
of the same version -- and all three existed only mid-section, so the wheels
had to be built there too, on a cache with two stamps that invalidated each
other.
Each of those three is now a durable thing: anvil-python-dev carries the
headers, pkg_deps fills each recipe's own sysroot from the feed, and
pkg_buildpython caches one build-python for all nineteen recipes. So the
coupling goes away with them -- `make packages PKG=python-pillow` builds
Pillow.
pkg/python -> anvil-python + anvil-python-dev
pkg/python-<name> x18 -> anvil-python-distro, anvil-python-pillow, ...
Three verbs in pkg/lib.sh, shared by all nineteen rather than one per awkward
project: pkg_buildpython provides the build-python, pkg_pytarget points its
sysconfig at the target headers in the sysroot, pkg_pywheel builds one wheel
and unpacks it into the staging site-packages. greenlet's gcc 7.2 designated
initializers, lmdb's LMDB_FORCE_CPYTHON and pillow's build_ext options are
recipe lines and a PKG_PY_SETUP_ARGS knob, not three more verbs.
Eighteen versions that were invisible are now in the feed index, anvil-moonraker
declares the thirteen packages it imports, and a printer that does not want
gcode thumbnails can leave Pillow uninstalled.
PY_STAMP, PYPKG_STAMP and PY_BUILD are gone: pkg_stamp derives the key from
PKG_BUILD_DEPENDS, and bin/fetch-assets.sh asks pkg_needs instead of
re-deriving a stamp bin/patch.sh also derived. Two of its four toolchain
conditions were that second spelling.
Measured:
* 40 packages; 959 site-packages files, none owned by two packages
* 12 mipsel extension modules -- the count the old gate demanded
* every Depends resolves inside the feed (24 declare one, 0 unsatisfiable)
* two cold builds byte-identical, with work/pkg, work/.py-host and the
unpacked toolchain deleted in between
* 233 static tests, 4 new: the PYPKG_LIST/recipe agreement both ways, no
version pinned twice, patch.sh builds every package, and no Depends
naming a package no recipe produces
Not verified here: the replica suite. It needs the stock FlashForge package,
which the packaging lane deliberately does without.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
813973620c |
The payload carries a CPython 3.13 with a working sqlite3
Nothing runs on it. FF_PYTHON still points at FlashForge's 3.8.2, and the
comment beside it now says at length why changing that line is a one-line way
to break the whole userspace: klippy, Moonraker and ff-startup.py import
third-party C extensions -- tornado, lmdb, cffi, greenlet, pillow, libnacl --
that exist on this printer only as mipsel objects built against 3.8. None has
been cross-built for 3.13 yet. The interpreter ships ahead of the switch for
the same reason s6 did: it puts the artefact on real printers where it can be
measured, and it leaves the switch a one-file change rather than a build
change and a boot change at once.
Why it exists at all: the Moonraker pin is frozen at commit 9d0d09d, December
2023, for exactly one reason -- this firmware's Python has no _sqlite3 and
there is no libsqlite3 anywhere on the box, while Moonraker v0.9.0 moved its
database off lmdb onto sqlite. That is a cost paid at every release. The gate
proves the premise rather than assuming it: the stock 3.8.2, given the library
path it needs to start, imports json and zlib fine and cannot import sqlite3.
Built by bin/patch.sh from eight pinned sources with the Ingenic toolchain
that already builds c_helper.so -- gcc 7.2, glibc 2.29, cross to
mipsel-linux-gnu. Not musl, and this is not a preference: a musl interpreter
cannot dlopen a glibc c_helper.so, which is exactly how klippy loads it.
Three things about the build are load-bearing and all three were found the
hard way:
* -EL -mnan=2008 must reach the LINK lines, not only the compile lines.
They are baked into PATH wrapper scripts around the gcc driver rather than
passed as CFLAGS, because trusting eight separate build systems to forward
flags to their linkers is how you get legacy-NaN objects that the printer
refuses to load.
* _sqlite3 disappears silently without LIBS="-latomic -lm". A static
libsqlite3.a carries no DT_NEEDED on libm, so configure's
sqlite3_bind_double probe fails to link and CPython records the module as
"missing" -- a probe failure, so nothing in the build output says why. The
build now hard-fails when _sqlite3 is absent rather than shipping an
interpreter whose whole purpose is gone.
* OpenSSL's linux-mips32 target hardcodes -mips2, which collides with this
toolchain's -mfp64. -mips32r2 as a user cflag lands after the target's and
wins.
Built --disable-shared, unlike FlashForge's own 3.8.2. Static libpython and
static dependencies mean the shipped tree contains no shared object of ours at
all: nothing to version-skew, nothing that can resolve to a /usr/prog copy by
accident, and no new mandatory LD_LIBRARY_PATH entry -- which matters here
specifically, because removing /usr/prog version strings from anvil-env.sh is
the point. The usual objection to static, that C extensions cannot find the
interpreter's symbols, was tested rather than assumed: an out-of-tree
extension cross-built against the staged include/ imports and runs on the
printer with no libpython mapped.
It installs into $MODDIR itself, --prefix=/usr/data/anvil, the same prefix
root s6 uses: bin/python3.13 beside bin/s6-svscan, stdlib in lib/python3.13
beside lib/. One install, not two trees.
That creates a hazard worth naming, because anvil-env.sh PREPENDS $MODDIR/bin
to PATH so s6-svscan can find s6-supervise. `make install` also writes
bin/python3, and a shipped bin/python3 would then sit in front of
FlashForge's for every process that sources anvil-env.sh -- silently handing
klippy and Moonraker an interpreter with none of their extensions. So the
build deletes it and asserts bin/ holds exactly python3.13, verify.sh fails a
package carrying bin/python3, and the gate asks the shell what `python3`
resolves to on anvil-env.sh's own PATH. It answers
/usr/prog/Python-3.8.2/bin/python3, while python3.13 answers ours.
About 28MB and 600-odd files, which takes the install manifest from 70 entries
to 728 -- case-upgrade.sh still passes, which is the check that the manifest
deletion loop scales.
The build image grows a host gcc, which looks redundant beside two
cross-toolchains and is not: cross-building CPython needs a build-python of
exactly the same version to freeze modules and byte-compile the stdlib, so
patch.sh builds an x86-64 3.13 from the same tarball first.
tools/python/ keeps the measurement build and what it cost, as
tools/supervisor/ does for s6. Two gaps recorded there rather than lost: the
printer has NO CA certificates -- /etc/ssl/certs exists and is empty, so TLS
negotiates and verifies nothing, which is true of the stock interpreter too --
and libatomic.so.1 is a new runtime dependency, present on the rootfs,
measured, and removable by linking it statically if that is ever wanted.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|