fix(cpp-front): discover libclang on Linux, not only on Homebrew macOS #8

Merged
trevon merged 1 commit from fix/libclang-discovery-on-linux into main 2026-09-25 02:38:57 +00:00
Owner

The problem

tool/cpp_front.py hardcoded /opt/homebrew/opt/llvm and lib/libclang.dylib, so on Linux it died before parsing anything:

FileNotFoundError: [Errno 2] No such file or directory: '/opt/homebrew/opt/llvm/bin/clang'

PIPE_LLVM could move the prefix but not the file name, so no value of it made the tool run there.

Why it went unnoticed

test/cpp_front_test.dart looked for the same Homebrew .dylib, so on Linux it reported "All tests skipped" rather than failing. The suite was green because it ran nothing.

before after
dart test test/cpp_front_test.dart on Linux +0 ~4: All tests skipped. +4: All tests passed!

The change

  • Prefix per platform: Homebrew's LLVM on macOS, the system prefix elsewhere, PIPE_LLVM still winning over both.
  • Library looked up as .dylib or .so, exact name first then highest version, and under lib/*-linux-gnu — distributions ship libclang.so.<major>.<minor> without always adding the unversioned symlink, and Debian keeps it in a multiarch subdirectory.
  • -print-resource-dir falls back to clang on PATH when the prefix ships only the library.
  • When nothing matches, the conventional name goes to clang.cindex so its own error names the library rather than a path this code invented.
  • The test's detection now mirrors the front end's, so it runs instead of skipping.

_sdk_root already degraded to None off macOS (no xcrun), so it needed nothing.

Verification

Run end to end against an unrelated 87-translation-unit C++ project: 87/87 parsed, 0 TUs failed, 0 clang errors, 26 state enums and 879 emissions recovered.

dart analyze clean, dart format clean.

One caveat, stated rather than hidden: the full suite fails test/stdout_json_test.dart under the parallel runner on this machine — including on pristine main — and it passes in isolation on both branches. A serial run failed a different test (firestore_queries_test.dart) instead. Pre-existing and unrelated to this change, but worth a look on its own.

🤖 Generated with Claude Code

## The problem `tool/cpp_front.py` hardcoded `/opt/homebrew/opt/llvm` and `lib/libclang.dylib`, so on Linux it died before parsing anything: ``` FileNotFoundError: [Errno 2] No such file or directory: '/opt/homebrew/opt/llvm/bin/clang' ``` `PIPE_LLVM` could move the prefix but not the file name, so no value of it made the tool run there. ## Why it went unnoticed `test/cpp_front_test.dart` looked for the same Homebrew `.dylib`, so on Linux it reported **"All tests skipped"** rather than failing. The suite was green because it ran nothing. | | before | after | | --- | --- | --- | | `dart test test/cpp_front_test.dart` on Linux | `+0 ~4: All tests skipped.` | `+4: All tests passed!` | ## The change - Prefix per platform: Homebrew's LLVM on macOS, the system prefix elsewhere, `PIPE_LLVM` still winning over both. - Library looked up as `.dylib` or `.so`, exact name first then highest version, and under `lib/*-linux-gnu` — distributions ship `libclang.so.<major>.<minor>` without always adding the unversioned symlink, and Debian keeps it in a multiarch subdirectory. - `-print-resource-dir` falls back to `clang` on `PATH` when the prefix ships only the library. - When nothing matches, the conventional name goes to `clang.cindex` so its own error names the library rather than a path this code invented. - The test's detection now mirrors the front end's, so it runs instead of skipping. `_sdk_root` already degraded to `None` off macOS (no `xcrun`), so it needed nothing. ## Verification Run end to end against an unrelated 87-translation-unit C++ project: **87/87 parsed, 0 TUs failed, 0 clang errors**, 26 state enums and 879 emissions recovered. `dart analyze` clean, `dart format` clean. One caveat, stated rather than hidden: the full suite fails `test/stdout_json_test.dart` under the parallel runner on this machine — **including on pristine `main`** — and it passes in isolation on both branches. A serial run failed a different test (`firestore_queries_test.dart`) instead. Pre-existing and unrelated to this change, but worth a look on its own. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(cpp-front): discover libclang on Linux, not only on Homebrew macOS
Some checks failed
Lint Commits / commitlint (pull_request) Successful in 16s
Tests / Static Analysis (pull_request) Has been cancelled
Tests / Tests (pull_request) Has been cancelled
cf8c4cccc1
The front end hardcoded /opt/homebrew/opt/llvm and lib/libclang.dylib, so
on Linux it died before parsing anything:

    FileNotFoundError: [Errno 2] No such file or directory:
    '/opt/homebrew/opt/llvm/bin/clang'

PIPE_LLVM could move the prefix but not the file name, so no value of it
made the tool run there.

Discovery is now per platform: Homebrew's LLVM on macOS, the system prefix
elsewhere, PIPE_LLVM still winning over both. The library is looked up as
.dylib or .so, exact name first and then highest version, and under
lib/*-linux-gnu as well, because distributions ship
libclang.so.<major>.<minor> without always adding the unversioned symlink
and Debian keeps it in a multiarch subdirectory. -print-resource-dir falls
back to clang on PATH when the prefix ships only the library. When nothing
matches, the conventional name is handed to clang.cindex so its own error
names the library rather than a path this code invented.

_sdk_root already degrades to None off macOS, since xcrun is absent.

test/cpp_front_test.dart looked for the same Homebrew dylib, so on Linux
it reported "All tests skipped" rather than failing. That is why the gap
went unnoticed: the suite was green because it ran nothing. Its detection
now mirrors the front end's, and on this Linux machine the four cases go
from skipped to run and passing.

Verified end to end against an unrelated 87-translation-unit C++ project:
87/87 parsed, 0 TUs failed, 0 clang errors, 26 state enums and 879
emissions recovered.

Both suites fail test/stdout_json_test.dart under the parallel runner on
this machine, pristine main included, and it passes in isolation on both
branches; a serial run failed a different test instead. Pre-existing and
unrelated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
trevon merged commit 6e0222ffbe into main 2026-09-25 02:38:57 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
trevon/pipe!8
No description provided.