Skip to content

Commit 97f84f5

Browse files
committed
Update README
1 parent 9050491 commit 97f84f5

2 files changed

Lines changed: 251 additions & 13 deletions

File tree

README.md

Lines changed: 144 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,54 @@
11
## Overview
22

3-
This ruleset is a companion to [rules_rust](https://github.com/bazelbuild/rules_rust) which provides a reimplementation of `crate_universe`. It integrates tightly with Bazel's downloader and the lockfile facts API, allowing automatic,
4-
extremely fast, incremental resolution without the Bazel-specific Cargo lockfile that `rules_rust` uses.
3+
`rules_rs` is both a wrapper around [rules_rust](https://github.com/bazelbuild/rules_rust) and an alternative implementation for selected parts of the Rust + Bazel stack.
54

6-
## Installation
5+
It is designed to:
76

7+
- Reuse stable `rules_rust` functionality, such as the core compilation rules.
8+
- Provide alternative implementations where there is a benefit to be gained (`crate_universe`-style dependency resolution and toolchain provisioning).
9+
- Let users migrate incrementally while still reusing selected `rules_rust` components (for example toolchains).
10+
11+
## Advantages Over `rules_rust`
12+
13+
- Extremely fast (~200ms) incremental dependency resolution via Bazel downloader integration and lockfile facts. Uses your Cargo lockfile directly. No "Cargo workspace splicing", no Bazel-specific Cargo lockfile.
14+
- Toolchains are more flexible, powerful, and lightweight. We don't register any toolchains by default, but with a 1-line `register_toolchains` call you can have a working setup for the entire cross-product of supported exec and target triples. The support matrix is wider than rules_rust, we support multiple ABIs per OS (-msvc, -gnu, and -gnullvm on Windows, -gnu and -musl on Linux). We bring fully hermetic `-musl`, `-gnullvm`, and OSX linker runtimes thanks to @llvm module, so you can do full cross builds from any host platform to any target platform, including with remote execution. (OSX host, linux remote executor, Windows gnullvm target works seamlessly). See [PR #21](https://github.com/dzbarsky/rules_rs/pull/21) for more details.
15+
- The patched `rules_rust` extension provides all underlying rules_rust functionality with many fixes applied (Windows linking works now, various rust-analyzer improvements, etc.)
16+
17+
# Installation and Configuraiton
18+
19+
```bzl
20+
bazel_dep(name = "rules_rs", version = "0.0.33")
821
```
9-
bazel_dep(name = "rules_rs", version = "0.0.1")
10-
```
1122

12-
## Usage
13-
Usage is basically the same as in rules_rust, with a few attributes renamed for clarity.
23+
## Toolchains
24+
25+
Strongly recommended: use `rules_rs` toolchains.
26+
27+
You can still use `rules_rust` toolchains when doing a gradual migration, but that should be considered a compatibility on-ramp rather than the default.
1428

29+
### Option A: `rules_rs` toolchains (recommended)
30+
31+
```bzl
32+
toolchains = use_extension("@rules_rs//rs/experimental/toolchains:module_extension.bzl", "toolchains")
33+
34+
toolchains.toolchain(
35+
edition = "2024",
36+
version = "1.92.0",
37+
)
38+
39+
use_repo(toolchains, "default_rust_toolchains")
40+
register_toolchains("@default_rust_toolchains//:all")
1541
```
42+
43+
Make sure you set `use_experimental_platforms = True` in `crate.from_cargo(...)`.
44+
45+
### Option B: Keep your existing `rules_rust` toolchain configuration.
46+
47+
## Dependency Resolution
48+
49+
`rules_rs` uses its own `crate_universe` implementation through `crate.from_cargo`:
50+
51+
```bzl
1652
crate = use_extension("@rules_rs//rs:extensions.bzl", "crate")
1753

1854
crate.from_cargo(
@@ -25,23 +61,118 @@ crate.from_cargo(
2561
"x86_64-apple-darwin",
2662
"x86_64-unknown-linux-gnu",
2763
],
64+
# True when using rules_rs experimental toolchains/platforms.
65+
# False (default) when using rules_rust toolchains/platforms.
66+
use_experimental_platforms = True,
2867
)
2968

30-
crate.annotation(
31-
crate = "backtrace",
32-
gen_build_script = "off",
69+
use_repo(crate, "crates")
70+
```
71+
72+
`crate.spec` and vendoring mode are currently unsupported.
73+
74+
### Exec vs target triple caveats
75+
76+
- Windows: the default Windows **exec** toolchain is MSVC-flavored. The upstream `gnullvm` toolchain dynamically links `libunwind`, which may not exist on a stock Windows machine.
77+
- If you target `*-pc-windows-gnullvm`, resolve both triples in dependency resolution (`crate.from_cargo`): one MSVC triple for exec/build-script/proc-macro work and one `gnullvm` triple for target artifacts.
78+
- Linux: similarly, when targeting `*-unknown-linux-musl`, also include the corresponding `*-unknown-linux-gnu` triple for exec. Proc macros and build scripts run in exec configuration, and Linux exec toolchains are GNU. This is required because the current `@toolchains_llvm_bootstrapped` flow cannot produce musl-flavored proc-macro `.so` artifacts for exec.
79+
80+
Example `platform_triples` values:
81+
82+
```bzl
83+
# Windows gnullvm target with MSVC exec.
84+
platform_triples = [
85+
"x86_64-pc-windows-msvc", # exec
86+
"x86_64-pc-windows-gnullvm", # target
87+
]
88+
89+
# Linux musl target with GNU exec.
90+
platform_triples = [
91+
"x86_64-unknown-linux-gnu", # exec
92+
"x86_64-unknown-linux-musl", # target
93+
]
94+
```
95+
96+
# TODO(zbarsky): Should we issue warnings if you configure the triples in an unexpected way?
97+
98+
## Import `rules_rust` from `rules_rs`
99+
100+
`rules_rs` exports a `rules_rust` module extension you can use to provision the pinned `rules_rust` repo:
101+
102+
```bzl
103+
rules_rust = use_extension("@rules_rs//rs/experimental:rules_rust.bzl", "rules_rust")
104+
use_repo(rules_rust, "rules_rust")
105+
```
106+
107+
The core compilation rules (`rust_library`, `rust_binary`, `rust_test`, `rust_proc_macro`, `rust_static_library`, and `rust_dynamic_library`) can be loaded directly from `@rules_rs//rs:*.bzl` but clippy integration, protobuf, etc come from rules_rust for now.
108+
Using this extension is STRONGLY ENCOURAGED because it carries fixes that improve Windows behavior, rust-analyzer integration, and related compatibility work.
109+
In addition, when using the `rules_rs` toolchains, loading the compilation rules from `@rules_rs` directly and using the extension is REQUIRED for toolchain resolution to work correctly, at least until https://github.com/bazelbuild/rules_rust/pull/3857 is accepted by rules_rust maintainers. See the Migration section for more info.
110+
111+
## Platform Configuration
112+
113+
For reliable toolchain resolution, ABI choices should be explicit on every platform participating in your build, including the host platform.
114+
115+
Linux and Windows each have ABI variants that affect toolchain matching (gnu/musl on Linux, msvc/gnu/gnullvm on Windows). Implicit/default platforms lacking these constraints will result in toolchain resolution errors, as no toolchains will match.
116+
117+
At minimum, set an explicit `--host_platform` that adds your ABI constraint on top of `@platforms//host`:
118+
119+
`.bazelrc`:
120+
121+
```bazelrc
122+
common:linux --host_platform=//platforms:local_gnu
123+
common:windows --host_platform=//platforms:local_windows_msvc
124+
```
125+
126+
`platforms/BUILD.bazel`:
127+
128+
```bzl
129+
# Host platform with an explicit Linux GNU ABI choice.
130+
platform(
131+
name = "local_gnu",
132+
parents = ["@platforms//host"],
133+
constraint_values = [
134+
"@llvm//constraints/libc:gnu.2.28",
135+
],
33136
)
34137

35-
...
138+
# Host platform with an explicit Windows ABI choice.
139+
platform(
140+
name = "local_windows_msvc",
141+
parents = ["@platforms//host"],
142+
constraint_values = [
143+
"@rules_rs//rs/experimental/platforms/constraints:windows_msvc",
144+
],
145+
)
36146
```
37147

38-
`crate.spec` and vendoring mode are currently unsupported.
148+
Set host ABI constraints to match your exec toolchain choice; handle target ABI differences via target platforms and `platform_triples`.
39149

40-
# Public API
150+
For remote execution platforms, you can inherit from a triple-based platform published in `@rules_rs//rs/experimental/platforms` and then layer exec properties:
151+
152+
```bzl
153+
platform(
154+
name = "rbe_linux_amd64_gnu",
155+
parents = ["@rules_rs//rs/experimental/platforms:x86_64-unknown-linux-gnu"],
156+
exec_properties = {
157+
"container-image": "docker://ghcr.io/example/rbe-linux-gnu:latest",
158+
},
159+
)
160+
```
161+
162+
## Migration
163+
164+
A sample migration script is provided at `scripts/rewrite_rules_rust_loads.sh`. It rewrites common `@rules_rust` Rust loads to `@rules_rs//rs:*` wrappers and then formats with `buildifier`.
165+
166+
```bash
167+
./scripts/rewrite_rules_rust_loads.sh
168+
```
169+
170+
## Public API
41171

42172
See https://registry.bazel.build/docs/rules_rs
43173

44174
## Users
175+
45176
- [OpenAI Codex](https://github.com/openai/codex)
46177
- [Aspect CLI](https://github.com/aspect-build/aspect-cli)
47178
- [Datadog Agent](https://github.com/DataDog/datadog-agent)
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
if ! command -v rg >/dev/null 2>&1; then
5+
echo "error: rg is required" >&2
6+
exit 1
7+
fi
8+
9+
if ! command -v buildozer >/dev/null 2>&1; then
10+
echo "error: buildozer is required" >&2
11+
exit 1
12+
fi
13+
14+
if ! command -v buildifier >/dev/null 2>&1; then
15+
echo "error: buildifier is required" >&2
16+
exit 1
17+
fi
18+
19+
workspace_root="${1:-.}"
20+
cd "${workspace_root}"
21+
22+
starlark_globs=(
23+
--glob 'BUILD'
24+
--glob 'BUILD.*'
25+
--glob '*.bzl'
26+
)
27+
28+
mapfile -t candidate_files < <(rg -l "${starlark_globs[@]}" 'load\("@rules_rust//(rust|cargo):' || true)
29+
30+
if ((${#candidate_files[@]} == 0)); then
31+
echo "No @rules_rust rust/cargo load statements found."
32+
exit 0
33+
fi
34+
35+
to_targets() {
36+
local files=("$@")
37+
local file basename dir
38+
local -A seen=()
39+
targets_out=()
40+
for file in "${files[@]}"; do
41+
file="${file#./}"
42+
basename="$(basename "${file}")"
43+
case "${basename}" in
44+
BUILD | BUILD.*)
45+
dir="$(dirname "${file}")"
46+
if [[ "${dir}" == "." ]]; then
47+
target="//:all"
48+
else
49+
target="//${dir}:all"
50+
fi
51+
;;
52+
*.bzl)
53+
# buildozer edits non-BUILD files when the file path is used as package.
54+
target="//${file}:all"
55+
;;
56+
*)
57+
continue
58+
;;
59+
esac
60+
if [[ -z "${seen["${target}"]:-}" ]]; then
61+
targets_out+=("${target}")
62+
seen["${target}"]=1
63+
fi
64+
done
65+
}
66+
67+
to_targets "${candidate_files[@]}"
68+
all_targets=("${targets_out[@]}")
69+
70+
for command in \
71+
'substitute_load ^@rules_rust//rust:rust_static_library\.bzl$ @rules_rs//rs:rust_static_library.bzl' \
72+
'substitute_load ^@rules_rust//rust:rust_shared_library\.bzl$ @rules_rs//rs:rust_shared_library.bzl' \
73+
'substitute_load ^@rules_rust//cargo/private:cargo_build_script_wrapper\.bzl$ @rules_rs//rs:cargo_build_script.bzl'
74+
do
75+
buildozer -k "${command}" "${all_targets[@]}" >/dev/null 2>&1 || true
76+
done
77+
78+
rewrites=(
79+
'rust_binary @rules_rs//rs:rust_binary.bzl'
80+
'rust_library @rules_rs//rs:rust_library.bzl'
81+
'rust_proc_macro @rules_rs//rs:rust_proc_macro.bzl'
82+
'rust_test @rules_rs//rs:rust_test.bzl'
83+
'rust_static_library @rules_rs//rs:rust_static_library.bzl'
84+
'rust_shared_library @rules_rs//rs:rust_shared_library.bzl'
85+
'cargo_build_script @rules_rs//rs:cargo_build_script.bzl'
86+
)
87+
88+
for rewrite in "${rewrites[@]}"; do
89+
symbol="${rewrite%% *}"
90+
module="${rewrite##* }"
91+
92+
# Match only positional imports (example: "rust_binary"), not aliased imports.
93+
pattern="load\\(\\s*\"@rules_rust//[^\\\"]+\"(?s:[^\\)]*?,\\s*\"${symbol}\")"
94+
mapfile -t symbol_files < <(rg -l -U -P "${starlark_globs[@]}" "${pattern}" || true)
95+
if ((${#symbol_files[@]} == 0)); then
96+
continue
97+
fi
98+
99+
to_targets "${symbol_files[@]}"
100+
symbol_targets=("${targets_out[@]}")
101+
buildozer -k "replace_load ${module} ${symbol}" "${symbol_targets[@]}" >/dev/null 2>&1 || true
102+
done
103+
104+
buildifier -mode=fix "${candidate_files[@]}"
105+
106+
echo "Rewrote common @rules_rust load statements in ${#candidate_files[@]} file(s)."
107+
echo "Note: aliased imports (example: rb = \"rust_binary\") are not auto-rewritten."

0 commit comments

Comments
 (0)