bazelbuild / bazelbuild/rules_rust
C++ linker and sysroot paths are not rewritten by Bazel path mapping
- Dominant language
- Starlark
- Stars
- 843
- Forks
- 651
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 15
Description
rustc actions advertise `supports-path-mapping`, but the C++ linker returned by
`cc_common.get_tool_for_action()` is passed to `rustc` as an analysis-time
string:
```starlark
rustc_flags.add(ld, format = "--codegen=linker=%s")
```
The C++ link arguments are also passed as strings:
```starlark
rustc_flags.add_all(link_args, format_each = "--codegen=link-arg=%s")
```
Bazel only rewrites paths that retain their `File` identity when expanded
through an `Args` object. It cannot rewrite arbitrary strings containing
`file.path`.
When `--experimental_output_paths=strip` is enabled, the Rustc action executes
against the path-mapped `bazel-out/cfg` layout, but `--codegen=linker` and
linker arguments such as `--sysroot` can still refer to their analysis-time
`bazel-out/-exec` paths.
This causes Rust linking to fail when using a hermetic C++ toolchain whose
linker or sysroot is a Bazel artifact.
## Example failure
The generated Rustc command contains arguments similar to:
```text
--codegen=linker=bazel-out/-exec/bin/.../x86_64-linux-g++.br_real
--codegen=link-arg=--sysroot=bazel-out/-exec/bin/.../sysroot
```
The action sandbox instead contains the toolchain under:
```text
bazel-out/cfg/bin/...
```
Rustc therefore fails to execute the linker, or the linker fails to find its
sysroot.
## Expected behavior
All artifact paths supplied to an action that advertises
`supports-path-mapping` should be passed through path-mapping-aware `Args`
entries.
In particular:
- `--codegen=linker` should use the corresponding C++ toolchain `File`.
- A path-bearing C++ `--sysroot` argument should be derived from an artifact
that Bazel can map at action execution time.
- Tool executables contained within directory/tree artifacts should also be
supported.
- Existing behavior should remain available as a fallback when the linker
cannot be associated with a toolchain artifact.
## Actual behavior
`cc_common.get_tool_for_action()` returns the linker path as a string.
`rules_rust` forwards that string directly to `rustc`, so Bazel cannot rewrite
its output-path prefix.
The same problem affects a `--sysroot` value returned as part of the C++
toolchain command line.
## Reproduction outline
1. Configure a hermetic C++ toolchain whose linker and sysroot are generated or
external Bazel artifacts.
2. Build a `rust_binary` that uses the C++ linker.
3. Enable:
```text
--experimental_output_paths=strip
```
4. Observe that the Rustc action uses `bazel-out/cfg`, while
`--codegen=linker` or `--codegen=link-arg=--sysroot=...` still contains the
analysis-time configuration path.
Disabling stripped output paths avoids the mismatch.
## Related work
- #4011 added general support for `experimental_output_paths`.
- #3927 included a change to pass `--codegen=linker` using a `File`, but it was
closed after #4011 was believed to cover the same work.
The current `main` branch still passes both the linker and link arguments as
strings, so this part of #3927 does not appear to have been incorporated by
#4011.
## Suggested direction
Associate the path returned by `cc_common.get_tool_for_action()` with a member
of the C++ toolchain's linker/all-files artifact sets, preserving a directory
artifact plus relative suffix when necessary.
Pass that artifact through `Args.add` for `--codegen=linker`. Path-bearing
linker arguments such as `--sysroot` should similarly be constructed from a
typed artifact at argument-expansion time.
A regression test should use a C++ toolchain whose linker and sysroot live
under a configuration-dependent output path and build with
`--experimental_output_paths=strip`.
```
Contributor guide
Research direction
Start at the cc_common.get_tool_for_action() call and the rustc_flags Args construction described in the issue. Inspect the C++ toolchain linker/all-files artifact sets and how path-bearing --sysroot arguments are represented. Add a regression test using configuration-dependent linker and sysroot artifacts with --experimental_output_paths=strip; done means Bazel rewrites these paths while preserving the fallback behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, rust
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100