CircuitPython unix-port RingIO build failure¶
Covers why building the CircuitPython unix port with VARIANT=standard fails out of the box, and why scripts/prepare_circuitpython.py passes a workaround flag. The decision rationale (why we build standard with the flag rather than switching variants) lives in Decision 0017; this page is the forensic detail behind it.
This only matters if you build the CP unix port from source (the cross-runtime test path does). Nothing here affects on-device CircuitPython.
Symptoms¶
The build fails, and how it fails depends on the CP version:
- CP 10.1.4 and earlier:
objringio.ois missing frompy/py.mk, soobjringio.cis never compiled and the compile bug stays hidden. Butpy/modmicropython.c:217referencesmp_type_ringio, so the linker fails with an undefined-symbol error for_mp_type_ringio. - CP 10.2.0:
objringio.owas added back topy/py.mk, so the build system compilesobjringio.cand the long-standing compile bug surfaces directly as aclangerror (use of undeclared identifier 'iget', etc.).
The 10.2.0 change exposed a pre-existing compile bug; it didn't create a new one or fix anything. Verified by diffing py/ringbuf.h between the two versions: identical.
Root cause¶
CircuitPython's ringbuf API has diverged from MicroPython's. CP's ringbuf_t doesn't expose the iget / iput members, and CP's py/ringbuf.{c,h} doesn't provide ringbuf_avail / ringbuf_memcpy_get_internal. CP's objringio.c was inherited from MicroPython and references all four, so it cannot compile against CP's narrower ringbuf API without first back-porting the missing surface or rewriting objringio.c.
The standard variant sets MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES, which enables MICROPY_PY_MICROPYTHON_RINGIO by default (mpconfig.h:1387). modmicropython.c:217 then references mp_type_ringio, but the Makefile never compiles the object file that defines it, hence the linker error on older CP, and the compile error once py.mk compiles the file again.
Why CircuitPython CI doesn't catch it¶
- CI builds
VARIANT=coverage, notstandard:.github/workflows/run-tests.yml:48runsmake -C ports/unix VARIANT=coverage -j4. - The coverage variant explicitly disables RingIO:
ports/unix/variants/coverage/mpconfigvariant.h:52setsMICROPY_PY_MICROPYTHON_RINGIO (0)with the comment "CIRCUITPY-CHANGE: Disable things never used in circuitpython". tools/ci.shis dead code: inherited from the MicroPython fork, never referenced by any CircuitPython GitHub Actions workflow.
The bug only surfaces when building VARIANT=standard, which nobody in the CircuitPython project does in CI.
CircuitPython does not use RingIO¶
A full-tree search confirms RingIO is never used in CircuitPython-specific code: no references in shared-bindings/, shared-module/, ports/ (only the coverage variant's disable), py/circuitpy_mpconfig.h, py/circuitpy_defns.mk, or tests/. The only RingIO code in the tree is inherited from upstream MicroPython: py/objringio.c, py/obj.h:893 (extern declaration), py/modmicropython.c:216-217 (conditional registration), and py/py.cmake:101 (CMake source list).
RingIO is a MicroPython-only feature (micropython.RingIO()), a lock-free single-producer/single-consumer ring buffer designed for ISR-to-main-loop communication. CircuitPython forbids ISR usage and has its own I/O abstractions, so the type has no purpose in the CircuitPython ecosystem.
Upstream status¶
This is a genuine CircuitPython bug in both 10.1.4 (linker surface) and 10.2.0 (compile surface). A complete upstream fix would require either back-porting MP's ringbuf helpers (iget / iput + ringbuf_avail / ringbuf_memcpy_get_internal) into CP's py/ringbuf.{c,h}, or rewriting objringio.c against CP's narrower ringbuf API. Both are CP-side patches. No upstream fix yet.
Because CircuitPython doesn't use RingIO and its coverage variant already disables it, the practical impact is limited to anyone building VARIANT=standard from source. When CircuitPython fixes this upstream (or we move to a CP version that does), the workaround flag becomes a no-op (setting a value that is already 0 has no effect), so no cleanup is needed on our side.