memlnaut-nisps/scripts/setup-firmware-toolchain.sh
monkey-w1n5t0n 68d4cc4017 build(firmware): migrate to PlatformIO and vendor memllib (plan §5)
One cut, no dual path. Closes ALIGNMENT defect 3 ("Arduino-CLI build
machinery is actively hostile") and vision bullet 4.

platformio.ini carries 16 [env:], one per variant, each passing
-DMEMLNAUT_MODE_TYPE; selftest passes -DNISPS_SELFTEST=1 instead. The env list
IS the registry now — the .ino comment-registry and the NISPS_ST_* token-paste
table are deleted rather than migrated. L12 noted that table was already
silently missing the currently-shipped SLPWorkshop variant, which is the whole
argument against having a second list.

Also deleted: the Python/sed machinery that rewrote the COMMITTED .ino on every
build, the sketch symlink forest, the global TFT_eSPI User_Setup.h mutation
(now -D flags — TFT_eSPI's own documented PlatformIO recipe), the UF2
boot-mount detection stack (upload_protocol=picotool talks to the bootloader
directly), and build-firmware-arch.sh entirely. Scripts 683 -> 435 lines.

memllib is vendored at lib/memllib/ from upstream e291192; no submodules
remain. VENDORED.md records provenance and the re-sync procedure.

S9: a firmware-build CI job compiles three representative envs against a cached
toolchain and reports per-variant flash/RAM. Firmware is in an automated gate
for the FIRST time. The old ci.yml comment justified excluding it as "low
verification value" — an assessment that did not survive contact, since the
SelfTest variant sat broken for an unknown period calling a DisplayDriver
method that did not exist at the pinned memllib commit, and nothing noticed
because nothing built it.

Verified: all 16 envs build from an empty cache, each within ~520 bytes of the
arduino-cli binary it replaces, flash and RAM. Measured as .text+.rodata /
.data+.bss+vector+uninitialized — NOT PlatformIO's console line, which
double-counts .data on this board. This does not prove the hardware boots; no
flash+smoke test was possible and that stays an operator chokepoint.

  slpworkshop 248232/145028   pafsynth 256880/149716   selftest 216228/17960
  (all 16 in the CI log format; none exceeds 2% of a 16 MB flash)

Two traps recorded so nobody rediscovers them: vendoring memllib's subdirs
without a src/ wrapper makes PlatformIO's library builder silently compile
NOTHING while still linking; and project build_flags land BEFORE the
framework's own -std=gnu++17 -Os, so build_unflags is required.

CORRECTION carried in this commit: the firmware sizes in c19d846's message and
the first version of the memllib recon doc were wrong — SLPWorkshop 145348,
PAFSynth 145300, SelfTest 141840. They came from building variants in sequence
through a SHARED incremental arduino-cli build directory, which reused stale
objects and under-reported by ~75 KB. Clean-cache rebuilds of the identical
commit give 216736/18492 for SelfTest. The real cost of the memllib upstream
bump is +216 bytes flash, not +316. Never measure firmware size through a
reused build dir.

HISTORY NOTE: this commit and the docs commit before it were rebuilt (force-push,
2026-07-21) so that each contains only what its message describes. The first
versions had the firmware deletions stranded in the docs commit by a shared-index
race between concurrent agents; content is byte-identical to the originals.

Gates: run-all-tests.sh ALL GREEN (nisps/ untouched by this change beyond
include paths); 16/16 pio envs build.
2026-07-21 20:17:58 +02:00

67 lines
2.8 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# setup-firmware-toolchain.sh — bring-up check for the MEMLNaut firmware
# PlatformIO build. Idempotent: safe to re-run.
#
# There is very little left to "set up": memllib is vendored into
# firmware/MEMLNaut-NISPS/lib/memllib (no submodule to init), and PlatformIO
# bootstraps its own platform + toolchain + libraries (TFT_eSPI, TFT_eWidget,
# MIDI Library, all version-pinned in platformio.ini) into ~/.platformio on
# first build — no global Arduino library-directory mutation, no manual
# TFT_eSPI User_Setup.h copy (that config is now `-D` build flags in
# platformio.ini).
#
# This script just:
# 1. Checks `pio` (PlatformIO Core) is reachable.
# 2. Optionally compiles the `selftest` variant to verify the whole chain
# (downloads ~1-2 GB of platform/toolchain packages on first run).
#
# Usage:
# scripts/setup-firmware-toolchain.sh # verify via a SelfTest build
# scripts/setup-firmware-toolchain.sh --no-build # just check `pio` is reachable
#
# This machine uses nix. If `pio` isn't already on PATH, run this script (and
# the other firmware scripts) through:
# nix-shell -p platformio-core --run 'scripts/setup-firmware-toolchain.sh'
# NOT `nix-shell -p platformio` — that package wraps the CLI in a bubblewrap
# FHS sandbox that fails under containerised/sandboxed shells (no working user
# namespace). `platformio-core` is the same CLI, unwrapped.
set -euo pipefail
DO_BUILD=1
for arg in "$@"; do
case "$arg" in
--no-build) DO_BUILD=0 ;;
-h|--help) sed -n '2,33p' "$0"; exit 0 ;;
*) echo "unknown arg: $arg" >&2; exit 2 ;;
esac
done
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=./firmware-common.sh
source "$SCRIPT_DIR/firmware-common.sh"
log() { printf '\n\033[1;36m==> %s\033[0m\n' "$*"; }
die() { printf '\033[1;31merror: %s\033[0m\n' "$*" >&2; exit 1; }
log "Checking for PlatformIO Core (pio)"
ensure_pio
log "pio found: $(command -v pio) ($(pio --version 2>&1 | head -1))"
if [[ "$DO_BUILD" -eq 1 ]]; then
log "Verifying: compiling the SelfTest firmware (first run downloads the RP2350 platform/toolchain into ~/.platformio — hundreds of MB, be patient)"
if "$SCRIPT_DIR/build-firmware.sh" selftest; then
log "SelfTest firmware built successfully"
echo
echo "Next: flash it with"
echo " scripts/flash-firmware.sh selftest"
echo "or build a normal mode, e.g. scripts/build-firmware.sh pafsynth"
echo "or build every variant: scripts/build-firmware.sh --all"
else
die "SelfTest build failed — see the pio output above. This is a compile error to debug, not a missing-toolchain problem (pio bootstraps its own toolchain)."
fi
else
log "Setup check complete (build skipped). Verify with:"
echo " scripts/build-firmware.sh selftest"
fi