mirror of
https://github.com/Klipper4FlashForge/firmware.git
synced 2026-10-21 21:02:16 -05:00
pkg/ -> pkgs/, and the thirty-four recipes that build a pinned tarball and
carry no files of this repo move down a level into pkgs/3rdparty/. What is
left at the top is the four components a person actually edits: anvil-core,
klipper, moonraker, helixscreen.
THE LINE IS MECHANICAL, NOT EDITORIAL, and that is why it can be a directory
rather than a field in pkg.conf. "Do we actively modify it" drifts -- the day
somebody patches zlib nobody would agree which side it belongs on, and the
answer would be a rename touching CI and docs decided by taste. "Does it carry
files of ours" is a fact about the tree: it is exactly whether the recipe has
a payload/, prog/ or seed/, checkable in one assertion, and
test_recipe_layout.py now demands the move in both directions -- a 3rdparty
recipe that grows one of the three must come up, and a top-level recipe with
none of them must go down, or the top level slowly refills and the split stops
meaning anything.
ONE FUNCTION KNOWS THE TWO DEPTHS. pkgs/lib.sh's pkg_dir resolves a recipe id
to its directory and nothing else spells either path -- not a recipe, not
bin/build-packages.sh, not a test. Names stay unique across both levels
because pkg_out, pkg_stamp and the .ipk filename are all keyed by the bare
name; a duplicate would resolve to whichever level is searched first and
build the wrong thing silently, so that is a test too.
Recipes now source `. ./bin/common.sh` instead of counting `..` from $0.
Depth-counting would have needed two spellings for two levels, and it was
never buying anything: `. pkg/lib.sh` on the next line already required the
working directory to be the repo root.
A SECOND SILENT-SHRINK BUG, and this one was live. qa/static's _files()
expanded a list of globs and returned whatever matched, so "pkgs/*/build.sh"
quietly stopped covering thirty-four recipes the moment they moved -- the lane
stayed green, and the only visible sign was a test count dropping by 34 in a
run nobody was counting. _files() now refuses a pattern that matches nothing.
That is the same failure the ash-compatibility check had a guard for and the
syntax check did not, which is why the guard reads the way it does.
AND ONE PACKAGE WAS SHIPPING PYTHON BYTECODE. anvil-core stages a directory of
.py helpers wholesale, so any test that imported one left a __pycache__ beside
it -- gitignored, invisible in a diff, copied by cp -a like anything else. The
package's contents depended on whether pytest had been run on the machine that
built it: two builds of one commit, different sha256, cause nowhere in the
tree. What it shipped was worthless as well as unstable, compiled by the build
image's python 3.11 for a printer running the 3.13 this repo cross-builds. The
sweep is in pkg_ship now, once, and the two hand-written copies in
pkgs/klipper and pkgs/moonraker are deleted -- the trap is set for any recipe
that stages a tree of .py files, and the two recipes that had hit it had each
solved it locally while the third, which had not, was the one shipping.
Measured:
* the rename changes no package bytes. Same cached build trees, feed built
with the diff stashed and unstashed: all 41 .ipk match.
* with the bytecode sweep, anvil-core returns to exactly the bytes the
previous commit produced.
* no package in the feed contains a .pyc or a __pycache__.
* make qa-static: 247 passed (236 before this work + 11 layout tests).
* make test: 8 passed, 0 failed, including unpack/patch/pack/verify on the
synthetic stock package. make test-py: 181 passed.
Not explained: anvil-python-dev produced two different sha256 from an
UNCHANGED work/pkg/python at two points today, under code that was identical
both times -- so it is not reproducible from a cached tree, and it is not this
commit's doing (the stashed and unstashed builds above agree on it). Worth a
look; the dev split in bin/build-packages.sh is where to start.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
61 lines
3.6 KiB
Plaintext
61 lines
3.6 KiB
Plaintext
# anvil-python -- CPython, cross-compiled for the printer.
|
|
#
|
|
# WHY THERE IS A SECOND PYTHON ON THIS MACHINE AT ALL. FlashForge built its
|
|
# 3.8.2 without _sqlite3, and that single omission is what pins
|
|
# MOONRAKER_VERSION to a 2023 commit: every Moonraker from v0.9.0 on keeps its
|
|
# database in sqlite. This interpreter has a working sqlite3, which is what
|
|
# eventually unpins it.
|
|
#
|
|
# THE PREFIX IS COMPILED IN, exactly as it is for s6. sys.prefix and the stdlib
|
|
# search that follows from it are baked in at configure time, so moving the
|
|
# directory on the printer breaks the interpreter -- it has to be rebuilt, not
|
|
# renamed. That is also the argument for putting it in $MODDIR with everything
|
|
# else rather than somewhere private: there is one prefix to keep stable, not
|
|
# two.
|
|
#
|
|
# ONLY bin/python3.13 SHIPS, and the name matters. payload/anvil-env.sh
|
|
# PREPENDS $MODDIR/bin to PATH (s6-svscan execs s6-supervise by name off PATH,
|
|
# so it has to), so a bin/python3 of ours would sit AHEAD of FlashForge's for
|
|
# every process that sources it, and anything saying `python3` rather than
|
|
# "$FF_PYTHON" would silently change interpreter. `make install` creates that
|
|
# symlink, plus idle3, pydoc3 and the *-config scripts; build.sh names the one
|
|
# binary it ships and the rest are simply never copied out of the staging tree.
|
|
PKG_NAME=anvil-python
|
|
PKG_VERSION="$PY_VERSION"
|
|
PKG_RELEASE=1
|
|
PKG_SECTION=lang
|
|
|
|
PKG_EXCLUDE=".version"
|
|
|
|
# NO Depends, AND THAT IS A MEASURED CLAIM RATHER THAN AN OVERSIGHT. Every C
|
|
# library this interpreter uses is linked in STATICALLY -- see build.sh -- so
|
|
# the only shared objects it needs are the printer's own libc, libm, libdl,
|
|
# libpthread and libatomic.so.1, all of which are on the stock rootfs. Nothing
|
|
# in this feed has to be installed first.
|
|
PKG_DEPENDS=""
|
|
|
|
# SEVEN LIBRARIES, AND EACH ONE IS EXACTLY ONE stdlib MODULE. openssl is _ssl
|
|
# and _hashlib, sqlite is _sqlite3, zlib is zlib, libffi is _ctypes, xz is
|
|
# _lzma, bzip2 is _bz2, expat is pyexpat. build.sh gates all seven by name
|
|
# after the build, because CPython's answer to a library it cannot link is to
|
|
# record the module as absent and CARRY ON -- a silent success that produces an
|
|
# interpreter missing the one module this package exists for.
|
|
PKG_BUILD_DEPENDS="openssl sqlite zlib libffi xz bzip2 expat"
|
|
|
|
# THE HEADERS ARE THE POINT OF THE DEV SPLIT HERE, more than anywhere else in
|
|
# this feed. The eighteen pkgs/3rdparty/python-* recipes cross-compile C extensions
|
|
# against them, and before this package existed they reached them by building
|
|
# inside bin/patch.sh at the one moment an untrimmed staging tree happened to
|
|
# be on disk. A -dev package is that moment made durable: the headers are in
|
|
# the feed, a wheel recipe names `python` as a build dependency and gets them,
|
|
# and a printer -- which builds no extension modules -- installs none of it.
|
|
#
|
|
# config-3.13-* comes along because sysconfig's LIBPL points into it, and a
|
|
# sysconfig answering with a directory that does not exist is the kind of thing
|
|
# a future setuptools notices. libpython3.13.a is deleted in build.sh rather
|
|
# than shipped inside it: 35MB of static archive that nothing links.
|
|
PKG_DEV_FILES="include lib/pkgconfig lib/python$PY_MM/config-$PY_MM-*"
|
|
PKG_DEV_DESCRIPTION="CPython headers and build configuration for mipsel. This is what the pkgs/3rdparty/python-* recipes compile their C extensions against; nothing installs it on a printer."
|
|
|
|
PKG_DESCRIPTION="CPython $PY_VERSION for the printer, with sqlite3, ssl, lzma, bz2, ctypes and expat linked in statically. Installs as bin/python3.13 -- never as python3, which would shadow the stock interpreter on PATH."
|