Skip to content

fix(build): unbreak ESP32 sketch builds — gcc cwd/-o path consistency (closes #282)#283

Merged
zackees merged 1 commit into
mainfrom
fix/compile-cwd-relative-project-dir-282
May 29, 2026
Merged

fix(build): unbreak ESP32 sketch builds — gcc cwd/-o path consistency (closes #282)#283
zackees merged 1 commit into
mainfrom
fix/compile-cwd-relative-project-dir-282

Conversation

@zackees
Copy link
Copy Markdown
Member

@zackees zackees commented May 29, 2026

Summary

Every ESP32 sketch build on main has been failing in CI since 2026-05-28 with HWCDC.cpp: fatal error: opening dependency file tests/platform/esp32dev/.fbuild/build/esp32dev/quick/core/HWCDC_57cf.cpp.d: No such file or directory (and the same for ColorFormat.c and other framework core/ sources). Closes #282.

Root cause: latent asymmetry in compile_source. When the CLI is invoked with a relative project_dir (which CI does — fbuild build tests/platform/esp32dev ...), the relative output reaches compile_source and hits zccache::compile_cwd_from_output (which canonicalizes the workspace to absolute) paired with zccache::path_arg_for_compile_cwd (which short-circuits on relative paths and returns the raw relative string). gcc then ran with absolute CWD plus a relative -o, resolving to a doubled path (/.../fbuild/tests/platform/esp32dev/tests/platform/esp32dev/.fbuild/...) whose core/ parent was never create_dir_all'd.

The bug landed weeks ago (#191/#193) but stayed hidden because the soldr build cache restored .o files on every CI run, skipping the cold-compile dispatch. The setup-soldr@v0 floating tag picking up soldr 0.7.33 → 0.7.42 changed the toolchain-cache hash, invalidated every prior .o, and the latent bug surfaced on every cold framework core/ source.

Fix

Promote source and output to absolute paths at the top of compile_source via a small absolute_from_cwd helper (equivalent in intent to std::path::absolute, hand-written because clippy enforces MSRV 1.75 and that function is stable since 1.79). With absolute inputs, compile_cwd_from_output and path_arg_for_compile_cwd produce a consistent (cwd, -o) pair that joins back to the original physical file.

Test plan

  • soldr cargo test -p fbuild-build --lib compiler:: — 97 passed, 0 failed, including 3 new tests:
    • absolute_from_cwd_is_identity_on_absolute_paths
    • absolute_from_cwd_promotes_relative_paths
    • compile_path_contract_pairs_cwd_and_output_arg_for_282
  • soldr cargo test -p fbuild-build --lib — 543 passed, 0 failed (no regressions).
  • Build ESP32 Dev (and the other 5 currently-red ESP32 board workflows) pass on this PR — this is the regression guarantee for the actual CI scenario; once green, ESP32 sketch builds fail when project_dir is relative — compile_cwd vs -o path mismatch (missing core/ parent dir) #282 is verified end-to-end.

Does NOT require pinning zackees/setup-soldr — soldr can keep floating on v0.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where output paths were not resolved correctly during compilation, which could cause build failures in certain directory configuration scenarios.

Review Change Stack

…ject_dir

#282: every ESP32 sketch build on main has been failing in CI with
`HWCDC.cpp: fatal error: opening dependency file
tests/platform/esp32dev/.fbuild/build/esp32dev/quick/core/HWCDC_57cf.cpp.d:
No such file or directory`. Root cause was a latent asymmetry in
`compile_source`: when the CLI is invoked with a relative `project_dir`
(which CI does -- `fbuild build tests/platform/esp32dev ...`), the
relative output reaches `compile_source` and hits
`zccache::compile_cwd_from_output` (which canonicalizes the workspace
to absolute) paired with `zccache::path_arg_for_compile_cwd` (which
short-circuits on relative paths and returns the raw relative string).
gcc then ran with `cwd = absolute project_dir` plus a relative `-o`,
resolving to a doubled path
(`/.../fbuild/tests/platform/esp32dev/tests/platform/esp32dev/.fbuild/...`)
whose `core/` parent was never `create_dir_all`'d -- so `-MMD -MF`
failed.

The bug landed weeks ago in #191/#193 but stayed hidden because the
soldr build-cache restored `.o` files on every CI run, skipping the
cold-compile dispatch path. The `setup-soldr@v0` floating tag picking
up soldr 0.7.33 -> 0.7.42 changed the toolchain-cache hash, invalidated
every prior `.o`, and the latent bug surfaced on every cold core/
source.

Fix: at the top of `compile_source`, promote `source` and `output` to
absolute paths via a small `absolute_from_cwd` helper (equivalent in
intent to `std::path::absolute`, written by hand for the workspace
MSRV that `clippy.toml` enforces at 1.75 -- the function is stable
since 1.79). With absolute inputs, `compile_cwd_from_output` and
`path_arg_for_compile_cwd` produce a consistent (cwd, `-o`) pair that
joins back to the original physical file.

Added unit tests:
- `absolute_from_cwd_is_identity_on_absolute_paths` -- sanity.
- `absolute_from_cwd_promotes_relative_paths` -- sanity.
- `compile_path_contract_pairs_cwd_and_output_arg_for_282` -- the
  post-fix invariant: `cwd.join(out_arg)` resolves to the absolute
  output for any workspace under a `.fbuild` directory.

End-to-end verification: the failing CI workflows (`Build ESP32 Dev`,
ESP32-S3/S2/P4/C3/H2 and friends) exercise the relative-project_dir
path on every push -- once green on this PR, that's the regression
guarantee for the scenario.

Closes #282.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 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: d653f3a4-c8c3-4924-ad1b-ed1cd0912494

📥 Commits

Reviewing files that changed from the base of the PR and between f9fe196 and 16e044c.

📒 Files selected for processing (1)
  • crates/fbuild-build/src/compiler.rs

📝 Walkthrough

Walkthrough

This PR fixes build failures in cold-cache ESP32 compilation when project_dir is relative. A relative output path combined with an absolute compile cwd causes gcc to write dependency files to a non-existent doubled path. The fix normalizes source and output to absolute paths before computing the zccache compile cwd, ensuring consistent path resolution.

Changes

Compilation Path Normalization

Layer / File(s) Summary
Path normalization helper
crates/fbuild-build/src/compiler.rs
absolute_from_cwd converts relative paths to absolute using std::env::current_dir() without canonicalizing symlinks, with fallback to original path on error.
Compile source path resolution
crates/fbuild-build/src/compiler.rs
compile_source calls absolute_from_cwd on both source and output before computing compile_cwd and -o arguments to prevent doubled paths when resolving relative output against absolute cwd.
Regression and unit tests
crates/fbuild-build/src/compiler.rs
Issue #282 regression test validates cwd.join(path_arg_for_compile_cwd(abs_output, cwd)) resolves to the same absolute output path; unit tests verify absolute_from_cwd is identity for absolute paths and correctly promotes relative inputs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • FastLED/fbuild#193: Adjusts zccache compile cwd and path normalization in the same compiler.rs file to ensure output/source paths resolve correctly relative to computed compile cwd.
  • FastLED/fbuild#273: Modifies path handling that feeds into path_arg_for_compile_cwd, directly overlapping in the same path-resolution logic for compile output paths.

Poem

🐇 A rabbit hops through paths absolute and true,
No more doubled trails when cwd meets -o,
From relative tangles, a helper breaks through,
Normalize early, let the cold compiles flow! 🏗️

🚥 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 accurately and specifically describes the main fix: restoring ESP32 sketch builds by ensuring gcc receives consistent absolute paths for both cwd and -o arguments, directly addressing issue #282.
Linked Issues check ✅ Passed The PR fully implements the narrow fix preferred in issue #282: normalizing output and source to absolute paths in compiler.rs before computing compile_cwd, ensuring consistent cwd/-o path resolution. Regression tests for issue #282 are included.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the cwd/-o path mismatch in compile_source and adding regression tests for issue #282; no unrelated modifications are present.
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 fix/compile-cwd-relative-project-dir-282

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.

@zackees zackees merged commit a5f60b9 into main May 29, 2026
80 of 83 checks passed
zackees added a commit that referenced this pull request May 29, 2026
Two CI failures on PR #283 needed fixing:

1. `Reject .rs files over 1000 LOC` -- compiler.rs was at 1064, over
   the 1000-LOC repo gate. Extracted the entire `mod tests { ... }`
   block to a sibling `compiler_tests.rs` and wired it back via
   `#[cfg(test)] #[path = "compiler_tests.rs"] mod tests;`. compiler.rs
   drops to 668 LOC; tests file is 418 LOC. No behavior change.

2. `Check (macos-latest)` and `(windows-latest)` failed on the new
   `compile_path_contract_pairs_cwd_and_output_arg_for_282` regression
   test. Cause: `compile_cwd_from_output` canonicalizes its result
   (resolving `/var` -> `/private/var` on macOS, and adding then
   stripping the `\?\` extended-length prefix on Windows). The test's
   `abs_output` was built from the raw `tempfile::tempdir()` path,
   which differs from the canonicalized form -- so the final equality
   assertion compared two spellings of the same physical file. Fixed
   by normalizing the tempdir base up front: canonicalize, then strip
   the Windows `\?\` prefix, so both sides of the assertion stay on
   the same form `compile_cwd_from_output` produces.

Local: `soldr cargo test -p fbuild-build --lib` -- 543 passed.

Refs #282.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@zackees zackees mentioned this pull request May 29, 2026
4 tasks
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.

ESP32 sketch builds fail when project_dir is relative — compile_cwd vs -o path mismatch (missing core/ parent dir)

1 participant