From a4923812aa2a16b3eb854ec69c75081a15026c4e Mon Sep 17 00:00:00 2001 From: Will Smith Date: Sat, 12 Aug 2023 13:27:37 -0700 Subject: [PATCH] add documentation to readme --- README.md | 164 +++++++++++++++++++++++++++++++++++++++++++++- example/README.md | 2 + 2 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 example/README.md diff --git a/README.md b/README.md index 3c6bfa5..1509041 100644 --- a/README.md +++ b/README.md @@ -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 = "" +GAZELLE_RUST_SHA256 = "" + +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. diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..2886685 --- /dev/null +++ b/example/README.md @@ -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).