blob: 41e4e5fa57dd9631ea48cec960b39a4c90dcd16c [file] [log] [blame]
"""# Crate Universe
Crate Universe is a set of Bazel rule for generating Rust targets using Cargo.
## Experimental
`crate_universe` is experimental, and may have breaking API changes at any time. These instructions may also change without notice.
## Setup
After loading `rules_rust` in your workspace, set the following to begin using `crate_universe`:
```python
load("@rules_rust//crate_universe:crates.bzl", "crate_deps_repository")
crate_deps_repository()
```
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_deps_repository-bootstrap) on the `crate_deps_repository`
call above or [crates_repository::generator_urls](#crates_repository-generator_urls) in uses of `crates_repository`.
## Rules
- [crate_deps_repository](#crate_deps_repository)
- [crates_repository](#crates_repository)
- [crates_vendor](#crates_vendor)
- [crate.annotation](#crateannotation)
- [crate.spec](#cratespec)
- [crate.workspace_member](#crateworkspace_member)
- [render_config](#render_config)
- [splicing_config](#splicing_config)
## `crates_repository` Workflows
The [`crates_repository`](#crates_repository) rule (the primary repository rule of `cargo-bazel`) 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",
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 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("@cargo_bazel//:defs.bzl", "crate", "crates_repository", "render_config")
crates_repository(
name = "crate_index",
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",
],
)
```
[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/
"""
load(
"//crate_universe:crates.bzl",
_crate_deps_repository = "crate_deps_repository",
)
load(
"//crate_universe/private:crate.bzl",
_crate = "crate",
)
load(
"//crate_universe/private:crates_repository.bzl",
_crates_repository = "crates_repository",
)
load(
"//crate_universe/private:crates_vendor.bzl",
_crates_vendor = "crates_vendor",
)
load(
"//crate_universe/private:generate_utils.bzl",
_render_config = "render_config",
)
load(
"//crate_universe/private:splicing_utils.bzl",
_splicing_config = "splicing_config",
)
crate = _crate
crate_deps_repository = _crate_deps_repository
crates_repository = _crates_repository
crates_vendor = _crates_vendor
render_config = _render_config
splicing_config = _splicing_config