Skip to content

fix(pipeline): absolutize project_dir to fix relative-path include doubling#315

Merged
zackees merged 1 commit into
mainfrom
fix/lib-fastled-auto-discovery-303
May 30, 2026
Merged

fix(pipeline): absolutize project_dir to fix relative-path include doubling#315
zackees merged 1 commit into
mainfrom
fix/lib-fastled-auto-discovery-303

Conversation

@zackees
Copy link
Copy Markdown
Member

@zackees zackees commented May 30, 2026

Summary

fbuild test-emu .build/pio/<env> was failing every ESP32 QEMU CI run with fatal error: FastLED.h: No such file or directory even though the preceding ci-compile.py step had just produced a working firmware in the same project directory.

Issue described in #303.

Root cause

The CLI passes the project-dir argument through verbatim to the daemon, which builds a PathBuf from the string and hands it to the orchestrator unchanged. Whether the path is absolute or relative depends entirely on what the user typed.

  • ci-compile.py invokes fbuild with an absolute project dir (workspace-rooted). discover_project_includes produces absolute include flags. zccache::path_arg_for_compile_cwd strips the compile-cwd prefix, leaving project-relative include flags that GCC resolves correctly against cwd = <project>/.
  • fbuild test-emu .build/pio/<env> (the CI form) sends a relative path. discover_project_includes joins it as-is, producing relative include paths like -I.build/pio/esp32dev/lib/FastLED. zccache::path_arg_for_compile_cwd short-circuits on non-absolute inputs (if !path.is_absolute() { return path.to_string_lossy().to_string(); }) and passes them through unchanged. GCC then resolves the already-relative include path against the project-rooted compile cwd, producing the doubled prefix <project>/.build/pio/esp32dev/lib/FastLED -- which doesn't exist -- and FastLED.h is reported missing.

The bug had nothing to do with lib-discovery logic (the original hypothesis in #303). discover_project_includes already implements PlatformIO's lib/<Name>/src/ auto-discovery correctly. The output of that discovery was just spelled in a form that survived too far through the compile-cwd plumbing.

Fix

discover_project_includes now calls absolute_from_cwd(project_dir) at the top, making every emitted include dir absolute regardless of how the caller spelled the input. The normalize-then-exec chain then behaves identically for absolute and relative call sites.

absolute_from_cwd already existed in compiler.rs as pub fn absolute_from_cwd(path: &Path) -> PathBuf (used for source and output paths in compile_source to fix the analogous #282 bug). Promoted from private to pub for cross-module use.

Why this is the right layer

Three places could host the fix; pipeline-level is the smallest blast radius:

  1. Daemon handlers (build, test_emu, deploy): would have to canonicalize on every handler; easy to miss new entry points.
  2. zccache::path_arg_for_compile_cwd: would have to look up current_dir() for every relative path; couples the helper to process state.
  3. discover_project_includes (chosen): one call, single responsibility (emit absolute include paths), already documents that callers should not depend on relativeness.

Test plan

  • cargo test --lib -p fbuild-build pipeline::project_discovery -- 2/2 new regression tests passing
  • cargo test --lib -p fbuild-build -- 546/546 passing
  • CI: qemu_esp32dev_test, qemu_esp32s3_test, qemu_esp32c3_test should turn green once a release of fbuild ships and FastLED bumps its pin.

Fixes #303

Generated with Claude Code (https://claude.com/claude-code)

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 30, 2026

Warning

Review limit reached

@zackees, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 53 minutes and 17 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 60abb319-04a1-4e74-9988-c173ebda8ba5

📥 Commits

Reviewing files that changed from the base of the PR and between 8bfba3b and 24a671a.

📒 Files selected for processing (2)
  • crates/fbuild-build/src/compiler.rs
  • crates/fbuild-build/src/pipeline/project_discovery.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/lib-fastled-auto-discovery-303

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.

)

`fbuild test-emu .build/pio/<env>` was failing every ESP32 QEMU CI run
with `fatal error: FastLED.h: No such file or directory` even though
the preceding `ci-compile.py` step had just produced a working firmware
in the same directory.

Root cause: the CLI passes the project path through verbatim. ci-compile.py
sends an *absolute* path (workspace-rooted) so include flags end up absolute,
get stripped to project-relative by `zccache::path_arg_for_compile_cwd`, and
GCC resolves them correctly against `cwd = <project>/`. test-emu passes
the raw `.build/pio/<env>` *relative* string, which propagates straight into
`discover_project_includes` and produces relative include paths like
`-I.build/pio/esp32dev/lib/FastLED`. The zccache normalizer short-circuits
on non-absolute inputs and passes them through unchanged. GCC then resolves
the relative include against the already-project-rooted compile cwd, doubling
the prefix to `<project>/.build/pio/esp32dev/lib/FastLED` — a path that
doesn't exist — and FastLED.h is reported missing.

Fix: promote `project_dir` to an absolute path at the top of
`discover_project_includes` via the existing `absolute_from_cwd` helper
(made `pub` for cross-module use). Every emitted include dir is now
absolute regardless of how the caller spelled the input, so the
normalize→exec chain is stable.

Regression tests cover both absolute and relative `project_dir` inputs
and assert the absolutization invariant. Full fbuild-build test suite:
546/546 passing.

Fixes #303
@zackees zackees force-pushed the fix/lib-fastled-auto-discovery-303 branch from 9d9db68 to 24a671a Compare May 30, 2026 20:14
@zackees zackees merged commit 8f7910a into main May 30, 2026
75 of 82 checks passed
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.

fbuild test-emu rebuilds project without picking up lib/FastLED — breaks ESP32 QEMU CI

1 participant