Skip to content

Commit

Permalink
Depend on a copy of rustfmt for the target
Browse files Browse the repository at this point in the history
The toolchain_files() and current_rust_toolchain() rules return files
for the current 'exec' platform. This is perfecly reasonable if you want
to use these tools as part of ctx.actions.run(). But if you want to use
these as part of 'data = []' (runfiles), they must be built for the
target.

This change adds a helper rule, toolchain_files_for_target(), which can
take the aforementioned rules as an input, transitioning it so that it
yields files for the target platform. I'm not happy with how this rule
is implemented, but there is little we can do about that until
bazelbuild/bazel#19645 is addressed.
  • Loading branch information
EdSchouten committed Jun 7, 2024
1 parent 4d3f959 commit 16c8856
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
31 changes: 30 additions & 1 deletion rust/private/toolchain_utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def _toolchain_files_impl(ctx):
)]

toolchain_files = rule(
doc = "A rule for fetching files from a rust toolchain.",
doc = "A rule for fetching files from a rust toolchain for the exec platform.",
implementation = _toolchain_files_impl,
attrs = {
"tool": attr.string(
Expand Down Expand Up @@ -95,3 +95,32 @@ current_rust_toolchain = rule(
str(Label("@rules_rust//rust:toolchain_type")),
],
)

def _transition_to_target_impl(settings, attr):
return {
# String conversion is needed to prevent a crash with Bazel 6.x.
"//command_line_option:extra_execution_platforms": [
str(platform)
for platform in settings["//command_line_option:platforms"]
],
}

_transition_to_target = transition(
implementation = _transition_to_target_impl,
inputs = ["//command_line_option:platforms"],
outputs = ["//command_line_option:extra_execution_platforms"],
)

def _toolchain_files_for_target_impl(ctx):
return [ctx.attr.toolchain_files[0][DefaultInfo]]

toolchain_files_for_target = rule(
doc = "A rule for fetching files from a rust toolchain for the target platform.",
implementation = _toolchain_files_for_target_impl,
attrs = {
"toolchain_files": attr.label(cfg = _transition_to_target, mandatory = True),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
)
14 changes: 10 additions & 4 deletions tools/rustfmt/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("//rust:defs.bzl", "rust_binary", "rust_clippy", "rust_library")
load("//rust/private:toolchain_utils.bzl", "toolchain_files_for_target")
load("//tools:tool_utils.bzl", "aspect_repository")

exports_files(
Expand All @@ -9,6 +10,11 @@ exports_files(
visibility = ["//visibility:public"],
)

toolchain_files_for_target(
name = "current_rustfmt_toolchain_for_target",
toolchain_files = "//rust/toolchain:current_rustfmt_toolchain",
)

rust_library(
name = "rustfmt_lib",
srcs = glob(
Expand All @@ -19,12 +25,12 @@ rust_library(
],
),
data = [
":current_rustfmt_toolchain_for_target",
"//:rustfmt.toml",
"//rust/toolchain:current_rustfmt_toolchain",
],
edition = "2018",
rustc_env = {
"RUSTFMT": "$(rlocationpath //rust/toolchain:current_rustfmt_toolchain)",
"RUSTFMT": "$(rlocationpath :current_rustfmt_toolchain_for_target)",
"RUSTFMT_CONFIG": "$(rlocationpath //:rustfmt.toml)",
},
deps = [
Expand Down Expand Up @@ -91,10 +97,10 @@ rust_binary(
srcs = [
"src/upstream_rustfmt_wrapper.rs",
],
data = ["//rust/toolchain:current_rustfmt_toolchain"],
data = [":current_rustfmt_toolchain_for_target"],
edition = "2018",
rustc_env = {
"RUSTFMT": "$(rlocationpath //rust/toolchain:current_rustfmt_toolchain)",
"RUSTFMT": "$(rlocationpath :current_rustfmt_toolchain_for_target)",
},
toolchains = ["@rules_rust//rust/toolchain:current_rust_toolchain"],
visibility = ["//visibility:public"],
Expand Down

0 comments on commit 16c8856

Please sign in to comment.