Skip to content

fix(build): rebuild_signature omits build_unflags stripping → persistent recompiles for build_unflags projects #970

Description

@zackees

Context

Found while tracing #957. Distinct from #957 (which is the depfile-own-mtime false-stale, fixed separately).

The per-TU .cmdhash rebuild signature has a WRITE-vs-COMPUTE asymmetry around build_unflags:

  • WRITE (after a successful compile): the flags reach compile_source via the default trait compile_cpp/compile_c (crates/fbuild-build/src/compiler.rs:~109-125), which calls apply_compile_unflags(self.cpp_flags(), extra_flags, self.build_unflags()) before compiling. So the signature written to .cmdhash is hashed from flags with build_unflags stripped.
  • COMPUTE (staleness check on rebuild): Esp32Compiler::rebuild_signature (crates/fbuild-build/src/esp32/esp32_compiler.rs:199-220) hashes raw self.c_flags()/self.cpp_flags() with build_unflags NOT applied.

When platformio.ini sets a non-empty build_unflags that strips a real token, WRITE ≠ COMPUTE on every rebuild → the sketch/core TUs recompile persistently (not just once). NightDriverStrip's demo env has empty build_unflags, so it's latent there (which is why #951/#956 measured a clean 2.1 s no-op rebuild) — but any project using build_unflags regresses to full recompiles each build.

The same latent asymmetry exists in the other rebuild_signature overrides that don't apply unflags: the default trait impl (compiler.rs:~161), ch32v_compiler.rs:~194, renesas_compiler.rs:~229.

Fix

Apply apply_compile_unflags(base_flags, extra_flags, self.build_unflags()) inside the signature computation so WRITE and COMPUTE hash the identical post-unflag flag set. Prefer centralizing it (strip unflags inside the shared build_rebuild_signature path, or a shared helper both sides call) so every platform's rebuild_signature is covered rather than fixing per-platform. Note: shipping this shifts all .cmdhash values once → a one-time recompile on the first build after it lands (acceptable, same as any signature-format change).

Acceptance criteria

  • A project with build_unflags = <token> gets a clean no-op rebuild (no recompile) after a warm build.
  • Unit test: rebuild_signature for a compiler with non-empty build_unflags equals the signature the compile path writes.

Decisions

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions