Conversation
…red (#37) Extends PlatformIO `build_unflags` past user-facing scopes into the framework/toolchain-contributed flag set. Before, `build_unflags = -std=gnu++11` in platformio.ini would strip the token from `build_flags` entries but leave the framework's own `-std=gnu++11` in place, so the compile line still carried the flag the user meant to remove. Mechanism: - Adds `Compiler::build_unflags()` trait method with default `&[]` so existing platform impls are unaffected. - Default `compile_c` / `compile_cpp` impls route the platform flags and `extra_flags` through `apply_compile_unflags`, which filters both via `pipeline::remove_unflagged_tokens` when the set is non-empty. Early return keeps the zero-unflags path allocation-free. - `pipeline::remove_unflagged_tokens` is now `pub` so platform code can use the same PlatformIO-compatible removal semantics (exact-token + value-pair) already established by `BuildContext::new`. - `BuildContext` now stores `build_unflags` so orchestrators can pass it to their compiler via a builder method. ESP32 is wired as the reference implementation: `Esp32Compiler` gains a `build_unflags` field + `with_build_unflags(...)` builder + trait override. All four construction sites in `esp32::orchestrator` chain `.with_build_unflags(ctx.build_unflags.clone())`. Other platforms are untouched and will continue to only filter user/sketch-scope flags — follow-up PRs can wire them using the same one-line builder pattern. Tests cover: default trait impl returns empty, configured unflags round-trip through the trait method, and end-to-end stripping of a framework-contributed `-std=gnu++2b` from `cpp_flags()`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR introduces support for the Changes
Sequence DiagramsequenceDiagram
participant Config as PlatformIO Config
participant BuildCtx as BuildContext
participant Orch as Orchestrator
participant Compiler as Esp32Compiler
participant Pipeline as Compile Pipeline
Config->>BuildCtx: get_build_unflags()
BuildCtx->>BuildCtx: store build_unflags
BuildCtx->>Orch: pass ctx with build_unflags
Orch->>Compiler: with_build_unflags(ctx.build_unflags)
Compiler->>Compiler: store build_unflags
Pipeline->>Compiler: compile_c/compile_cpp
Compiler->>Compiler: apply_compile_unflags(flags, unflags)
Compiler->>Pipeline: compile_one(filtered_flags)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsTimed out fetching pipeline failures after 30000ms 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. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/fbuild-build/src/esp32/orchestrator.rs (1)
544-585:⚠️ Potential issue | 🟠 MajorFilter temp compiler flags through
remove_unflagged_tokensat extraction points;.with_build_unflags(...)on temp compilers is a no-op.The library helpers
ensure_libraries_syncandcompile_library_with_jobsaccept raw&[String]flags and do not re-apply unflags. SinceEsp32Compiler::c_flags()andcpp_flags()don't consultself.build_unflags, the.with_build_unflags(...)calls on temp compilers strip nothing. Onlycompile_c/compile_cpptrait methods apply them—but those are bypassed when you extract and pass flags directly.Result: library archives and the
compile_commands.jsonfile advertise unfiltered flags while the sketch is compiled with them stripped. This risks ABI/ODR mismatches (e.g.,-std=gnu++2bin archives vs.-std=gnu++20in sketch) and confuses clangd/IDEs.Affected paths:
- Lines 544–585: dep libs via
ensure_libraries_sync- Lines 609–667: project-as-library via
compile_project_as_library- Lines 694–810: framework built-in libs (WiFi/SPI/…) via
compile_library_with_jobs- Lines 976–1014: local
lib/*viacompile_library_with_jobs- Lines 882–886 and 1045–1060:
compile_commands.jsonvia rawc_flags()/cpp_flags()Fix: Apply
pipeline::remove_unflagged_tokensright after eachc_flags()/cpp_flags()extraction, before passing to helpers:Proposed fix pattern
let temp_compiler = Esp32Compiler::with_temp_dir( ... build_dir.join("tmp"), - ) - .with_build_unflags(ctx.build_unflags.clone()); + ); // Apply user build_flags to library compilation (matching PlatformIO behavior). // User flags like -std=gnu++2a replace the MCU config's -std=gnu++2b. - let c_flags = apply_overlay_flags(&temp_compiler.c_flags(), &user_overlay, "dummy.c"); - let cpp_flags = - apply_overlay_flags(&temp_compiler.cpp_flags(), &user_overlay, "dummy.cpp"); + let mut base_c = temp_compiler.c_flags(); + let mut base_cpp = temp_compiler.cpp_flags(); + crate::pipeline::remove_unflagged_tokens(&mut base_c, &ctx.build_unflags); + crate::pipeline::remove_unflagged_tokens(&mut base_cpp, &ctx.build_unflags); + let c_flags = apply_overlay_flags(&base_c, &user_overlay, "dummy.c"); + let cpp_flags = apply_overlay_flags(&base_cpp, &user_overlay, "dummy.cpp");Repeat for
p_compiler(609–623),fw_compiler(694–709), local-libs (976–1014), and bothgenerate_compile_dbcall sites (882–886, 1045–1060).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/fbuild-build/src/esp32/orchestrator.rs` around lines 544 - 585, The temp compilers' c_flags()/cpp_flags() are used directly so .with_build_unflags(...) is a no-op; call pipeline::remove_unflagged_tokens on each extracted flag vector before passing them to library helpers (e.g., after temp_compiler.c_flags()/cpp_flags(), p_compiler, fw_compiler and local lib compiler extractions) and before building compile_commands.json; update the uses around Esp32Compiler::with_temp_dir (temp_compiler), the p_compiler block (compile_project_as_library), fw_compiler block (compile_library_with_jobs), local lib compilation sites, and the two generate_compile_db call sites to replace raw c_flags()/cpp_flags() with the cleaned vectors from pipeline::remove_unflagged_tokens.
🧹 Nitpick comments (1)
crates/fbuild-build/src/esp32/orchestrator.rs (1)
501-506: Minor: re-readsbuild_flagsfrom config, bypassingctx.user_flags.Lines 504 re-parse
ctx.config.get_build_flags(¶ms.env_name)?instead of usingctx.user_flags, whichBuildContext::newalready produced with user-scopebuild_unflagsapplied. So even after the library-path fix above, the user's ownbuild_flagsfeedinguser_overlayhere haven't had unflags applied at the source — they'll only be stripped later via the framework-flag filter, which works only for exact token matches already present in both scopes.Not a blocker (the overlay still gets filtered for framework tokens), but it's an inconsistency worth cleaning up so one source of truth (
ctx.user_flags) flows through the whole orchestrator.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/fbuild-build/src/esp32/orchestrator.rs` around lines 501 - 506, Replace the redundant call to ctx.config.get_build_flags(¶ms.env_name)? with the already-processed ctx.user_flags so the orchestrator uses the single source of truth produced by BuildContext::new; specifically, in the block that builds user_flags/user_build_flags (variables user_flags, user_build_flags, and where params.extra_build_flags is extended), use ctx.user_flags as the base (and then extend with params.extra_build_flags and prepend sdk_defines as before) so unflags applied in BuildContext::new are preserved when computing the user_overlay.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@crates/fbuild-build/src/esp32/orchestrator.rs`:
- Around line 544-585: The temp compilers' c_flags()/cpp_flags() are used
directly so .with_build_unflags(...) is a no-op; call
pipeline::remove_unflagged_tokens on each extracted flag vector before passing
them to library helpers (e.g., after temp_compiler.c_flags()/cpp_flags(),
p_compiler, fw_compiler and local lib compiler extractions) and before building
compile_commands.json; update the uses around Esp32Compiler::with_temp_dir
(temp_compiler), the p_compiler block (compile_project_as_library), fw_compiler
block (compile_library_with_jobs), local lib compilation sites, and the two
generate_compile_db call sites to replace raw c_flags()/cpp_flags() with the
cleaned vectors from pipeline::remove_unflagged_tokens.
---
Nitpick comments:
In `@crates/fbuild-build/src/esp32/orchestrator.rs`:
- Around line 501-506: Replace the redundant call to
ctx.config.get_build_flags(¶ms.env_name)? with the already-processed
ctx.user_flags so the orchestrator uses the single source of truth produced by
BuildContext::new; specifically, in the block that builds
user_flags/user_build_flags (variables user_flags, user_build_flags, and where
params.extra_build_flags is extended), use ctx.user_flags as the base (and then
extend with params.extra_build_flags and prepend sdk_defines as before) so
unflags applied in BuildContext::new are preserved when computing the
user_overlay.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 331ccb8a-5c88-43f0-866c-6936e0adb56c
📒 Files selected for processing (4)
crates/fbuild-build/src/compiler.rscrates/fbuild-build/src/esp32/esp32_compiler.rscrates/fbuild-build/src/esp32/orchestrator.rscrates/fbuild-build/src/pipeline.rs
…ers (#37) Follow-up to the ESP32 reference implementation — applies the same builder-pattern wiring to every other platform so PlatformIO `build_unflags` now strips framework/toolchain-contributed flags on AVR, Teensy, generic ARM (STM32 / RP2040 / Apollo3), nRF52, Renesas, Silabs, CH32V, SAM, and ESP8266. Per-compiler changes are identical in shape: - Add `build_unflags: Vec<String>` field, initialized empty in constructor - Add `with_build_unflags(...)` builder method - Override `Compiler::build_unflags()` to return `&self.build_unflags` Each platform orchestrator chains `.with_build_unflags(ctx.build_unflags.clone())` on every `XxxCompiler::new(...)` site (one per orchestrator, except stm32 which has two). Default-impl `compile_c` / `compile_cpp` in the `Compiler` trait already filter both platform and `extra_flags` through this set when it's non-empty (added in PR #63), so wiring each platform picks up framework-scope filtering automatically. All 447 fbuild-build lib tests pass; clippy -D warnings clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ers (#37) (#64) Follow-up to the ESP32 reference implementation — applies the same builder-pattern wiring to every other platform so PlatformIO `build_unflags` now strips framework/toolchain-contributed flags on AVR, Teensy, generic ARM (STM32 / RP2040 / Apollo3), nRF52, Renesas, Silabs, CH32V, SAM, and ESP8266. Per-compiler changes are identical in shape: - Add `build_unflags: Vec<String>` field, initialized empty in constructor - Add `with_build_unflags(...)` builder method - Override `Compiler::build_unflags()` to return `&self.build_unflags` Each platform orchestrator chains `.with_build_unflags(ctx.build_unflags.clone())` on every `XxxCompiler::new(...)` site (one per orchestrator, except stm32 which has two). Default-impl `compile_c` / `compile_cpp` in the `Compiler` trait already filter both platform and `extra_flags` through this set when it's non-empty (added in PR #63), so wiring each platform picks up framework-scope filtering automatically. All 447 fbuild-build lib tests pass; clippy -D warnings clean. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Extends PlatformIO
build_unflagspast user-facing scopes (already handled byBuildContext::new) into framework/toolchain-contributed flags. Before,build_unflags = -std=gnu++11inplatformio.inistripped the token frombuild_flagsentries but left the framework's own-std=gnu++11in place, so the compile line still carried the flag the user meant to remove.Mechanism
Compiler::build_unflags()trait method with default&[]— zero behavior change for platforms that don't opt in.compile_c/compile_cppimpls route platform flags ANDextra_flagsthrough a newapply_compile_unflagshelper that filters viapipeline::remove_unflagged_tokens. Early return keeps the zero-unflags path allocation-free.pipeline::remove_unflagged_tokensis nowpubso platform code can use the same PlatformIO-compatible semantics (exact-token + value-pair removal) already used byBuildContext::new.BuildContextgains abuild_unflagsfield so orchestrators can pass the set to their compiler.ESP32 reference impl
Esp32Compilergets abuild_unflagsfield and awith_build_unflags(...)builder.&self.build_unflags.Esp32Compiler::with_temp_dir(...)construction sites inesp32::orchestratorchain.with_build_unflags(ctx.build_unflags.clone()).Other platforms remain unchanged. Follow-up PRs can wire them using the same one-line builder pattern if desired.
Context
Addresses #37 — which asked for
build_unflagsto apply to effective native flag scopes (compile / link / assembler), not just the user-providedbuild_flagslayer. This PR lands the compile scope; link is already handled by the existingremove_unflagged_tokens(&mut overlay_link_flags, ...)call inBuildContext::new.Test plan
uv run cargo clippy --workspace --all-targets -- -D warningscleanuv run cargo test -p fbuild-build --lib— 447 passed (3 new)🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Tests