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