Skip to content

EPIC-08: honest builds - #8

Merged
diegoparrilla merged 6 commits into
release/v1.1.0from
epic/08-honest-builds
Sep 15, 2026
Merged

diegoparrilla merged 6 commits into
release/v1.1.0from
epic/08-honest-builds

Conversation

@diegoparrilla

Copy link
Copy Markdown
Contributor

First epic of v1.1.0: every build either produces the firmware it claims to, or fails.

What changes

  • Fail fast. build.sh, rp/build.sh and target/atarist/build.sh stop at the first failed step. Before, an m68k failure let the RP build embed the committed target_firmware.h, and a C or link failure let build.sh copy an older UF2 from rp/dist and still write a JSON for the new version.
  • Real build types. release is CMake Release with DEBUG_MODE=0. debug is the same build with DEBUG_MODE=1, adding only DPRINTF traces on the UART console. Both are case-insensitive. RP_CMAKE_BUILD_TYPE=MinSizeRel overrides only the CMake type, to compare against what shipped until now.
  • FF_FS_TINY no longer follows _DEBUG, so debug and release builds use the same FatFs objects.
  • Symbols stay in rp.elf. --strip-all is gone; the flashed image is unchanged.
  • Dead build configuration removed: the clang-tidy block that never ran, the duplicate settings.c compile, and pico_set_binary_type(rp).
  • VS Code gets release and debug variants with DEBUG_MODE and the development UUID set.
  • CI uses ARM GNU Toolchain 14.2.rel1 instead of Ubuntu's compiler, builds both types, posts a size report, and uploads rp.elf with its map. Release builds attach them to the GitHub release, not to S3.
  • CLAUDE.md describes the new build.

Verified locally

Check Result
New scripts with RP_CMAKE_BUILD_TYPE=MinSizeRel, fixed RELEASE_DATE, against the same build before any change rp.uf2 byte-identical
./build.sh pico_w release … and ./build.sh pico_w DEBUG … with the m68k step in Docker Both succeed; JSON MD5 matches the UF2; version v1.1.0
Every translation unit, both types -O3 and -DNDEBUG; -D_DEBUG correct everywhere it is read
m68k syntax error Exit 2, dist/ empty
BOOT.BIN over 10 KB Exit 5, dist/ empty
C compile error Exit 2, dist/ empty
Link error Exit 2, dist/ empty

The first fail-fast run stopped at a stale .git/modules/pico-sdk/index.lock from April. The old script had been skipping the pico-sdk pin silently since then. Anyone with an old clone may hit the same lock once.

Build Heap Code copied to RAM Flash used
release 36,132 40,249 569,408
debug 27,916 44,181 617,788

Release is known not to run on hardware yet; later v1.1.0 epics address that.

Still to do before merging

  • Hardware: flash the MinSizeRel override build and run the smoke check (boot to menu, [G], [U], one HTTP upload and download, SELECT short press).
  • Hardware: flash release and debug once each and record how far they get, with the debug console log.
  • VS Code: pick the debug variant, build, and confirm the configure log shows DEBUG_MODE: 1.

…types (EPIC-08 STORY-01 STORY-02)

A failed step no longer gets stepped over. build.sh, rp/build.sh and
target/atarist/build.sh stop on the first error. Before this, an m68k
failure let the RP build embed the committed target_firmware.h, and a
C or link failure let build.sh copy an older UF2 from rp/dist and write
a JSON announcing the new version.

- rp/build.sh empties rp/dist before building.
- target/atarist/build.sh deletes any previous target_firmware.h and
  checks that firmware.py produced a new one, using python3 when the
  host has no python.
- build.sh falls back to md5 -q when md5sum is missing, as on macOS.

The build types are now what their names say, case-insensitively:
release is CMake Release with DEBUG_MODE=0, and debug is the same
build with DEBUG_MODE=1 for DPRINTF traces on the UART console.
RP_CMAKE_BUILD_TYPE overrides only the CMake build type, to compare
against the MinSizeRel configuration that shipped until now. A
caller-provided RELEASE_DATE is kept, so two builds of one commit can
be compared byte for byte.

FF_FS_TINY no longer follows _DEBUG, so a debug build keeps the same
FatFs objects as a release build.

With the fail-fast in place the first run stopped at a stale
.git/modules/pico-sdk/index.lock from April. The old script had been
skipping the pico-sdk pin silently ever since.
…RY-03 STORY-05)

--strip-all removed the symbol table and debug information from
rp.elf without changing a byte of the flashed image, so crash
addresses could not be decoded and a debug probe could not break at
main. The link keeps --gc-sections only.

Also removed, all without effect on the image:
- the clang-tidy block, which set CMAKE_C_CLANG_TIDY after every
  target existed and so never ran;
- the settings library: settings.c was compiled into it and a second
  time directly into rp, and only the direct copy was linked;
- pico_set_binary_type(rp), which selects nothing because the custom
  linker script takes precedence.

The stdio comment now says what the code does: USB stdio stays for
usbcdc.c, and only debug builds enable UART stdio.

Verified with RP_CMAKE_BUILD_TYPE=MinSizeRel and a fixed RELEASE_DATE:
rp.uf2 is byte-identical to the same build before these changes.
…Y-03)

CMake Tools offered its stock Debug and Release variants, which built
with DEBUG_MODE and APP_UUID_KEY unset: no traces, the default UUID,
and a CMake type the scripts never use. .vscode/cmake-variants.yaml
now defines the same two build types as ./build.sh, both CMake Release,
with DEBUG_MODE and the development UUID set at configure time.

The debug launch configuration still carried the template's name.
…-04)

Both workflows installed Ubuntu's packaged gcc-arm-none-eabi, so the
released UF2 came from a different compiler than the ARM GNU Toolchain
14.2 used locally. They now download and cache 14.2.rel1 and print the
compiler version.

- build.yml builds release and debug in a matrix, writes a size report
  (sections, code copied to RAM, heap, reserved stack, flash used) to
  the job summary, and uploads the firmware with rp.elf and its map.
- release.yml builds release in lower case, writes the same report, and
  attaches rp.elf and its map to the GitHub release. They are not
  uploaded to the S3 bucket.
- actions/checkout v4, actions/setup-python v5, and GITHUB_OUTPUT
  instead of the deprecated set-output command.
…ORY-04)

The build section still said every build is MinSizeRel and that
clang-tidy runs from CMake. It now describes the release and debug
types, the MinSizeRel override, reproducible RELEASE_DATE, symbols in
rp.elf, the VS Code variants and the CI matrix.
The stcmd that atarist-toolkit-docker's installer writes, which CI uses,
takes $VERSION as the Docker image tag. build.sh exported the firmware
version under that name, so CI asked for atarist-toolkit-docker:v1.1.0,
which does not exist, and the m68k build failed. The previous build.sh
exported it too and ignored a failed m68k build, so earlier CI and
release builds most likely embedded the committed target_firmware.h;
the logs of those runs have expired. VERSION is only used inside
build.sh.
@diegoparrilla
diegoparrilla merged commit 610b66f into release/v1.1.0 Sep 15, 2026
2 checks passed
@diegoparrilla
diegoparrilla deleted the epic/08-honest-builds branch September 15, 2026 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant