-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
163 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,168 @@ | ||
|
||
## gazelle_rust | ||
## gazelle\_rust | ||
|
||
A Gazelle language plugin for Rust; automatic dependency management for Rust projects built with | ||
Bazel. See [example](https://github.com/Calsign/gazelle_rust/tree/main/example) for how to use. | ||
Bazel. | ||
|
||
References: | ||
- [Gazelle](https://github.com/bazelbuild/bazel-gazelle) | ||
- [rules_rust](https://github.com/bazelbuild/rules_rust) | ||
- [rules\_rust](https://github.com/bazelbuild/rules_rust) | ||
- [Bazel](https://bazel.build/) | ||
|
||
## Setup | ||
|
||
[`example/WORKSPACE`](https://github.com/Calsign/gazelle_rust/blob/main/example/WORKSPACE) shows how | ||
to load rules\_rust and gazelle\_rust together. In a real project, you would need to use | ||
`http_archive` instead of `local_repository`, for example: | ||
|
||
```py | ||
GAZELLE_RUST_COMMIT = "<commit>" | ||
GAZELLE_RUST_SHA256 = "<hash>" | ||
|
||
http_archive( | ||
name = "gazelle_rust", | ||
sha256 = GAZELLE_RUST_SHA256, | ||
strip_prefix = "gazelle_rust-{}".format(GAZELLE_RUST_COMMIT), | ||
url = "https://github.com/Calsign/gazelle_rust/archive/{}.zip".format(GAZELLE_RUST_COMMIT), | ||
) | ||
``` | ||
|
||
gazelle\_rust doesn't have any releases yet, so please just pick the latest commit on `main`. To | ||
determine the sha256, first set the value to `None`, then fill in the sha256 that bazel tells you. | ||
|
||
gazelle\_rust currently requires a patch to rules\_rust in order to expose the logic needed to parse | ||
crate\_universe lockfiles. This is required even if you don't use crate\_universe. gazelle\_rust | ||
provides patches that work both with and without the `-p1` flag, and `example/WORKSPACE` shows how | ||
to apply the patch to rules\_rust. | ||
|
||
The dependencies for gazelle\_rust itself are loaded through two repository rule macros, shown in | ||
`example/WORKSPACE`. This includes setting up gazelle, but you may use a different gazelle version | ||
by loading the gazelle repo before calling `gazelle_rust_dependencies*`. | ||
|
||
gazelle\_rust includes a patch to gazelle which allows for reporting unused crate\_universe | ||
dependencies. If you do not include the patch, everything else will still work fine but unused | ||
crate\_universe dependencies will not be reported. | ||
|
||
## Running gazelle | ||
|
||
[`example/BUILD.bazel`](https://github.com/Calsign/gazelle_rust/blob/main/example/BUILD.bazel) shows | ||
how to create the gazelle target. With the gazelle target defined, you can run it: | ||
|
||
```sh | ||
bazel run //:gazelle | ||
``` | ||
|
||
This will modify your build files in-place to create and update rust targets for all of the rust | ||
files in your project. | ||
|
||
gazelle\_rust provides a premade gazelle binary, but you can also create your own `gazelle_binary` | ||
target and add `@gazelle_rust//rust_language` to languages. | ||
|
||
## Generated targets | ||
|
||
[`example/src/BUILD.bazel`](https://github.com/Calsign/gazelle_rust/blob/main/example/src/BUILD.bazel) | ||
shows sample targets generated by gazelle. The following rules are supported: | ||
|
||
* `rust_library` | ||
* `rust_binary` | ||
* `rust_test` | ||
* `rust_proc_macro` | ||
* `rust_shared_library` | ||
* `rust_static_library` | ||
|
||
When generating targets for new sources (those not already listed in `srcs` for an existing target), | ||
gazelle\_rust will infer the rule kind based on information like whether the file has a `main` and | ||
the name of the directory. The full logic is in `inferRuleKind` in | ||
[`rust_language/generate.go`](https://github.com/Calsign/gazelle_rust/blob/main/rust_language/generate.go). | ||
If you change the rule kind afterward, gazelle\_rust will respect the existing rule kind. | ||
|
||
By default gazelle\_rust will generate one target per source file. You may change the grouping by | ||
adding a file to `srcs` for an existing target, and gazelle will respect that existing grouping. | ||
|
||
gazelle\_rust does not currently support sources in subdirectories, and will always place targets | ||
into build files adjacent to the sources that they correspond to. | ||
|
||
## Assigning dependencies | ||
|
||
gazelle\_rust parses each source file and identifies any path that looks like an external crate | ||
dependency. For example `some_lib::Foobar` implies a new dependency on `some_lib` unless `some_lib` | ||
is already in scope. | ||
|
||
This approach is fairly robust. Please see | ||
[`rust_parser/parser.rs`](https://github.com/Calsign/gazelle_rust/blob/main/rust_parser/parser.rs) | ||
for implementation details and the [parser | ||
tests](https://github.com/Calsign/gazelle_rust/tree/main/rust_parser/test_data) for the range of | ||
cases covered. The only known case that is not handled is paths in macros like `println!`, which is | ||
quite tricky. (Derive macros are handled properly.) | ||
|
||
For each dependency, gazelle\_rust identifies the crate in the project (or crate universe | ||
dependency) providing that crate name. gazelle\_rust raises an error if the crate could not be found | ||
or more than one crate with that name was found. | ||
|
||
This means there is a global namespace of crates within the project. If this poses an issue for you, | ||
you can use the gazelle [`resolve` | ||
directive](https://github.com/bazelbuild/bazel-gazelle#directives) to configure which target is | ||
selected on a per-directory basis. | ||
|
||
## Crate universe | ||
|
||
The example shows how to handle crate universe dependencies with gazelle\_rust. | ||
[`example/WORKSPACE`](https://github.com/Calsign/gazelle_rust/blob/main/example/WORKSPACE) shows how | ||
to load crate universe dependencies, please refer to the [rules\_rust | ||
documentation](http://bazelbuild.github.io/rules_rust/crate_universe.html) for more information. The | ||
example shows the repository rule approach, but gazelle\_rust also supports the vendored approach. | ||
|
||
[`example/BUILD.bazel`](https://github.com/Calsign/gazelle_rust/blob/main/example/BUILD.bazel) shows | ||
how to configure gazelle\_rust to resolve crate universe dependencies. | ||
|
||
Different configurations of crate universe use either a cargo lockfile (`Cargo.lock`) or a custom | ||
lockfile (`Cargo.Bazel.lock`), and gazelle\_rust supports both. Use the directive | ||
`gazelle:rust_cargo_lockfile` to indicate a cargo lockfile and `gazelle:rust_lockfile` to indicate a | ||
custom lockfile. These options are mutually exclusive. | ||
|
||
Additionally, you must tell rules\_rust the prefix for all crate universe labels using the | ||
`gazelle:rust_crates_prefix` directive, e.g. `@crates//:` for a repository rule approach or | ||
`//3rdparty/crates:` for a vendored approach. | ||
|
||
|
||
## Ignoring dependencies | ||
|
||
Some situations are too complex for gazelle\_rust to handle, such as platform-conditional | ||
dependencies. It is possible that fancy support could be added in the future, but for now you must | ||
handle this manually by ignoring the dependency in the source file and potentially adding [`# keep` | ||
comments](https://github.com/bazelbuild/bazel-gazelle#keep-comments) in the build file. | ||
|
||
To tell gazelle\_rust to ignore a dependency, you can add the `#[gazelle::ignore]` attribute macro | ||
to a use item. For example: | ||
|
||
```rust | ||
// the tokio runtime is not supported in wasm | ||
#[cfg(not(target_arch = "wasm32"))] | ||
#[gazelle::ignore] | ||
use tokio::runtime::Runtime; | ||
``` | ||
|
||
Then in the build file: | ||
|
||
```py | ||
rust_library( | ||
name = "maybe_tokio", | ||
deps = select({ | ||
"@platforms//cpu:wasm32": [], | ||
"//conditions:default": [ | ||
"//3rdparty/crates:tokio", | ||
], | ||
}), | ||
) | ||
|
||
rust_library( | ||
name = "some_cool_cross_platform_thing", | ||
deps = [ | ||
":maybe_tokio", # keep | ||
], | ||
... | ||
) | ||
``` | ||
|
||
See the [macro crate](https://github.com/Calsign/gazelle_rust/tree/main/macro) for more information | ||
about the ignore macro. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
This is an example showing how to use gazelle\_rust. There is more information in the [main | ||
README](https://github.com/Calsign/gazelle_rust/blob/main/README.md). |