Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,36 @@ https://bazelbuild.github.io/rules_rust/rust_analyzer.html#vscode

## Advanced Options

<details>
<summary>Enable nightly rustc-dev components</summary>

Nightly crates that depend on `rustc_private` need the `rustc-dev` component in the
compiler sysroot. Opt into that only for the nightly toolchain that needs it:

```bzl
toolchains.toolchain(
name = "nightly_rust_toolchains",
edition = "2024",
include_rustc_dev = True,
version = "nightly/2026-03-05",
)
use_repo(toolchains, "nightly_rust_toolchains")
register_toolchains("@nightly_rust_toolchains//:all")
```

`include_rustc_dev` is accepted only for nightly Rust versions. It keeps the default
toolchain path unchanged and exposes separate `*_with_dev` toolchains when a build sets
both:

```bash
bazel build \
--@rules_rust//rust/toolchain/channel=nightly \
--@rules_rs//rs/toolchains/rustc_dev:enabled \
//...
```

</details>

<details>
<summary>Use legacy rules_rust toolchains or platforms</summary>

Expand Down
21 changes: 21 additions & 0 deletions rs/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,27 @@ bzl_library(
],
)

bzl_library(
name = "rustc_dev_repository",
srcs = ["rustc_dev_repository.bzl"],
visibility = ["//rs:__subpackages__"],
deps = [
"//rs/private:rust_repository_utils",
"@rules_rust//rust/platform:bzl_lib",
],
)

bzl_library(
name = "rustc_with_dev_repository",
srcs = ["rustc_with_dev_repository.bzl"],
visibility = ["//rs:__subpackages__"],
deps = [
"@bazel_features//:features",
"@rules_rust//rust/platform:bzl_lib",
"@rules_rust//rust/private:bzl_lib",
],
)

