Name Date Size #Lines LOC

..--

build/prost_toolchain/H25-Apr-2025-3328

grpc_client/H25-Apr-2025-9276

grpc_server/H25-Apr-2025-213157

proto_bindings/H25-Apr-2025-9575

.bazelrcH A D25-Apr-2025242 86

.bazelversionH A D25-Apr-20255 11

.gitignoreH A D25-Apr-202596 55

BUILD.bazelH A D25-Apr-202597 76

Cargo.tomlH A D25-Apr-20251.2 KiB4333

MODULE.bazelH A D25-Apr-20253.5 KiB134114

README.mdH A D25-Apr-20256.4 KiB222176

README.md

1# gRPC Client & Server
2
3This example shows how to build a gRPC server and client in Rust with Bazel.
4There is a Cargo Workspace configuration and a Bazelmod configuration. Furthermore,
5all binary targets apply optimization from the [compiler optimization example](../03-comp-opt).
6
7To run the example with Cargo, open one terminal and start the server with:
8
9`
10cargo run --bin grpc_server
11`
12
13And, in a second terminal, to run the client:
14
15`
16cargo run --bin grpc_client
17`
18
19The equivalent Bazel targets are:
20
21Server:
22
23`bazel run //grpc_server:bin`
24
25Client:
26
27`bazel run //grpc_client:bin`
28
29## Setup
30
31The Prost and Tonic rules do not specify a default toolchain in order to avoid mismatched dependency issues.
32While the Tonic toolchain works out of the box when its dependencies are matched, however,
33Prost requires a custom toolchain that you have to define.
34
35The setup requires three steps to complete:
361. Configure rules and dependencies in MODULE.bazel
372. Configure a custom Prost toolchain
383. Register custom Prost toolchain.
39
40To keep the build hermetic, we use the LLVM Clang compiler to compile all C/C++ dependencies.
41
42### 1) Configure rules and dependencies
43
44In your MODULE.bazel, you add the following:
45
46```starlark
47# rules for proto
48###############################################################################
49# https://github.com/bazelbuild/rules_proto/releases
50bazel_dep(name = "rules_proto", version = "6.0.2")
51# https://github.com/aspect-build/toolchains_protoc/releases
52bazel_dep(name = "toolchains_protoc", version = "0.3.1")
53# https://registry.bazel.build/modules/protobuf
54bazel_dep(name = "protobuf", version = "27.1")
55# rules for LLVM
56# https://github.com/bazel-contrib/toolchains_llvm
57bazel_dep(name = "toolchains_llvm", version = "1.0.0")
58
59# 1 Register LLVM
60###############################################################################
61# L L V M
62# https://github.com/bazel-contrib/toolchains_llvm/blob/master/tests/MODULE.bazel
63###############################################################################
64llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm")
65LLVM_VERSIONS = { "": "16.0.0",}
66
67# LLVM toolchain.
68llvm.toolchain(
69    name = "llvm_toolchain",
70    llvm_versions = LLVM_VERSIONS,
71)
72use_repo(llvm, "llvm_toolchain", "llvm_toolchain_llvm")
73register_toolchains("@llvm_toolchain//:all")
74
75# 2 Register Proto toolchain
76###############################################################################
77# Proto toolchain
78register_toolchains("@rules_rust//proto/protobuf:default-proto-toolchain")
79
80# Custom Prost toolchain will be added later. See next section
81
82# 3 Register proto / prost / tonic crates
83###############################################################################
84crate = use_extension("@rules_rust//crate_universe:extension.bzl", "crate")
85
86# protobufs / gRPC
87crate.spec(
88    package = "prost",
89    version = "0.12",
90)
91crate.spec(
92    default_features = False,
93    package = "prost-types",
94    version = "0.12",
95)
96crate.spec(
97    features = ["transport"],
98    package = "tonic",
99    version = "0.11",
100)
101crate.spec(
102    package = "tonic-build",
103    version = "0.11",
104)
105crate.spec(
106    package = "protoc-gen-prost",
107    version = "0.3.1",
108)
109crate.annotation(
110    crate = "protoc-gen-prost",
111    gen_binaries = ["protoc-gen-prost"],
112)
113crate.spec(
114    package = "protoc-gen-tonic",
115    version = "0.4.0",
116)
117crate.annotation(
118    crate = "protoc-gen-tonic",
119    gen_binaries = ["protoc-gen-tonic"],
120)
121
122# Other Rust dependencies ...
123
124crate.from_specs()
125use_repo(crate, "crates")
126```
127
128### 2) Configure a custom Prost toolchain
129
130Configuring a custom Prost toolchain is straightforward, you create a new folder with an empty BUILD.bazl file, and add
131the toolchain definition.
132As your Bazel setup grows over time, it is a best practice to put all custom macros, rules, and toolchains in a
133dedicated folder, for example: `build/`.
134
135Suppose you have your BUILD.bazl file in `build/prost_toolchain/BUILD.bazel`, then add the following content:
136
137```starlark
138load("@rules_rust//proto/prost:defs.bzl", "rust_prost_toolchain")
139load("@rules_rust//rust:defs.bzl", "rust_library_group")
140
141rust_library_group(
142    name = "prost_runtime",
143    deps = [
144        "@crates//:prost",
145    ],
146)
147
148rust_library_group(
149    name = "tonic_runtime",
150    deps = [
151        ":prost_runtime",
152        "@crates//:tonic",
153    ],
154)
155
156rust_prost_toolchain(
157    name = "prost_toolchain_impl",
158    prost_plugin = "@crates//:protoc-gen-prost__protoc-gen-prost",
159    prost_runtime = ":prost_runtime",
160    prost_types = "@crates//:prost-types",
161    proto_compiler = "@protobuf//:protoc",
162    tonic_plugin = "@crates//:protoc-gen-tonic__protoc-gen-tonic",
163    tonic_runtime = ":tonic_runtime",
164)
165
166toolchain(
167    name = "prost_toolchain",
168    toolchain = "prost_toolchain_impl",
169    toolchain_type = "@rules_rust//proto/prost:toolchain_type",
170)
171```
172
173The Prost and Tonic dependencies are pulled from the previously configured
174crate dependencies in the MODULE file. With this custom toolchain in place, the last step is to register it.
175
176### 3. Register custom Prost toolchain.
177
178In your MODULE.bazel file, locate your toolchains and add the following entry right below the proto toolchain.
179
180```starlark
181# 2 Register Proto toolchain
182###############################################################################
183# Proto toolchain
184register_toolchains("@rules_rust//proto/protobuf:default-proto-toolchain")
185
186# Custom Prost toolchain
187register_toolchains("@//build/prost_toolchain")
188```
189
190Pay attention to the path, `build/prost_toolchain` because if your toolchain
191is in a different folder, you have to update this path to make the build work.
192
193## Usage
194
195Once the setup has been completed, you use the proto & prost targets as you normally do. For example, to configure rust
196bindings for a proto file, just add the target:
197
198```starlark
199load("@rules_proto//proto:defs.bzl", "proto_library")
200load("@rules_rust//proto/prost:defs.bzl", "rust_prost_library")
201
202# Build proto files
203# https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_proto_library
204proto_library(
205    name = "proto_bindings",
206    srcs = [
207          "proto/helloworld.proto",
208    ],
209)
210
211# Generate Rust bindings from the generated proto files
212# https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_prost_library
213rust_prost_library(
214    name = "rust_proto",
215    proto = ":proto_bindings",
216    visibility = ["//visibility:public"],
217)
218```
219
220From there, you
221just [follow the target documentation](https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_proto_library).
222