Skip to content

feat(build): #243 #244 strip .eh_frame on release builds across all GCC platforms#245

Merged
zackees merged 1 commit into
mainfrom
feat/issue-243-244-eh-frame-strip
May 13, 2026
Merged

feat(build): #243 #244 strip .eh_frame on release builds across all GCC platforms#245
zackees merged 1 commit into
mainfrom
feat/issue-243-244-eh-frame-strip

Conversation

@zackees
Copy link
Copy Markdown
Member

@zackees zackees commented May 12, 2026

Closes #243.
Closes #244.

Summary

GCC emits .eh_frame unwinding tables by default. On a stock FastLED ESP32-S3 Blink build this is ~225 KB / 36 % of the firmware — dead metadata no _Unwind_* API ever consumes when exceptions and panic backtrace are both off (audit: FastLED/FastLED#2473). FastLED's library-side pragma workaround (PR #2423) is a no-op on modern GCC; the only reliable fix is cc1-level flags, which is the build system's job.

This PR adds a shared eh_frame strip policy that injects -fno-asynchronous-unwind-tables -fno-unwind-tables to every TU when appropriate. The decision respects user intent at every layer.

Architecture

Layer New code Purpose
Pure decision crates/fbuild-build/src/eh_frame_policy.rs decide(&EhFrameInputs) -> EhFramePolicy. Pure function, 16 unit tests covering the precedence matrix.
sdkconfig parser crates/fbuild-config/src/sdkconfig.rs Minimal parser for the 4 boolean keys the policy reads. Defaults to ESP-IDF Arduino defaults. 14 unit tests.
Orchestrator helper crates/fbuild-build/src/eh_frame_policy_compute.rs Reads env vars + BuildContext fields, calls decide().
Compiler injection 5 *_compiler.rs files (esp32, generic_arm, teensy, esp8266, avr) with_eh_frame_policy() setter + 3-line append in common_flags(). Mirrors existing with_build_unflags pattern.
Orchestrator wiring 8 orchestrator files (esp32, generic_arm, teensy, esp8266, avr, stm32, rp2040, apollo3) Compute policy once per build, pass to every compiler construction site. ESP32 reads sdkconfig from project dir.

Decision precedence

  1. FBUILD_STRIP_EH_FRAME=1 → Strip
  2. FBUILD_KEEP_EH_FRAME=1 → Preserve
  3. build_type = debug (or -Og/-O0 in build_flags) → Preserve
  4. -fexceptions / -funwind-tables / -fasynchronous-unwind-tables in build_flags (not negated) → Preserve
  5. ESP32 sdkconfig has panic_print_backtrace, panic_gdbstub, debug_ocdaware, or optimization_debug set → Preserve
  6. Otherwise → Strip

Behavior under defaults

Platform Default policy Why
ESP32 (Arduino) Preserve ESP-IDF Arduino default has CONFIG_ESP_SYSTEM_PANIC_PRINT_BACKTRACE=y so esp32_exception_decoder keeps producing readable crash backtraces.
Teensy / STM32 / RP2040 / NRF52 / ESP8266 Strip Their JSON configs already ship -fno-exceptions; nothing in their toolchain consumes eh_frame. Immediate flash savings on every release build.
AVR Strip (no-op) AVR-gcc only emits eh_frame when -fexceptions is on, which AVR's JSON disables. Wired for uniformity.
Debug build (any platform) Preserve -Og/-O0 builds always keep eh_frame for crash debugging.

User-facing overrides

FBUILD_STRIP_EH_FRAME=1 fbuild build -e esp32s3 examples/Blink   # force strip
FBUILD_KEEP_EH_FRAME=1  fbuild build -e esp32s3 examples/Blink   # force preserve

How to verify the binary shrank

FBUILD_KEEP_EH_FRAME=1  fbuild build -e esp32s3 examples/Blink
cp .fbuild/build/esp32s3/release/firmware.bin /tmp/blink-preserve.bin

FBUILD_STRIP_EH_FRAME=1 fbuild build -e esp32s3 examples/Blink
cp .fbuild/build/esp32s3/release/firmware.bin /tmp/blink-strip.bin

ls -la /tmp/blink-{preserve,strip}.bin
# Expected: preserve ~657 KB, strip <= 510 KB (delta >= 150 KB).

xtensa-esp32s3-elf-readelf --debug-dump=frames \
  .fbuild/build/esp32s3/release/firmware.elf | grep -c "FDE cie"
# Expected: preserve ~6500 FDEs, strip near zero from project TUs.

The integration test (crates/fbuild-build/tests/eh_frame_strip_esp32.rs, #[ignore]-marked) automates this: builds twice, asserts firmware.bin delta ≥ 150 KB and .eh_frame section delta ≥ 50 KB via the object crate.

Test plan

  • uv run soldr cargo fmt --all -- --check (clean)
  • uv run soldr cargo check --workspace --all-targets (clean)
  • uv run soldr cargo clippy --workspace --all-targets -- -D warnings (clean, only pre-existing MSRV-mismatch warning)
  • uv run soldr cargo test -p fbuild-build --lib → 534 passed (+10 platform tests from this PR)
  • uv run soldr cargo test -p fbuild-config → 120 passed (+14 sdkconfig tests from this PR)
  • uv run soldr cargo test -p fbuild-build eh_frame_policy → 16 / 16 passed
  • uv run soldr cargo build --tests → all test crates compile, including the #[ignore]-marked integration test
  • Manual: run the integration test under --ignored on a host with the ESP32 toolchain to confirm the ≥ 150 KB savings claim end-to-end. Deferred to post-merge / a follow-up CI gate.

TDD workflow used

Wave 1 (in parallel via subagents): two pure modules (eh_frame_policy + sdkconfig) with full unit-test matrices. Wave 1 verified clean before Wave 2 started.

Wave 2 (single subagent): platform wiring + integration test. Tests assert STRIP_FLAGS presence under EhFramePolicy::Strip and absence under default Preserve for every compiler. All 5 GCC compilers + 8 orchestrators wired uniformly.

Out of scope

  • WASM (different unwind model).
  • CI bench gate on absolute binary size (deferred — the integration test gates the behavior, not the absolute bytes).
  • FastLED-side cleanup of the unused FL_NO_UNWIND_BEGIN/_END pragma macros. Harmless to leave in place.
  • docs/ page on size optimization. PR body + issue body carry the user-facing info for now; a real docs page can follow when someone asks.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Configurable eh_frame unwind-table handling across supported platforms (ESP32, ESP8266, STM32, ARM, AVR, Teensy, RP2040, Apollo3)
    • SDK config parsing for ESP32 to influence eh_frame decisions
    • Environment variables FBUILD_KEEP_EH_FRAME and FBUILD_STRIP_EH_FRAME control behavior; debug builds preserve by default
  • Tests

    • Added (ignored) ESP32 integration test verifying firmware size reduction when eh_frame is stripped

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7bf5057d-931b-4ec7-8aa3-0cc2056f0456

📥 Commits

Reviewing files that changed from the base of the PR and between 42e0459 and 6ba0003.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • crates/fbuild-build/Cargo.toml
  • crates/fbuild-build/src/apollo3/orchestrator.rs
  • crates/fbuild-build/src/avr/avr_compiler.rs
  • crates/fbuild-build/src/avr/orchestrator.rs
  • crates/fbuild-build/src/eh_frame_policy.rs
  • crates/fbuild-build/src/eh_frame_policy_compute.rs
  • crates/fbuild-build/src/esp32/esp32_compiler.rs
  • crates/fbuild-build/src/esp32/orchestrator.rs
  • crates/fbuild-build/src/esp8266/esp8266_compiler.rs
  • crates/fbuild-build/src/esp8266/orchestrator.rs
  • crates/fbuild-build/src/generic_arm/arm_compiler.rs
  • crates/fbuild-build/src/lib.rs
  • crates/fbuild-build/src/rp2040/orchestrator.rs
  • crates/fbuild-build/src/stm32/orchestrator.rs
  • crates/fbuild-build/src/teensy/orchestrator.rs
  • crates/fbuild-build/src/teensy/teensy_compiler.rs
  • crates/fbuild-build/tests/eh_frame_strip_esp32.rs
  • crates/fbuild-config/src/lib.rs
  • crates/fbuild-config/src/sdkconfig.rs
✅ Files skipped from review due to trivial changes (2)
  • crates/fbuild-config/src/lib.rs
  • crates/fbuild-build/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (16)
  • crates/fbuild-build/src/lib.rs
  • crates/fbuild-build/src/esp8266/orchestrator.rs
  • crates/fbuild-build/src/stm32/orchestrator.rs
  • crates/fbuild-build/src/rp2040/orchestrator.rs
  • crates/fbuild-build/src/teensy/teensy_compiler.rs
  • crates/fbuild-config/src/sdkconfig.rs
  • crates/fbuild-build/src/esp32/esp32_compiler.rs
  • crates/fbuild-build/src/avr/orchestrator.rs
  • crates/fbuild-build/src/esp8266/esp8266_compiler.rs
  • crates/fbuild-build/src/generic_arm/arm_compiler.rs
  • crates/fbuild-build/src/apollo3/orchestrator.rs
  • crates/fbuild-build/src/eh_frame_policy.rs
  • crates/fbuild-build/tests/eh_frame_strip_esp32.rs
  • crates/fbuild-build/src/esp32/orchestrator.rs
  • crates/fbuild-build/src/avr/avr_compiler.rs
  • crates/fbuild-build/src/eh_frame_policy_compute.rs

📝 Walkthrough

Walkthrough

This PR implements an automatic .eh_frame stripping policy across embedded build targets. A new EhFramePolicy enum and decision function determine when to inject -fno-asynchronous-unwind-tables -fno-unwind-tables based on debug profile, exception flags, environment overrides, and platform-specific config (ESP32 sdkconfig). The policy is wired into compilers and orchestrators (ARM, Xtensa, AVR, Teensy), and an ignored ESP32 integration test validates size differences.

Changes

EhFrame policy and cross-platform implementation

Layer / File(s) Summary
Policy decision logic and orchestrator compute helper
crates/fbuild-build/src/eh_frame_policy.rs, crates/fbuild-build/src/eh_frame_policy_compute.rs, crates/fbuild-build/src/lib.rs
EhFramePolicy enum with Preserve/Strip, EhFrameInputs aggregation, STRIP_FLAGS constant, decide() implementing ordered precedence (env overrides → debug build → positive flags → platform config → default). compute_eh_frame_policy() reads env and orchestrator context and returns the policy; both modules are exposed from lib.rs.
ESP-IDF sdkconfig parser for platform-specific hints
crates/fbuild-config/src/sdkconfig.rs, crates/fbuild-config/src/lib.rs
SdkConfigSummary with tracked booleans, arduino_default(), parse(), and from_project_dir() to load sdkconfig / sdkconfig.defaults; used by compute_eh_frame_policy() on ESP32.
Compiler infrastructure: policy field and builder across all platforms
crates/fbuild-build/src/generic_arm/arm_compiler.rs, crates/fbuild-build/src/esp32/esp32_compiler.rs, crates/fbuild-build/src/esp8266/esp8266_compiler.rs, crates/fbuild-build/src/avr/avr_compiler.rs, crates/fbuild-build/src/teensy/teensy_compiler.rs
Each compiler adds eh_frame_policy field (initialized to EhFramePolicy::default()), with_eh_frame_policy() builder, and conditional injection of STRIP_FLAGS into common_flags(). Unit tests validate default and strip behaviors.
Orchestrator wiring: compute policy and pass to each compiler
crates/fbuild-build/src/esp32/orchestrator.rs, crates/fbuild-build/src/esp8266/orchestrator.rs, crates/fbuild-build/src/avr/orchestrator.rs, crates/fbuild-build/src/teensy/orchestrator.rs, crates/fbuild-build/src/apollo3/orchestrator.rs, crates/fbuild-build/src/rp2040/orchestrator.rs, crates/fbuild-build/src/stm32/orchestrator.rs
Each orchestrator computes the eh_frame_policy once per build (passing SDK config for ESP32 where applicable), records it in fingerprint metadata where present, and threads it into compiler instances via .with_eh_frame_policy(...).
Integration test and dev dependency
crates/fbuild-build/Cargo.toml, crates/fbuild-build/tests/eh_frame_strip_esp32.rs
Add object crate as a workspace-scoped dev-dependency. Add an ignored ESP32 integration test that builds a minimal Blink project twice (with FBUILD_KEEP_EH_FRAME=1 and FBUILD_STRIP_EH_FRAME=1), parses ELF .eh_frame sections, and asserts ≥50 KiB reduction in .eh_frame and ≥150 KiB reduction in firmware binary.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

  • FastLED/fbuild#14: Threads the computed eh_frame_policy into the Apollo3/Arm compiler flow (related orchestrator integration).

Poem

"🐰 I nibble flags and hop through code,
Snipping eh_frame where no backtrace showed.
Binaries shrink, the flash sings light,
Tiny builds sleep well tonight. ✨"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(build): #243 #244 strip .eh_frame on release builds across all GCC platforms' accurately summarizes the main change: adding eh_frame stripping policy across all GCC-based platforms to reduce firmware size on release builds.
Linked Issues check ✅ Passed The pull request fully implements all coding requirements from both #243 and #244: EhFramePolicy enum, sdkconfig parser, decision function, per-platform compiler wiring with with_eh_frame_policy() methods, orchestrator integration across eight platforms, and comprehensive unit/integration tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing eh_frame stripping across GCC platforms. The only tangential addition is the object dev-dependency for integration testing, which is necessary and minimal.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-243-244-eh-frame-strip

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/fbuild-build/src/avr/orchestrator.rs`:
- Around line 93-97: The fast-path fingerprint metadata currently omits
eh_frame_policy so builds can be reused when
FBUILD_KEEP_EH_FRAME/FBUILD_STRIP_EH_FRAME change; update the metadata
fingerprint construction to include the local eh_frame_policy value wherever
metadata_hash or the fast-path fingerprint is computed (references: the
eh_frame_policy variable, metadata_hash/fingerprint construction code used in
this file and the other indicated blocks around lines 130-146 and 232-233),
i.e., add eh_frame_policy into the set of inputs hashed for the
metadata/fingerprint so changes to the policy invalidate cached artifacts.

In `@crates/fbuild-build/src/esp32/orchestrator.rs`:
- Around line 166-175: The fingerprint metadata for ESP32 currently omits the
computed eh_frame_policy, so add the value produced by
crate::eh_frame_policy_compute::compute_eh_frame_policy (the eh_frame_policy
variable computed from
fbuild_config::sdkconfig::SdkConfigSummary::from_project_dir) into the
Esp32FingerprintMetadata inputs used for hashing/ cache key; update the code
that constructs Esp32FingerprintMetadata (the struct/constructor where
platform-specific hash inputs are collected) to include eh_frame_policy so cache
hits respect strip/preserve mode changes.

In `@crates/fbuild-build/src/rp2040/orchestrator.rs`:
- Around line 72-75: The eh_frame_policy computed by
compute_eh_frame_policy(&ctx, params.profile, None) is not being encoded into
the fast-path fingerprint, so builds can be reused across different EH frame
strip/keep settings; update the fingerprint construction logic (the code that
builds the fast-path fingerprint/key in orchestrator.rs) to include the
eh_frame_policy value (use the eh_frame_policy variable) as part of the
fingerprint metadata so changes to FBUILD_STRIP_EH_FRAME/FBUILD_KEEP_EH_FRAME
produce distinct fingerprints and avoid stale artifact reuse.

In `@crates/fbuild-build/src/teensy/orchestrator.rs`:
- Around line 76-80: The no-op fingerprint currently misses the resolved
eh_frame_policy computed by compute_eh_frame_policy(&ctx, params.profile, None),
so include the eh_frame_policy value into the fingerprint metadata used for
cache/no-op decisions; locate where the no-op fingerprint is assembled and add
eh_frame_policy (or a serialization of it) as an input field so changes to
FBUILD_KEEP_EH_FRAME / FBUILD_STRIP_EH_FRAME (and the computed policy)
invalidate the cache.

In `@crates/fbuild-build/tests/eh_frame_strip_esp32.rs`:
- Around line 102-106: The test must require an explicit ELF path instead of
falling back to firmware_path: replace the chained
.or(preserve_result.firmware_path.clone()) usage when building preserve_elf so
it calls preserve_result.elf_path.clone().expect("preserve build should produce
ELF path") (and do the same change for the similar block around the second
occurrence that currently uses firmware_path fallback) so parsing .eh_frame
always operates on an actual ELF file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7c2aa215-0835-46ae-af98-e881234454a6

📥 Commits

Reviewing files that changed from the base of the PR and between 86fe55b and 42e0459.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • crates/fbuild-build/Cargo.toml
  • crates/fbuild-build/src/apollo3/orchestrator.rs
  • crates/fbuild-build/src/avr/avr_compiler.rs
  • crates/fbuild-build/src/avr/orchestrator.rs
  • crates/fbuild-build/src/eh_frame_policy.rs
  • crates/fbuild-build/src/eh_frame_policy_compute.rs
  • crates/fbuild-build/src/esp32/esp32_compiler.rs
  • crates/fbuild-build/src/esp32/orchestrator.rs
  • crates/fbuild-build/src/esp8266/esp8266_compiler.rs
  • crates/fbuild-build/src/esp8266/orchestrator.rs
  • crates/fbuild-build/src/generic_arm/arm_compiler.rs
  • crates/fbuild-build/src/lib.rs
  • crates/fbuild-build/src/rp2040/orchestrator.rs
  • crates/fbuild-build/src/stm32/orchestrator.rs
  • crates/fbuild-build/src/teensy/orchestrator.rs
  • crates/fbuild-build/src/teensy/teensy_compiler.rs
  • crates/fbuild-build/tests/eh_frame_strip_esp32.rs
  • crates/fbuild-config/src/lib.rs
  • crates/fbuild-config/src/sdkconfig.rs

Comment thread crates/fbuild-build/src/avr/orchestrator.rs
Comment thread crates/fbuild-build/src/esp32/orchestrator.rs
Comment thread crates/fbuild-build/src/rp2040/orchestrator.rs
Comment thread crates/fbuild-build/src/teensy/orchestrator.rs
Comment thread crates/fbuild-build/tests/eh_frame_strip_esp32.rs Outdated
…CC platforms

GCC emits .eh_frame unwinding tables by default. On a stock FastLED
ESP32-S3 Blink build this is ~225 KB / 36% of the firmware -- dead
metadata no _Unwind_* API ever consumes when exceptions and panic
backtrace are both off. FastLED's library-side pragma workaround
(FastLED/FastLED#2423) is a no-op on modern GCC (audited in
FastLED/FastLED#2473); the only reliable fix is cc1-level flags, which
is the build system's job.

This PR adds a shared eh_frame strip policy that injects
`-fno-asynchronous-unwind-tables -fno-unwind-tables` to every TU when
appropriate. The decision respects user intent at every layer:
explicit env override, debug builds, `-fexceptions` in build_flags,
ESP-IDF panic-backtrace / gdbstub / ocdaware / optimization-debug
sdkconfig keys.

New modules
- `crates/fbuild-build/src/eh_frame_policy.rs` -- pure `decide()`
  function over plain inputs, plus `STRIP_FLAGS` constant. 16 unit
  tests cover the full precedence matrix.
- `crates/fbuild-build/src/eh_frame_policy_compute.rs` -- orchestrator-
  side helper that reads env vars + extracts BuildContext fields and
  calls `decide()`.
- `crates/fbuild-config/src/sdkconfig.rs` -- minimal sdkconfig parser
  surfacing the 4 keys the policy reads. Defaults to ESP-IDF Arduino
  defaults (`panic_print_backtrace = true`) so the safe assumption for
  an unmodified project is Preserve. 14 unit tests.

Per-platform wiring
- ESP32, generic ARM (STM32/RP2040/NRF52), Teensy, ESP8266, AVR each
  get a `with_eh_frame_policy()` setter and a 3-line append in
  `common_flags()`. Mirrors the existing `with_build_unflags` pattern.
- All orchestrators (esp32, generic_arm, teensy, esp8266, avr, stm32,
  rp2040, apollo3) compute the policy once per build and pass it to
  each compiler construction site. ESP32 also reads sdkconfig from the
  project dir. Other platforms pass `None`.
- 10 new platform unit tests (2 per platform) assert STRIP_FLAGS
  presence under `Strip` and absence under default `Preserve`.

Integration test (`#[ignore]`, toolchain-required)
- `crates/fbuild-build/tests/eh_frame_strip_esp32.rs` builds a tempfile
  ESP32 project twice (FBUILD_KEEP_EH_FRAME=1 vs FBUILD_STRIP_EH_FRAME=1)
  and asserts firmware.bin delta >= 150 KB plus `.eh_frame` ELF section
  delta >= 50 KB via the `object` crate.

User-facing overrides
- `FBUILD_STRIP_EH_FRAME=1` -- force strip regardless of detection
- `FBUILD_KEEP_EH_FRAME=1` -- force preserve

Behavior under defaults
- ESP32 with stock Arduino framework: Preserve (matches user
  expectation of esp32_exception_decoder showing readable backtraces).
- Teensy / STM32 / RP2040 / NRF52 / ESP8266: Strip (their JSON configs
  already ship `-fno-exceptions`; nothing in their toolchain consumes
  eh_frame). Immediate flash savings on every release build.
- AVR: Strip wired for uniformity; runtime is a no-op because AVR-gcc
  only emits eh_frame when `-fexceptions` is on, which AVR's JSON
  disables.
- Debug builds (`build_type = debug`, or `-Og`/`-O0` flags) always
  Preserve, even on platforms that would otherwise strip.

Test coverage
- 16 eh_frame_policy unit tests (decision matrix)
- 14 sdkconfig unit tests (parser + project-dir lookup)
- 10 per-platform compiler tests (STRIP_FLAGS presence/absence)
- 1 integration test (`#[ignore]`, runs locally with ESP32 toolchain)
- Existing 534 fbuild-build + 120 fbuild-config lib tests stay green.

Closes #243.
Closes #244.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zackees zackees force-pushed the feat/issue-243-244-eh-frame-strip branch from 42e0459 to 6ba0003 Compare May 13, 2026 00:54
@zackees
Copy link
Copy Markdown
Member Author

zackees commented May 13, 2026

CodeRabbit review folded in (squashed force-push to 6ba0003):

  • Added eh_frame_policy: &'static str to 4 fingerprint metadata structs: AvrFingerprintMetadata, Esp32FingerprintMetadata, Rp2040FingerprintMetadata, TeensyFingerprintMetadata. Cache now invalidates on FBUILD_STRIP_EH_FRAME / FBUILD_KEEP_EH_FRAME flips and on natural detection changes (e.g. user adding -fexceptions to build_flags, ESP32 sdkconfig panic-backtrace toggles).
  • Audited the other 4 orchestrators touched in this PR: stm32, esp8266, apollo3, generic_arm. None have a fingerprint metadata struct -- they don't participate in the warm-build fast path -- so no further changes were needed there.
  • Integration test (eh_frame_strip_esp32.rs) now requires elf_path explicitly at both build sites; the .or(firmware_path) fallback was dropping into a .bin and failing object::File::parse for the wrong reason.

Verification: workspace cargo check + clippy -D warnings clean (only the pre-existing MSRV warning), all 534 fbuild-build lib tests pass.

@zackees zackees merged commit a009a2b into main May 13, 2026
84 checks passed
zackees added a commit that referenced this pull request May 13, 2026
…atformIO) (#247)

Add a new "PlatformIO compatibility: .eh_frame strip" section to README
that explains why fbuild's release binaries on Teensy/STM32/RP2040/NRF52/
ESP8266 are smaller than PlatformIO's, summarizes the EhFramePolicy
precedence introduced in #245, and shows the two opt-out paths
(build_flags = -funwind-tables in platformio.ini, FBUILD_KEEP_EH_FRAME=1
env var). Also adds a one-line forward reference near the existing
"platformio.ini compatible" tagline so users notice the deviation.

Closes #246.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant