blob: cc41c4ec8038968762f34d93770968aef4c66ed8 [file] [view]
# gRPC Client & Server
This example shows how to build a gRPC server and client in Rust with Bazel.
There is a Cargo Workspace configuration and a Bazelmod configuration. Furthermore,
all binary targets apply optimization from the [compiler optimization example](../03-comp-opt).
To run the example with Cargo, open one terminal and start the server with:
`
cargo run --bin grpc_server
`
And, in a second terminal, to run the client:
`
cargo run --bin grpc_client
`
The equivalent Bazel targets are:
Server:
`bazel run //grpc_server:bin`
Client:
`bazel run //grpc_client:bin`
## Setup
The Prost and Tonic rules do not specify a default toolchain in order to avoid mismatched dependency issues.
While the Tonic toolchain works out of the box when its dependencies are matched, however,
Prost requires a custom toolchain that you have to define.
The setup requires three steps to complete:
1. Configure rules and dependencies in MODULE.bazel
2. Configure a custom Prost toolchain
3. Register custom Prost toolchain.
To keep the build hermetic, we use the LLVM Clang compiler to compile all C/C++ dependencies.
### 1) Configure rules and dependencies
In your MODULE.bazel, you add the following:
```starlark
# rules for proto
###############################################################################
# https://github.com/bazelbuild/rules_proto/releases
bazel_dep(name = "rules_proto", version = "7.1.0")
# https://registry.bazel.build/modules/protobuf
bazel_dep(name = "protobuf", version = "29.0", repo_name = "com_google_protobuf")
# rules for LLVM
# https://github.com/bazel-contrib/toolchains_llvm
bazel_dep(name = "toolchains_llvm", version = "1.2.0")
# 1 Register LLVM
###############################################################################
# L L V M
# https://github.com/bazel-contrib/toolchains_llvm/blob/master/tests/MODULE.bazel
###############################################################################
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm")
LLVM_VERSIONS = { "": "16.0.0",}
# LLVM toolchain.
llvm.toolchain(
name = "llvm_toolchain",
llvm_versions = LLVM_VERSIONS,
)
use_repo(llvm, "llvm_toolchain", "llvm_toolchain_llvm")
register_toolchains("@llvm_toolchain//:all")
# 2 Register Proto toolchain
###############################################################################
# Proto toolchain
register_toolchains("@rules_rust_prost//:default_prost_toolchain")
# Custom Prost toolchain will be added later. See next section
# 3 Register proto / prost / tonic crates
###############################################################################
crate = use_extension("@rules_rust//crate_universe:extensions.bzl", "crate")
# protobufs / gRPC
crate.spec(
package = "prost",
version = "0.12",
)
crate.spec(
default_features = False,
package = "prost-types",
version = "0.12",
)
crate.spec(
features = ["transport"],
package = "tonic",
version = "0.11",
)
crate.spec(
package = "tonic-build",
version = "0.11",
)
crate.spec(
package = "protoc-gen-prost",
version = "0.3.1",
)
crate.annotation(
crate = "protoc-gen-prost",
gen_binaries = ["protoc-gen-prost"],
)
crate.spec(
package = "protoc-gen-tonic",
version = "0.4.0",
)
crate.annotation(
crate = "protoc-gen-tonic",
gen_binaries = ["protoc-gen-tonic"],
)
# Other Rust dependencies ...
crate.from_specs()
use_repo(crate, "crates")
```
### 2) Configure a custom Prost toolchain
Configuring a custom Prost toolchain is straightforward, you create a new folder with an empty BUILD.bazl file, and add
the toolchain definition.
As your Bazel setup grows over time, it is a best practice to put all custom macros, rules, and toolchains in a
dedicated folder, for example: `build/`.
Suppose you have your BUILD.bazl file in `build/prost_toolchain/BUILD.bazel`, then add the following content:
```starlark
load("@rules_rust_prost//:defs.bzl", "rust_prost_toolchain")
load("@rules_rust//rust:defs.bzl", "rust_library_group")
rust_library_group(
name = "prost_runtime",
deps = [
"@crates//:prost",
],
)
rust_library_group(
name = "tonic_runtime",
deps = [
":prost_runtime",
"@crates//:tonic",
],
)
rust_prost_toolchain(
name = "prost_toolchain_impl",
prost_plugin = "@crates//:protoc-gen-prost__protoc-gen-prost",
prost_runtime = ":prost_runtime",
prost_types = "@crates//:prost-types",
proto_compiler = "@protobuf//:protoc",
tonic_plugin = "@crates//:protoc-gen-tonic__protoc-gen-tonic",
tonic_runtime = ":tonic_runtime",
)
toolchain(
name = "prost_toolchain",
toolchain = "prost_toolchain_impl",
toolchain_type = "@rules_rust_prost//:toolchain_type",
)
```
The Prost and Tonic dependencies are pulled from the previously configured
crate dependencies in the MODULE file. With this custom toolchain in place, the last step is to register it.
### 3. Register custom Prost toolchain.
In your MODULE.bazel file, locate your toolchains and add the following entry right below the proto toolchain.
```starlark
# 2 Register Proto toolchain
###############################################################################
# Proto toolchain
register_toolchains("@rules_rust_prost//:default_prost_toolchain")
# Custom Prost toolchain
register_toolchains("@//build/prost_toolchain")
```
Pay attention to the path, `build/prost_toolchain` because if your toolchain
is in a different folder, you have to update this path to make the build work.
## Usage
Once the setup has been completed, you use the proto & prost targets as you normally do. For example, to configure rust
bindings for a proto file, just add the target:
```starlark
load("@rules_proto//proto:defs.bzl", "proto_library")
load("@rules_rust_prost//:defs.bzl", "rust_prost_library")
# Build proto files
# https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_proto_library
proto_library(
name = "proto_bindings",
srcs = [
"proto/helloworld.proto",
],
)
# Generate Rust bindings from the generated proto files
# https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_prost_library
rust_prost_library(
name = "rust_proto",
proto = ":proto_bindings",
visibility = ["//visibility:public"],
)
```
From there, you
just [follow the target documentation](https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_proto_library).