bazelbuild / rules_rust

Rust rules for Bazel
https://bazelbuild.github.io/rules_rust/
Apache License 2.0
656 stars 419 forks source link

@rules_rust//:rustfmt depends on a copy of rustfmt built for the 'exec' platform, not the 'target' platform #2684

Closed EdSchouten closed 3 months ago

EdSchouten commented 3 months ago

Imagine you're running Bazel on a Mac, but you're making use of a remote execution service that provides workers for both Linux and macOS. You want to prefer the use of Linux workers over macOS, so your .bazelrc looks like this:

build --host_platform=//:macos --extra_execution_platforms=//:linux,//:macos

Now if we invoke @rules_rust//:rustfmt, we see the following:

$ bazel run @rules_rust//:rustfmt //my/package/...
INFO: Invocation ID: 66ff4b58-bb69-42aa-969e-7bf54e029f10
INFO: Analyzed target @@rules_rust//:rustfmt (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target @@rules_rust//tools/rustfmt:target_aware_rustfmt up-to-date:
  bazel-bin/external/rules_rust/tools/rustfmt/target_aware_rustfmt
INFO: Elapsed time: 1.127s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Running command line: bazel-bin/external/rules_rust/tools/rustfmt/target_aware_rustfmt //my/package/...
Loading: 0 packages loaded
INFO: Empty results
Loading: 0 packages loaded
INFO: Empty results
Loading: 0 packages loaded
INFO: Empty results
Loading: 0 packages loaded
/private/var/tmp/_bazel_ed/2cc046446ffd8acd61a49fc7cb12510e/execroot/myworkspace/bazel-out/darwin_x86_64-fastbuild/bin/external/rules_rust/tools/rustfmt/target_aware_rustfmt.runfiles/rustfmt_nightly-2024-05-02__x86_64-unknown-linux-gnu_tools/bin/rustfmt: /private/var/tmp/_bazel_ed/2cc046446ffd8acd61a49fc7cb12510e/execroot/myworkspace/bazel-out/darwin_x86_64-fastbuild/bin/external/rules_rust/tools/rustfmt/target_aware_rustfmt.runfiles/rustfmt_nightly-2024-05-02__x86_64-unknown-linux-gnu_tools/bin/rustfmt: cannot execute binary file

This is caused by the fact that @rules_rust//tools/rustfmt:rustfmt has data = ["//rust/toolchain:current_rustfmt_toolchain"]. The latter is only intended to be used as part of ctx.actions.run() (the 'exec' platform). In this case we require that a copy of rustfmt is used for the 'target' platform.

For similar mishaps, see https://github.com/bazelbuild/bazel/issues/19645 and https://github.com/bazel-contrib/rules_oci/pull/590.