Skip to content

Compiling Protos with tonic-prost-build

.proto files are not read at runtime: they are compiled at build time and generate the Rust code for the service, the message types, and optionally a descriptor for reflection.

build.rs

Any project using gRPC controllers needs a build.rs file that compiles the .proto files with tonic_prost_build. In Sword, it also generates sword_descriptor_set.bin in OUT_DIR to enable reflection.

rust
// build.rs
use std::{env, path::PathBuf};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let out_dir = PathBuf::from(env::var("OUT_DIR")?);
    let descriptor_path = out_dir.join("sword_descriptor_set.bin");

    tonic_prost_build::configure()
        .file_descriptor_set_path(&descriptor_path)
        .compile_protos(&["config/proto/users.proto"], &["config/proto"])?;

    Ok(())
}

Breakdown of the configuration:

  • .file_descriptor_set_path(...): writes the descriptor to OUT_DIR/sword_descriptor_set.bin. This is what lets Sword register reflection automatically.
  • .compile_protos(&["config/proto/users.proto"], &["config/proto"]): compiles the contract and its imports, using config/proto as the resolution root.

Sword registers the descriptor automatically

You do not need to register reflection manually in your modules. Just by generating sword_descriptor_set.bin in OUT_DIR, Sword detects it and exposes it.

Without OUT_DIR there is no reflection

If you omit .file_descriptor_set_path(...), the code still compiles, but there will be no descriptor available, and grpcurl will not be able to list/describe services with reflection.

Dependencies

In your Cargo.toml you need tonic-prost-build as a build dependency, plus prost and tonic-prost at runtime:

toml
[dependencies]
sword = { version = "x.y.z", features = ["grpc", "grpc-reflection"] }
tonic = "x.y.z"
prost = "x.y.z"
tonic-prost = "x.y.z"

[build-dependencies]
tonic-prost-build = "x.y.z"

Why prost and tonic-prost at runtime too?

The code generated by the compilation depends on prost (serialization) and tonic-prost (codec) in the final project. sword cannot re-export them in your place.