Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 1 | #[[ |
| 2 | ## Overview |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 3 | These build rules are used for building [protobufs][protobuf]/[gRPC][grpc] in [Rust][rust] with Bazel. |
| 4 | |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 5 | There are two rule sets. The first ruleset defines the `rust_proto_library` and `rust_grpc_library` |
| 6 | rules which generate Rust code using the [`rust-protobuf`] dependencies. The second ruleset defines |
| 7 | the `rust_prost_library` which generates Rust code using the [`prost`] and [`tonic`] dependencies. |
| 8 | |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 9 | [rust]: http://www.rust-lang.org/ |
| 10 | [protobuf]: https://developers.google.com/protocol-buffers/ |
| 11 | [grpc]: https://grpc.io |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 12 | [`rust-protobuf`]: https://github.com/stepancheg/rust-protobuf/ |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 13 | |
| 14 | See the [protobuf example](../examples/proto) for a more complete example of use. |
| 15 | |
| 16 | ### Setup |
| 17 | |
| 18 | To use the Rust proto rules, add the following to your `WORKSPACE` file to add the |
| 19 | external repositories for the Rust proto toolchain (in addition to the [rust rules setup](..)): |
| 20 | |
| 21 | ```python |
| 22 | load("@rules_rust//proto:repositories.bzl", "rust_proto_repositories") |
| 23 | |
| 24 | rust_proto_repositories() |
| 25 | |
| 26 | load("@rules_rust//proto:transitive_repositories.bzl", "rust_proto_transitive_repositories") |
| 27 | |
| 28 | rust_proto_transitive_repositories() |
| 29 | ``` |
| 30 | |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 31 | This will load the required dependencies for the Proto, Prost, and Tonic rules. It will also |
| 32 | register a default toolchain for the `rust_proto_library` and `rust_grpc_library` rules. The |
| 33 | `prost` and `tonic` rules do not specify a default toolchain in order to avoid mismatched |
| 34 | dependency issues. |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 35 | |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 36 | To customize the `rust_proto_library` and `rust_grpc_library` toolchain, please see the section |
| 37 | [Customizing `rust-protobuf` Dependencies](#custom-proto-deps). |
| 38 | |
| 39 | To setup the `prost` and `tonic` toolchain, please see the section [Customizing `prost` and `tonic` Dependencies](#custom-prost-deps). |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 40 | |
| 41 | For additional information about Bazel toolchains, see [here](https://docs.bazel.build/versions/master/toolchains.html). |
| 42 | |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 43 | ## <a name="custom-proto-deps">Customizing `rust-protobuf` Dependencies |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 44 | |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 45 | These rules depend on the [`protobuf`](https://crates.io/crates/protobuf) and |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 46 | the [`grpc`](https://crates.io/crates/grpc) crates in addition to the [protobuf |
| 47 | compiler](https://github.com/google/protobuf). To obtain these crates, |
| 48 | `rust_proto_repositories` imports the given crates using BUILD files generated with |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 49 | [crate_universe](./crate_universe.md). |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 50 | |
| 51 | If you want to either change the protobuf and gRPC rust compilers, or to |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 52 | simply use [crate_universe](./crate_universe.md) in a more |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 53 | complex scenario (with more dependencies), you must redefine those |
| 54 | dependencies. |
| 55 | |
| 56 | To do this, once you've imported the needed dependencies (see our |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 57 | [@rules_rust//proto/3rdparty/BUILD.bazel](https://github.com/bazelbuild/rules_rust/blob/main/proto/3rdparty/BUILD.bazel) |
| 58 | file to see the default dependencies), you need to create your own toolchain. |
| 59 | To do so you can create a BUILD file with your toolchain definition, for example: |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 60 | |
| 61 | ```python |
| 62 | load("@rules_rust//proto:toolchain.bzl", "rust_proto_toolchain") |
| 63 | |
| 64 | rust_proto_toolchain( |
| 65 | name = "proto-toolchain-impl", |
| 66 | # Path to the protobuf compiler. |
| 67 | protoc = "@com_google_protobuf//:protoc", |
| 68 | # Protobuf compiler plugin to generate rust gRPC stubs. |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 69 | grpc_plugin = "//3rdparty/crates:cargo_bin_protoc_gen_rust_grpc", |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 70 | # Protobuf compiler plugin to generate rust protobuf stubs. |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 71 | proto_plugin = "//3rdparty/crates:cargo_bin_protoc_gen_rust", |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 72 | ) |
| 73 | |
| 74 | toolchain( |
| 75 | name = "proto-toolchain", |
| 76 | toolchain = ":proto-toolchain-impl", |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 77 | toolchain_type = "@rules_rust//proto/protobuf:toolchain_type", |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 78 | ) |
| 79 | ``` |
| 80 | |
| 81 | Now that you have your own toolchain, you need to register it by |
| 82 | inserting the following statement in your `WORKSPACE` file: |
| 83 | |
| 84 | ```python |
| 85 | register_toolchains("//my/toolchains:proto-toolchain") |
| 86 | ``` |
| 87 | |
| 88 | Finally, you might want to set the `rust_deps` attribute in |
| 89 | `rust_proto_library` and `rust_grpc_library` to change the compile-time |
| 90 | dependencies: |
| 91 | |
| 92 | ```python |
| 93 | rust_proto_library( |
| 94 | ... |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 95 | rust_deps = ["//3rdparty/crates:protobuf"], |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 96 | ... |
| 97 | ) |
| 98 | |
| 99 | rust_grpc_library( |
| 100 | ... |
| 101 | rust_deps = [ |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 102 | "//3rdparty/crates:protobuf", |
| 103 | "//3rdparty/crates:grpc", |
| 104 | "//3rdparty/crates:tls_api", |
| 105 | "//3rdparty/crates:tls_api_stub", |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 106 | ], |
| 107 | ... |
| 108 | ) |
| 109 | ``` |
| 110 | |
| 111 | __Note__: Ideally, we would inject those dependencies from the toolchain, |
| 112 | but due to [bazelbuild/bazel#6889](https://github.com/bazelbuild/bazel/issues/6889) |
| 113 | all dependencies added via the toolchain ends-up being in the wrong |
| 114 | configuration. |
Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 115 | |
| 116 | ## <a name="custom-prost-deps">Customizing `prost` and `tonic` Dependencies |
| 117 | |
| 118 | These rules depend on the [`prost`] and [`tonic`] dependencies. To setup the necessary toolchain |
| 119 | for these rules, you must define a toolchain with the [`prost`], [`prost-types`], [`tonic`],[`protoc-gen-prost`], and [`protoc-gen-tonic`] crates as well as the [`protoc`] binary. |
| 120 | |
| 121 | [`prost`]: https://crates.io/crates/prost |
| 122 | [`prost-types`]: https://crates.io/crates/prost-types |
| 123 | [`protoc-gen-prost`]: https://crates.io/crates/protoc-gen-prost |
| 124 | [`protoc-gen-tonic`]: https://crates.io/crates/protoc-gen-tonic |
| 125 | [`tonic`]: https://crates.io/crates/tonic |
| 126 | [`protoc`]: https://github.com/protocolbuffers/protobuf |
| 127 | |
| 128 | To get access to these crates, you can use the [crate_universe](./crate_universe.md) repository |
| 129 | rules. For example: |
| 130 | |
| 131 | ```python |
| 132 | load("//crate_universe:defs.bzl", "crate", "crates_repository") |
| 133 | |
| 134 | crates_repository( |
| 135 | name = "crates_io", |
| 136 | annotations = { |
| 137 | "protoc-gen-prost": [crate.annotation( |
| 138 | gen_binaries = ["protoc-gen-prost"], |
| 139 | patch_args = [ |
| 140 | "-p1", |
| 141 | ], |
| 142 | patches = [ |
| 143 | # Note: You will need to use this patch until a version greater than `0.2.2` of |
| 144 | # `protoc-gen-prost` is released. |
| 145 | "@rules_rust//proto/prost/private/3rdparty/patches:protoc-gen-prost.patch", |
| 146 | ], |
| 147 | )], |
| 148 | "protoc-gen-tonic": [crate.annotation( |
| 149 | gen_binaries = ["protoc-gen-tonic"], |
| 150 | )], |
| 151 | }, |
| 152 | cargo_lockfile = "Cargo.Bazel.lock", |
| 153 | mode = "remote", |
| 154 | packages = { |
| 155 | "prost": crate.spec( |
| 156 | version = "0", |
| 157 | ), |
| 158 | "prost-types": crate.spec( |
| 159 | version = "0", |
| 160 | ), |
| 161 | "protoc-gen-prost": crate.spec( |
| 162 | version = "0", |
| 163 | ), |
| 164 | "protoc-gen-tonic": crate.spec( |
| 165 | version = "0", |
| 166 | ), |
| 167 | "tonic": crate.spec( |
| 168 | version = "0", |
| 169 | ), |
| 170 | }, |
| 171 | repository_name = "rules_rust_prost", |
| 172 | tags = ["manual"], |
| 173 | ) |
| 174 | ``` |
| 175 | |
| 176 | You can then define a toolchain with the `rust_prost_toolchain` rule which uses the crates |
| 177 | defined above. For example: |
| 178 | |
| 179 | ```python |
| 180 | load("@rules_rust//proto/prost:defs.bzl", "rust_prost_toolchain") |
| 181 | load("@rules_rust//rust:defs.bzl", "rust_library_group") |
| 182 | |
| 183 | rust_library_group( |
| 184 | name = "prost_runtime", |
| 185 | deps = [ |
| 186 | "@crates_io//:prost", |
| 187 | ], |
| 188 | ) |
| 189 | |
| 190 | rust_library_group( |
| 191 | name = "tonic_runtime", |
| 192 | deps = [ |
| 193 | ":prost_runtime", |
| 194 | "@crates_io//:tonic", |
| 195 | ], |
| 196 | ) |
| 197 | |
| 198 | rust_prost_toolchain( |
| 199 | name = "prost_toolchain_impl", |
| 200 | prost_plugin = "@crates_io//:protoc-gen-prost__protoc-gen-prost", |
| 201 | prost_runtime = ":prost_runtime", |
| 202 | prost_types = "@crates_io//:prost-types", |
| 203 | proto_compiler = "@com_google_protobuf//:protoc", |
| 204 | tonic_plugin = "@crates_io//:protoc-gen-tonic__protoc-gen-tonic", |
| 205 | tonic_runtime = ":tonic_runtime", |
| 206 | ) |
| 207 | |
| 208 | toolchain( |
| 209 | name = "prost_toolchain", |
| 210 | toolchain = "default_prost_toolchain_impl", |
| 211 | toolchain_type = "//proto/prost:toolchain_type", |
| 212 | ) |
| 213 | ``` |
| 214 | |
| 215 | Lastly, you must register the toolchain in your `WORKSPACE` file. For example: |
| 216 | |
| 217 | ```python |
| 218 | register_toolchains("//toolchains:prost_toolchain") |
| 219 | ``` |
Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame] | 220 | ]]# |