-
Notifications
You must be signed in to change notification settings - Fork 79
Description
When using hermetic_cc_toolchain with rules_rust, running bazel coverage on Rust targets fails with:
ld.lld: error: cannot open __llvm_profile_runtime: No such file or directory
This is caused by Zig's clang driver misinterpreting the -u SYMBOL linker flag format.
Environment
- hermetic_cc_toolchain: 4.1.0
- rules_rust: 0.68.1
- Zig: 0.12.0 (bundled with hermetic_cc_toolchain)
- Bazel: 8.x
- OS: Linux x86_64
Steps to Reproduce
Open GitHub codespace from my minimal reproduction repo: https://github.com/anthropics/bazel-cpp-rust-codecov
bazel coverage //rust:greeter_test
<succeeds as patch has been applied>
git rebase to remove single git commit patch
bazel coverage //rust:greeter_test
<fails>: ld.lld: error: cannot open __llvm_profile_runtime: No such file or directoryExpected Behavior
Coverage builds and tests run successfully, generating LCOV coverage data.
Actual Behavior
Build fails during linking with:
error: linking with `external/hermetic_cc_toolchain~~toolchains~zig_config/tools/x86_64-linux-gnu.2.17/c++` failed: exit status: 1
|
= note: ld.lld: error: cannot open __llvm_profile_runtime: No such file or directory
Root Cause
When bazel coverage runs, rustc passes coverage instrumentation flags to the linker:
-u __llvm_profile_runtime -fprofile-instr-generate
The -u SYMBOL flag tells the linker to force a symbol to be undefined (ensuring it gets linked in). However, Zig's clang driver incorrectly parses this:
- It matches
-uagainst the Windows/uCLFlag (undefine macro) instead of the Unix linker-uflag - This consumes
-uas a standalone flag __llvm_profile_runtimeis then treated as a positional argument (input filename)- Zig tries to open it as a file →
FileNotFound/No such file or directory
This can be verified by testing directly with Zig:
# Fails - Zig misparses -u
echo 'int main(){}' | zig c++ -x c - -u __test_symbol -target x86_64-linux-gnu -o /dev/null
# __test_symbol:1:1: error: FileNotFound
# Works - using -Wl to bypass Zig's argument parsing
echo 'int main(){}' | zig c++ -x c - -Wl,-u,__test_symbol -target x86_64-linux-gnu -o /dev/null
# SuccessUpstream Zig Bug
This is a known bug in Zig, tracked at:
- Issue: https://codeberg.org/ziglang/zig/issues/30613
- Fix PR: https://codeberg.org/ziglang/zig/pulls/30749
The fix modifies src/clang_options_data.zig to prevent the Windows /u CLFlag from matching when using a dash prefix (-u).
Workaround
Until the Zig fix is released, the issue can be worked around by patching zig-wrapper.zig to transform -u SYMBOL into -Wl,-u,SYMBOL.
I have posted #242 for consideration with this workaround.
Suggested Resolution
- Short-term: Consider including this patch in
hermetic_cc_toolchainuntil Zig releases a fix - Long-term: Remove the patch once a fixed Zig version is bundled
Related Issues
- Zig issue: https://codeberg.org/ziglang/zig/issues/30613
- Zig fix PR: https://codeberg.org/ziglang/zig/pulls/30749