Skip to content

Commit 8d2003a

Browse files
authored
Add Rust Getting Started Codelab
Add Getting Started Rust Codelab @easwars @dfawley
1 parent 4dd4aa6 commit 8d2003a

26 files changed

+6238
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Generate Code from Proto Files
2+
3+
This is a tutorial for generating code from Proto files using gRPC-Rust. This tutorial will utilize the RouteGuide example.
4+
5+
### Prerequisites
6+
7+
* [**Tonic**](https://github.com/hyperium/tonic.git), the open source repository that gRPC-Rust is build off on
8+
```sh
9+
$ git clone https://github.com/hyperium/tonic.git
10+
```
11+
* [**Rust**](https://www.rust-lang.org/).
12+
* Follow installation instructions [here](https://www.rust-lang.org/tools/install).
13+
* [**Bazel 8.3.1**](https://bazel.build/).
14+
* Follow installation instructions [here](https://github.com/bazelbuild/bazel/releases).
15+
* [**Protocol buffer**](https://developers.google.com/protocol-buffers) **compiler**, `protoc`, [version 3](https://protobuf.dev/programming-guides/proto3).
16+
* For installation instructions, see [Protocol Buffer Compiler Installation](https://grpc.io/docs/protoc-installation/).
17+
* NOTE: Must need a version of Protoc 3.31.1 or higher.
18+
* **Rust plugins** for the protocol compiler:
19+
```sh
20+
$ cd tonic/protoc-gen-rust-grpc
21+
$ bazel build //src:protoc-gen-rust-grpc
22+
$ PLUGIN_PATH="$(pwd)/bazel-bin/src/protoc-gen-rust-grpc"
23+
```
24+
25+
* Update your PATH so that the protoc compiler can find the plugins:
26+
27+
```sh
28+
export PATH="$(pwd)/bazel-bin/src/:$PATH"
29+
```
30+
31+
## Generating client and server code
32+
33+
Next we need to generate the gRPC client and server interfaces from our `.proto`
34+
service definition.
35+
36+
### Dependencies
37+
Edit `Cargo.toml` and add the dependency we'll need for this example, which is tonic-protobuf-build:
38+
39+
```console
40+
cargo add tonic-protobuf-build
41+
```
42+
43+
### Compiling and Building Proto
44+
Create a `build.rs` file at the root of your crate. A build.rs script is a Rust program that Cargo executes before compiling your main project. Its purpose is to perform tasks like generating source code, linking to non-Rust libraries, or setting environment variables that influence the build process.
45+
46+
In this case, we will be putting the command to compile and build the `.proto` file in build.rs. We will use gRPC's tonic_protobuf_build crate to generate code from the `.proto` file.
47+
```rust
48+
fn main() {
49+
tonic_protobuf_build::CodeGen::new()
50+
.include("proto")
51+
.inputs(["routeguide.proto"])
52+
.output_dir("generated")
53+
.compile()
54+
.unwrap();
55+
}
56+
```
57+
Now, run
58+
```shell
59+
$ cargo build
60+
```
61+
62+
That's it. The generated code contains:
63+
64+
- Struct definitions for message types `Point` and `Feature`.
65+
- A service trait we'll need to implement: `route_guide_server::RouteGuide`.
66+
- A client type we'll use to call the server: `route_guide_client::RouteGuideClient<T>`.
67+
68+
If your are curious as to where the generated files are, keep reading. The mystery will be revealed
69+
soon! We can now move on to the fun part.
70+
71+
## Bringing Generated Code into Scope
72+
73+
The generated code is placed inside our target directory, in a location defined by the `OUT_DIR`
74+
environment variable that is set by cargo. For our example, this means you can find the generated
75+
code in a path similar to `target/debug/build/routeguide/out/routeguide.rs`.
76+
77+
We can use gRPC's `include_proto` macro to bring the generated code into scope:
78+
79+
```rust
80+
pub mod routeguide {
81+
tonic::include_proto!("routeguide");
82+
}
83+
```
84+
85+
**Note**: The token passed to the `include_proto` macro (in our case "routeguide") is the name of
86+
the package declared in our `.proto` file, not a filename, e.g "routeguide.rs".
87+
88+
With this in place, we can stub out our service implementation:
89+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
[package]
2+
edition = "2021"
3+
license = "MIT"
4+
name = "getting-started"
5+
6+
[[bin]]
7+
name = "routeguide-server"
8+
path = "src/server/server.rs"
9+
10+
[[bin]]
11+
name = "routeguide-client"
12+
path = "src/client/client.rs"
13+
14+
[features]
15+
routeguide = ["dep:async-stream", "dep:tokio-stream", "dep:rand", "dep:serde", "dep:serde_json"]
16+
full = ["routeguide"]
17+
default = ["full"]
18+
19+
[dependencies]
20+
# Common dependencies
21+
tokio = { version = "1.0", features = ["rt-multi-thread", "macros"] }
22+
prost = "0.14"
23+
tonic = { git = "https://github.com/hyperium/tonic", branch="master"}
24+
tonic-protobuf = {git = "https://github.com/hyperium/tonic", branch="master", package = "tonic-protobuf" }
25+
grpc = {git = "https://github.com/hyperium/tonic", branch="master", package = "grpc"}
26+
# Optional dependencies
27+
async-stream = { version = "0.3", optional = true }
28+
tokio-stream = { version = "0.1", optional = true }
29+
tokio-util = { version = "0.7.8", optional = true }
30+
tower = { version = "0.5", optional = true }
31+
rand = { version = "0.9", optional = true }
32+
serde = { version = "1.0", features = ["derive"], optional = true }
33+
serde_json = { version = "1.0", optional = true }
34+
prost-types = { version = "0.14", optional = true }
35+
http = { version = "1", optional = true }
36+
hyper = { version = "1", optional = true }
37+
hyper-util = { version = "0.1.4", optional = true }
38+
tokio-rustls = { version = "0.26.1", optional = true, features = ["ring", "tls12"], default-features = false }
39+
hyper-rustls = { version = "0.27.0", features = ["http2", "ring", "tls12"], optional = true, default-features = false }
40+
tower-http = { version = "0.6", optional = true }
41+
protobuf = { version = "4.31.1-release"}
42+
43+
[build-dependencies]
44+
protobuf-codegen = { version = "4.31.1-release"}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn main() {
2+
protobuf_codegen::CodeGen::new()
3+
.include("proto")
4+
.inputs(["routeguide.proto"])
5+
.output_dir("generated")
6+
.compile_only()
7+
.unwrap();
8+
}

codelabs/grpc-rust-getting-started/completed/generated/crate_mapping.txt

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#[path = "routeguide.u.pb.rs"]
2+
#[allow(nonstandard_style)]
3+
pub mod internal_do_not_use_routeguide;
4+
#[allow(unused_imports, nonstandard_style)]
5+
pub use internal_do_not_use_routeguide::*;

0 commit comments

Comments
 (0)