1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
"""# Crate Universe
Crate Universe is a set of Bazel rule for generating Rust targets using Cargo.
## Setup
After loading `rules_rust` in your workspace, set the following to begin using `crate_universe`:
```python
load("@rules_rust//crate_universe:repositories.bzl", "crate_universe_dependencies")
crate_universe_dependencies()
```
Note that if the current version of `rules_rust` is not a release artifact, you may need to set additional
flags such as [`bootstrap = True`](#crate_universe_dependencies-bootstrap) on the `crate_universe_dependencies`
call above or [crates_repository::generator_urls](#crates_repository-generator_urls) in uses of `crates_repository`.
## Rules
- [crates_repository](#crates_repository)
- [crates_vendor](#crates_vendor)
## Utility Macros
- [crate_universe_dependencies](#crate_universe_dependencies)
- [crate.annotation](#crateannotation)
- [crate.spec](#cratespec)
- [crate.workspace_member](#crateworkspace_member)
- [render_config](#render_config)
- [splicing_config](#splicing_config)
## Workflows
The [`crates_repository`](#crates_repository) rule (the primary repository rule of `rules_rust`'s cargo support) supports a number of different
ways users can express and organize their dependencies. The most common are listed below though there are more to be found in
the [./examples/crate_universe](https://github.com/bazelbuild/rules_rust/tree/main/examples/crate_universe) directory.
### Cargo Workspaces
One of the simpler ways to wire up dependencies would be to first structure your project into a [Cargo workspace][cw].
The `crates_repository` rule can ingest a root `Cargo.toml` file and generate dependencies from there.
```python
load("@rules_rust//crate_universe:defs.bzl", "crates_repository")
crates_repository(
name = "crate_index",
cargo_lockfile = "//:Cargo.lock",
lockfile = "//:Cargo.Bazel.lock",
manifests = ["//:Cargo.toml"],
)
load("@crate_index//:defs.bzl", "crate_repositories")
crate_repositories()
```
The generated `crates_repository` contains helper macros which make collecting dependencies for Bazel targets simpler.
Notably, the `all_crate_deps` and `aliases` macros (see [Dependencies API](#dependencies-api)) commonly allow the
`Cargo.toml` files to be the single source of truth for dependencies. Since these macros come from the generated
repository, the dependencies and alias definitions they return will automatically update BUILD targets.
```python
load("@crate_index//:defs.bzl", "aliases", "all_crate_deps")
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
rust_library(
name = "lib",
aliases = aliases(),
deps = all_crate_deps(
normal = True,
),
proc_macro_deps = all_crate_deps(
proc_macro = True,
),
)
rust_test(
name = "unit_test",
crate = ":lib",
aliases = aliases(
normal_dev = True,
proc_macro_dev = True,
),
deps = all_crate_deps(
normal_dev = True,
),
proc_macro_deps = all_crate_deps(
proc_macro_dev = True,
),
)
```
### Direct Packages
In cases where Rust targets have heavy interractions with other Bazel targests ([Cc][cc], [Proto][proto], etc.),
maintaining `Cargo.toml` files may have deminishing returns as things like [rust-analyzer][ra] begin to be confused
about missing targets or environment variables defined only in Bazel. In workspaces like this, it may be desirable
to have a "Cargo free" setup. `crates_repository` supports this through the `packages` attribute.
```python
load("@rules_rust//crate_universe:defs.bzl", "crate", "crates_repository", "render_config")
crates_repository(
name = "crate_index",
cargo_lockfile = "//:Cargo.lock",
lockfile = "//:Cargo.Bazel.lock",
packages = {
"async-trait": crate.spec(
version = "0.1.51",
),
"mockall": crate.spec(
version = "0.10.2",
),
"tokio": crate.spec(
version = "1.12.0",
),
},
# Setting the default package name to `""` forces the use of the macros defined in this repository
# to always use the root package when looking for dependencies or aliases. This should be considered
# optional as the repository also exposes alises for easy access to all dependencies.
render_config = render_config(
default_package_name = ""
),
)
load("@crate_index//:defs.bzl", "crate_repositories")
crate_repositories()
```
Consuming dependencies may be more ergonomic in this case through the aliases defined in the new repository.
```python
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
rust_library(
name = "lib",
deps = [
"@crate_index//:tokio",
],
proc_macro_deps = [
"@crate_index//:async-trait",
],
)
rust_test(
name = "unit_test",
crate = ":lib",
deps = [
"@crate_index//:mockall",
],
)
```
### Binary dependencies
Neither of the above approaches supports depending on binary-only packages.
In order to depend on a Cargo package that contains binaries and no library, you
will need to do one of the following:
- Fork the package to add an empty lib.rs, which makes the package visible to
Cargo metadata and compatible with the above approaches;
- Or handwrite your own build target for the binary, use `http_archive` to
import its source code, and use `crates_repository` to make build targets for
its dependencies. This is demonstrated below using the `rustfilt` crate as an
example.
```python
# in WORKSPACE.bazel
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rustfilt",
build_file = "//rustfilt:BUILD.rustfilt.bazel",
sha256 = "c8d748b182c8f95224336d20dcc5609598af612581ce60cfb29da4dc8d0091f2",
strip_prefix = "rustfilt-0.2.1",
type = "tar.gz",
urls = ["https://crates.io/api/v1/crates/rustfilt/0.2.1/download"],
)
load("@rules_rust//crate_universe:defs.bzl", "crates_repository")
crates_repository(
name = "rustfilt_deps",
cargo_lockfile = "//rustfilt:Cargo.lock",
manifests = ["@rustfilt//:Cargo.toml"],
)
load("@rustfilt_deps//:defs.bzl", rustfilt_deps = "crate_repositories")
rustfilt_deps()
```
```python
# in rustfilt/BUILD.rustfilt.bazel
load("@rules_rust//rust:defs.bzl", "rust_binary")
rust_binary(
name = "rustfilt",
srcs = glob(["src/**/*.rs"]),
edition = "2018",
deps = [
"@rustfilt_deps//:clap",
"@rustfilt_deps//:lazy_static",
"@rustfilt_deps//:regex",
"@rustfilt_deps//:rustc-demangle",
],
)
```
If you use either `crates_repository` or `crates_vendor` to depend on a Cargo
package that contains _both_ a library crate _and_ binaries, by default only the
library gets made available to Bazel. To generate Bazel targets for the binary
crates as well, you must opt in to it with an annotation on the package:
```python
load("@rules_rust//crate_universe:defs.bzl", "crates_repository", "crate")
crates_repository(
name = "crate_index",
annotations = {
"thepackage": [crate.annotation(
gen_binaries = True,
# Or, to expose just a subset of the package's binaries by name:
gen_binaries = ["rustfilt"],
)],
},
# Or, to expose every binary of every package:
generate_binaries = True,
...
)
```
## Dependencies API
After rendering dependencies, convenience macros may also be generated to provide
convenient accessors to larger sections of the dependency graph.
- [aliases](#aliases)
- [crate_deps](#crate_deps)
- [all_crate_deps](#all_crate_deps)
- [crate_repositories](#crate_repositories)
---
---
[cw]: https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html
[cc]: https://docs.bazel.build/versions/main/be/c-cpp.html
[proto]: https://rules-proto-grpc.com/en/latest/lang/rust.html
[ra]: https://rust-analyzer.github.io/
"""
# Rules
=
=
# Utility Macros
=
=
=
=
# Dependencies API
=
=
=
=