bzl_library(
name = "stdlib_repository",
srcs = ["stdlib_repository.bzl"],
Expand Down
27 changes: 27 additions & 0 deletions rs/private/rustc_dev_repository.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
load("@rules_rust//rust/platform:triple.bzl", "triple")
load(":rust_repository_utils.bzl", "RUST_REPOSITORY_COMMON_ATTR", "download_and_extract")

def _rustc_dev_repository_impl(rctx):
exec_triple = triple(rctx.attr.triple)
download_and_extract(rctx, "rustc-dev", "rustc-dev", exec_triple)

rctx.file(
"BUILD.bazel",
"""\
filegroup(
name = "rustc_dev_libs",
srcs = glob(
["lib/rustlib/{triple}/lib/*.rlib"],
allow_empty = True,
),
visibility = ["//visibility:public"],
)
""".format(triple = exec_triple.str),
)

return rctx.repo_metadata(reproducible = True)

rustc_dev_repository = repository_rule(
implementation = _rustc_dev_repository_impl,
attrs = RUST_REPOSITORY_COMMON_ATTR,
)
79 changes: 79 additions & 0 deletions rs/private/rustc_with_dev_repository.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
load("@bazel_features//:features.bzl", "bazel_features")
load("@rules_rust//rust/platform:triple.bzl", "triple")
load(
"@rules_rust//rust/private:repository_utils.bzl",
"BUILD_for_compiler",
)

def _symlink_children(rctx, source_dir, destination_dir):
if not source_dir.exists or not source_dir.is_dir:
return

rctx.file("{}/.generated".format(destination_dir), "")
for entry in source_dir.readdir():
if entry.is_dir or entry.basename.startswith("."):
continue

destination = "{}/{}".format(destination_dir, entry.basename)
if not rctx.path(destination).exists:
rctx.symlink(entry, destination)

def _rustc_with_dev_repository_impl(rctx):
exec_triple = triple(rctx.attr.triple)
rustc_repo_root = rctx.path(rctx.attr.rustc_repo_build_file).dirname
rustc_dev_repo_root = rctx.path(rctx.attr.rustc_dev_repo_build_file).dirname

# Keep the ordinary rustc repository lean. This merged sysroot is materialized
# only when a dev-enabled toolchain is actually selected.
rctx.symlink(rustc_repo_root.get_child("bin"), "bin")

rustc_lib_root = rustc_repo_root.get_child("lib")
rustc_rustlib_root = rustc_lib_root.get_child("rustlib").get_child(exec_triple.str)
rustc_dev_lib_root = rustc_dev_repo_root.get_child("lib").get_child("rustlib").get_child(exec_triple.str)

_symlink_children(rctx, rustc_lib_root, "lib")
rctx.symlink(
rustc_rustlib_root.get_child("bin"),
"lib/rustlib/{}/bin".format(exec_triple.str),
)
_symlink_children(
rctx,
rustc_rustlib_root.get_child("codegen-backends"),
"lib/rustlib/{}/codegen-backends".format(exec_triple.str),
)
_symlink_children(
rctx,
rustc_rustlib_root.get_child("lib"),
"lib/rustlib/{}/lib".format(exec_triple.str),
)
_symlink_children(
rctx,
rustc_dev_lib_root.get_child("lib"),
"lib/rustlib/{}/lib".format(exec_triple.str),
)

# `rustc_private` crates link against compiler `.rlib`s from rustc-dev.
# The upstream compiler BUILD omits `.rlib`s because ordinary toolchains do
# not need them, so extend the merged sysroot manifest only for this variant.
build_file = BUILD_for_compiler(exec_triple, include_objcopy = True)
build_file = build_file.replace(
'"lib/rustlib/{}/lib/*.rmeta",'.format(exec_triple.str),
'\n'.join([
'"lib/rustlib/{}/lib/*.rmeta",'.format(exec_triple.str),
' "lib/rustlib/{}/lib/*.rlib",'.format(exec_triple.str),
]),
)
rctx.file("BUILD.bazel", build_file)

return rctx.repo_metadata(
reproducible = bazel_features.external_deps.repo_rules_relativize_symlinks,
)

rustc_with_dev_repository = repository_rule(
implementation = _rustc_with_dev_repository_impl,
attrs = {
"rustc_repo_build_file": attr.label(allow_single_file = True, mandatory = True),
"rustc_dev_repo_build_file": attr.label(allow_single_file = True, mandatory = True),
"triple": attr.string(mandatory = True),
},
)
3 changes: 3 additions & 0 deletions rs/private/toolchains_repository.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ load("@rules_rs//rs/toolchains:declare_rustfmt_toolchains.bzl", "declare_rustfmt
declare_rustc_toolchains(
version = {version},
edition = {edition},
include_rustc_dev = {include_rustc_dev},
extra_rustc_flags = {extra_rustc_flags},
extra_exec_rustc_flags = {extra_exec_rustc_flags},
)
Expand All @@ -28,6 +29,7 @@ declare_rust_analyzer_toolchains(
rustfmt_version = repr(rctx.attr.rustfmt_version),
rust_analyzer_version = repr(rctx.attr.rust_analyzer_version),
edition = repr(rctx.attr.edition),
include_rustc_dev = repr(rctx.attr.include_rustc_dev),
extra_rustc_flags = repr(rctx.attr.extra_rustc_flags),
extra_exec_rustc_flags = repr(rctx.attr.extra_exec_rustc_flags),
),
Expand All @@ -42,6 +44,7 @@ toolchains_repository = repository_rule(
"rustfmt_version": attr.string(mandatory = True),
"rust_analyzer_version": attr.string(mandatory = True),
"edition": attr.string(mandatory = True),
"include_rustc_dev": attr.bool(),
"extra_rustc_flags": attr.string_list_dict(),
"extra_exec_rustc_flags": attr.string_list_dict(),
},
Expand Down
2 changes: 2 additions & 0 deletions rs/toolchains/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ bzl_library(
"//rs/private:rust_analyzer_repository",
"//rs/private:rust_repository_utils",
"//rs/private:rust_src_repository",
"//rs/private:rustc_dev_repository",
"//rs/private:rustc_repository",
"//rs/private:rustc_with_dev_repository",
"//rs/private:rustfmt_repository",
"//rs/private:stdlib_repository",
"//rs/private:toolchains_repository",
Expand Down
84 changes: 76 additions & 8 deletions rs/toolchains/declare_rustc_toolchains.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def declare_rustc_toolchains(
*,
version,
edition,
include_rustc_dev = False,
extra_rustc_flags = {},
extra_exec_rustc_flags = {},
execs = SUPPORTED_EXEC_TRIPLES,
Expand All @@ -34,6 +35,7 @@ def declare_rustc_toolchains(
triple_suffix = exec_triple.system + "_" + exec_triple.arch

rustc_repo_label = "@rustc_{}_{}//:".format(triple_suffix, version_key)
rustc_with_dev_repo_label = "@rustc_with_dev_{}_{}//:".format(triple_suffix, version_key)
cargo_repo_label = "@cargo_{}_{}//:".format(triple_suffix, version_key)
clippy_repo_label = "@clippy_{}_{}//:".format(triple_suffix, version_key)

Expand All @@ -42,6 +44,7 @@ def declare_rustc_toolchains(
exec_triple.arch,
version_key,
)
rust_toolchain_with_dev_name = rust_toolchain_name + "_with_dev"

rust_std_select = {}
target_triple_select = {}
Expand Down Expand Up @@ -134,8 +137,44 @@ def declare_rustc_toolchains(
**rust_toolchain_kwargs
)

if include_rustc_dev:
# Keep the ordinary toolchains registered for the default path, and
# expose parallel dev-enabled variants only to configurations that
# explicitly request the merged rustc-dev sysroot.
rust_toolchain_with_dev_kwargs = dict(rust_toolchain_kwargs)
rust_toolchain_with_dev_kwargs.update(
rust_doc = "{}rustdoc".format(rustc_with_dev_repo_label),
rustc = "{}rustc".format(rustc_with_dev_repo_label),
rust_objcopy = "{}rust-objcopy".format(rustc_with_dev_repo_label),
rustc_lib = "{}rustc_lib".format(rustc_with_dev_repo_label),
)

rust_toolchain(
name = rust_toolchain_with_dev_name,
process_wrapper = "@rules_rust//util/process_wrapper",
**rust_toolchain_with_dev_kwargs
)

rust_toolchain(
name = rust_toolchain_with_dev_name + "_bootstrap",
bootstrapping = True,
process_wrapper = "@rules_rust//util/process_wrapper:bootstrap_process_wrapper",
**rust_toolchain_with_dev_kwargs
)

for target_triple in targets:
target_key = sanitize_triple(target_triple)
bootstrapped_target_settings = [
"@rules_rust//rust/private:bootstrapped",
"@rules_rust//rust/toolchain/channel:" + channel,
]
bootstrapping_target_settings = [
"@rules_rust//rust/private:bootstrapping",
"@rules_rust//rust/toolchain/channel:" + channel,
]
if include_rustc_dev:
bootstrapped_target_settings.append("@rules_rs//rs/toolchains/rustc_dev:disabled")
bootstrapping_target_settings.append("@rules_rs//rs/toolchains/rustc_dev:disabled")

native.toolchain(
name = "{}_{}_to_{}_{}".format(exec_triple.system, exec_triple.arch, target_key, version_key),
Expand All @@ -144,10 +183,7 @@ def declare_rustc_toolchains(
"@platforms//cpu:" + exec_triple.arch,
],
target_compatible_with = triple_to_constraint_set(target_triple),
target_settings = [
"@rules_rust//rust/private:bootstrapped",
"@rules_rust//rust/toolchain/channel:" + channel,
],
target_settings = bootstrapped_target_settings,
toolchain = rust_toolchain_name,
toolchain_type = "@rules_rust//rust:toolchain_type",
visibility = ["//visibility:public"],
Expand All @@ -160,11 +196,43 @@ def declare_rustc_toolchains(
"@platforms//cpu:" + exec_triple.arch,
],
target_compatible_with = triple_to_constraint_set(target_triple),
target_settings = [
"@rules_rust//rust/private:bootstrapping",
"@rules_rust//rust/toolchain/channel:" + channel,
],
target_settings = bootstrapping_target_settings,
toolchain = rust_toolchain_name + "_bootstrap",
toolchain_type = "@rules_rust//rust:toolchain_type",
visibility = ["//visibility:public"],
)

if include_rustc_dev:
native.toolchain(
name = "{}_{}_to_{}_{}_with_dev".format(exec_triple.system, exec_triple.arch, target_key, version_key),
exec_compatible_with = [
"@platforms//os:" + exec_triple.system,
"@platforms//cpu:" + exec_triple.arch,
],
target_compatible_with = triple_to_constraint_set(target_triple),
target_settings = [
"@rules_rust//rust/private:bootstrapped",
"@rules_rust//rust/toolchain/channel:" + channel,
"@rules_rs//rs/toolchains/rustc_dev:enabled_setting",
],
toolchain = rust_toolchain_with_dev_name,
toolchain_type = "@rules_rust//rust:toolchain_type",
visibility = ["//visibility:public"],
)

native.toolchain(
name = "{}_{}_to_{}_{}_bootstrap_with_dev".format(exec_triple.system, exec_triple.arch, target_key, version_key),
exec_compatible_with = [
"@platforms//os:" + exec_triple.system,
"@platforms//cpu:" + exec_triple.arch,
],
target_compatible_with = triple_to_constraint_set(target_triple),
target_settings = [
"@rules_rust//rust/private:bootstrapping",
"@rules_rust//rust/toolchain/channel:" + channel,
"@rules_rs//rs/toolchains/rustc_dev:enabled_setting",
],
toolchain = rust_toolchain_with_dev_name + "_bootstrap",
toolchain_type = "@rules_rust//rust:toolchain_type",
visibility = ["//visibility:public"],
)
Loading