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:
rustc_flags.add(ld, format = "--codegen=linker=%s")
The C++ link arguments are also passed as strings:
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/<configuration>-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:
--codegen=linker=bazel-out/<configuration>-exec/bin/.../x86_64-linux-g++.br_real
--codegen=link-arg=--sysroot=bazel-out/<configuration>-exec/bin/.../sysroot
The action sandbox instead contains the toolchain under:
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
-
Configure a hermetic C++ toolchain whose linker and sysroot are generated or
external Bazel artifacts.
-
Build a rust_binary that uses the C++ linker.
-
Enable:
--experimental_output_paths=strip
-
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
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.
rustc actions advertise
supports-path-mapping, but the C++ linker returned bycc_common.get_tool_for_action()is passed torustcas an analysis-timestring:
The C++ link arguments are also passed as strings:
Bazel only rewrites paths that retain their
Fileidentity when expandedthrough an
Argsobject. It cannot rewrite arbitrary strings containingfile.path.When
--experimental_output_paths=stripis enabled, the Rustc action executesagainst the path-mapped
bazel-out/cfglayout, but--codegen=linkerandlinker arguments such as
--sysrootcan still refer to their analysis-timebazel-out/<configuration>-execpaths.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:
The action sandbox instead contains the toolchain under:
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-mappingshould be passed through path-mapping-awareArgsentries.
In particular:
--codegen=linkershould use the corresponding C++ toolchainFile.--sysrootargument should be derived from an artifactthat Bazel can map at action execution time.
supported.
cannot be associated with a toolchain artifact.
Actual behavior
cc_common.get_tool_for_action()returns the linker path as a string.rules_rustforwards that string directly torustc, so Bazel cannot rewriteits output-path prefix.
The same problem affects a
--sysrootvalue returned as part of the C++toolchain command line.
Reproduction outline
Configure a hermetic C++ toolchain whose linker and sysroot are generated or
external Bazel artifacts.
Build a
rust_binarythat uses the C++ linker.Enable:
Observe that the Rustc action uses
bazel-out/cfg, while--codegen=linkeror--codegen=link-arg=--sysroot=...still contains theanalysis-time configuration path.
Disabling stripped output paths avoids the mismatch.
Related work
experimental_output_paths#4011 added general support forexperimental_output_paths.--codegen=linkerusing aFile, but it wasclosed after Add support for
experimental_output_paths#4011 was believed to cover the same work.The current
mainbranch still passes both the linker and link arguments asstrings, 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 memberof the C++ toolchain's linker/all-files artifact sets, preserving a directory
artifact plus relative suffix when necessary.
Pass that artifact through
Args.addfor--codegen=linker. Path-bearinglinker arguments such as
--sysrootshould similarly be constructed from atyped 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.