Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR: Add tonic/prost rules #915

Closed
UebelAndre opened this issue Aug 28, 2021 · 15 comments · Fixed by #2033
Closed

FR: Add tonic/prost rules #915

UebelAndre opened this issue Aug 28, 2021 · 15 comments · Fixed by #2033

Comments

@UebelAndre
Copy link
Collaborator

This is a fairly common request. It would be nice if there were some tonic/prost rules in the @rules_rust//proto package since the existing rules there are using the protobuf-rs crate which only supports a (now) 3 year old version of protobuf (see stepancheg/rust-protobuf#518).

@UebelAndre
Copy link
Collaborator Author

Right now there are two drafts for adding these rules:

As of right now, they're both pretty dated and likely will not work with the current rev of the rules. Hopefully this effort is revived 😄

@UebelAndre
Copy link
Collaborator Author

Hopefully, for folks looking to use a modern version of protobuf for proto generation, tonic/prost rules can satisfy this need since the existing proto rules do not (#302 - blocked by stepancheg/rust-protobuf#518).

@shikhar
Copy link
Contributor

shikhar commented Aug 29, 2021

Even without tonic/prost rules, which would certainly make for less boilerplate, it's not too bad. https://github.com/shikhar/bazel-tonic is an example project I created that entirely uses rules_rust. codegen via https://github.com/shikhar/bazel-tonic/blob/main/src/protogen/BUILD

@GregBowyer
Copy link
Contributor

GregBowyer commented Sep 17, 2021

I think it might be better to not have these in rules_rust but rather in rules_proto_grpc.

I have rules that can live in there in the works.

@UebelAndre
Copy link
Collaborator Author

I'd welcome it! I think it'd be better to keep proto/grpc rules all together. Even if they're for different languages.

@UebelAndre
Copy link
Collaborator Author

I saw rules-proto-grpc/rules_proto_grpc#143 was recently opened. Seems like there's some interest in adding something like that to rules_proto_grpc.

@aaliddell
Copy link

Oh hi, I stubled across this from your cross-link 👋

I'm stuck at the moment with Tonic/Prost support in rules_proto_grpc since they don't have protoc plugins available and instead require you use their own generation method that itself wraps protoc. It seems there were previously plugins and could be again in the future if there's demand. Otherwise I may have to figure out a way to wrap their generation method in a pseudo-plugin just to satisfy protoc, similar to what was done in those links above.

@GregBowyer
Copy link
Contributor

GregBowyer commented Sep 24, 2021 via email

@UebelAndre
Copy link
Collaborator Author

@GregBowyer is tokio-rs/prost#492 (comment) meaningful info for you? If the changes there were to go in a separate crate, would it still be possible to use them to write prost/tonic rules?

@Sollimann
Copy link

I'm unable to use tonic_build with prost to generate stubs for my clients and serves when running my build.rs file. @shikhar https://github.com/shikhar/rules-rust-playground/tree/bazelify is this the solution to make it work? 🤔

@Sollimann
Copy link

Sollimann commented Jan 24, 2022

I have an alternative fix 💪 ✅ It's not optimal, but this is a blocking issue for me, so I needed some way past it. First you do like you always would with cargo build / cargo build --release in a regular rust/cargo project. Normally when you build.rs file executes, the files go to the /target folder. Now, this didn't seem to work for me when using Bazel. So I figured that instead of having Bazel build the gRPC stubs and proto's, I'd rather do that with cargo, but I generate the stubs inside my /src folder instead of /target -folder. It works for me atleast.

cargo/
proto/
------ myproto.proto
src/
----- rust/
----------- mod.rs
----------- myproto.rs
----- lib.rs
BUILD.bazel
Cargo.toml
build.rs

build.rs

use std::fs;
use std::path::Path;
const PROTO_OUT_DIR: &str = "./src/rust";

fn main() -> Result<(), Box<dyn std::error::Error>> {
    if Path::new(PROTO_OUT_DIR).is_dir() {
        fs::remove_dir_all(PROTO_OUT_DIR)?;
    }

    fs::create_dir(PROTO_OUT_DIR).expect("Failed to create out dir");
    fs::write(
        format!("{}/mod.rs", PROTO_OUT_DIR),
        "pub mod sensors_service;",
    )?;

    let files = vec!["proto/sensors_service.proto"];
    let includes = vec!["proto"];

    tonic_build::configure()
        .build_client(true)
        .build_server(true)
        .format(true)
        .out_dir(PROTO_OUT_DIR)
        .compile(&files, &includes)?;
    Ok(())
}

Cargo.toml

[package]
name = "protos"
version = "0.1.0"
authors = ["sollimann <[email protected]>"]
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tonic = { version = "0.4", features = ["prost"] }
prost = "0.7"
prost-types = "0.7"
serde = { version = "1.0", features = ["derive"] }


[build-dependencies]
tonic-build = "0.4"
prost-build = "0.7"

BUILD.bazel

load("@rules_rust//rust:defs.bzl", "rust_library")

package(default_visibility = ["//visibility:public"])

rust_library(
    name = "protos",
    srcs = glob(["**/*.rs"]),
    # crate_features = [
    #     "default",
    #     "std",
    # ],
    crate_root = "src/lib.rs",
    data = [],
    edition = "2021",
    rustc_flags = [
        "--cap-lints=allow",
    ],
    version = "0.1.0",
    visibility = [
        # had to add this line to be able to add /protos ass dep to grpc-connector-service
        "//services/grpc-connector-service:__subpackages__",
    ],
    deps = [
        "//protos/cargo:prost",
        "//protos/cargo:prost_build",
        "//protos/cargo:prost_types",
        "//protos/cargo:serde",
        "//protos/cargo:tonic",
        "//protos/cargo:tonic_build",
    ],
)

@UebelAndre
Copy link
Collaborator Author

UebelAndre commented Mar 26, 2022

tokio-rs/prost#492 (comment) seems like a relevant update to this thread

Rejoyce! I finally got time to port this, and I am happy to announce that I now have a protoc-gen-prost plugin that lives outside of this repository that is on par feature-wise with this PR! I'd even say that it is better: all options are supported, with a cleaner code, and better formatting than ever (it passes the generated code through prettyplease).

With the merge of #598 it will even not require any change to prost (although it still needs a git dep since it's unreleased yet). But as soon as this is released, the plugin can be pushed to crates.io. There are a few things that are left to do, mainly refacto a teeny bit to expose the internals as a lib, so that a future protoc-gen-tonic (my actual goal) can build on it. That'll be easy since I wrote the current code with this in mind.

Find it here: https://github.com/Tuetuopay/protoc-gen-prost

@Tuetuopay
Copy link

Popping in to let you know that I pushed protoc-gen-tonic, which can get handy.

@aidanalphafund
Copy link

Has anyone managed to get this to work with protoc-gen-tonic and/or protoc-gen-prost?

@titanous
Copy link
Contributor

I've implemented support for protoc-gen-tonic and protoc-gen-prost in rules-proto-grpc/rules_proto_grpc#202.

elliotmjackson pushed a commit to bufbuild/protoc-gen-validate that referenced this issue Sep 19, 2022
In order to include this in rust sources this needs to be included
directly downstream. Ideally we had a simple proto library target we
could use instead, but the rust ecosystem is a bit bifurcated.

bazelbuild/rules_rust#915

Signed-off-by: Keith Smiley <[email protected]>

Signed-off-by: Keith Smiley <[email protected]>
Co-authored-by: Elliot Jackson <[email protected]>
alexjpwalker added a commit to typedb/typedb-dependencies that referenced this issue Nov 21, 2022
## What is the goal of this PR?

We added the `rust_tonic_compile` rule which compiles `.proto` files
into Rust sources that depend on the `tonic` and `prost` crates.

## What are the changes implemented in this PR?

We had an existing Rust binary for compiling proto files into a Tonic
library - a Cargo build script in `typedb-protocol`. But Cargo users
shouldn't have to run `protoc` on their machine to compile
`typedb-client` (which is what happens with a Cargo build script).
Rather, the `typedb-protocol` crate should contain the generated Rust
gRPC + Protobuf sources.

So we've created a rule, `rust_tonic_compile`, that internally runs a
`rust_binary` (similarly to how many of our rules run Kotlin binaries),
which uses `tonic_build` to compile `.proto` files into Rust sources,
and exposes the outputs. Any `rust_library` can then depend on these
generated sources. The API is similar to Java and Python
(`java_grpc_compile` and `python_grpc_compile` respectively), and the
`antlr` rule from `rules_antlr` behaves similarly, too.

Ideally, we wouldn't need our own rule to do this, however, the Bazel
rules repos that contain Rust gRPC + Protobuf rules only support the
`grpc` crate, and not the more popular `tonic` crate. Moreover, all of
them already have open PRs for adding such functionality:

- rules-proto-grpc/rules_proto_grpc#143
- stackb/rules_proto#201
- bazelbuild/rules_rust#915

Given that our implementation is **very minimal** (~30 lines of code) it
should incur a very low maintenance effort.
jamesreprise pushed a commit to jamesreprise/vaticle-dependencies that referenced this issue Dec 5, 2022
## What is the goal of this PR?

We added the `rust_tonic_compile` rule which compiles `.proto` files
into Rust sources that depend on the `tonic` and `prost` crates.

## What are the changes implemented in this PR?

We had an existing Rust binary for compiling proto files into a Tonic
library - a Cargo build script in `typedb-protocol`. But Cargo users
shouldn't have to run `protoc` on their machine to compile
`typedb-client` (which is what happens with a Cargo build script).
Rather, the `typedb-protocol` crate should contain the generated Rust
gRPC + Protobuf sources.

So we've created a rule, `rust_tonic_compile`, that internally runs a
`rust_binary` (similarly to how many of our rules run Kotlin binaries),
which uses `tonic_build` to compile `.proto` files into Rust sources,
and exposes the outputs. Any `rust_library` can then depend on these
generated sources. The API is similar to Java and Python
(`java_grpc_compile` and `python_grpc_compile` respectively), and the
`antlr` rule from `rules_antlr` behaves similarly, too.

Ideally, we wouldn't need our own rule to do this, however, the Bazel
rules repos that contain Rust gRPC + Protobuf rules only support the
`grpc` crate, and not the more popular `tonic` crate. Moreover, all of
them already have open PRs for adding such functionality:

- rules-proto-grpc/rules_proto_grpc#143
- stackb/rules_proto#201
- bazelbuild/rules_rust#915

Given that our implementation is **very minimal** (~30 lines of code) it
should incur a very low maintenance effort.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants