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