mirror of https://github.com/bazelbuild/rules_rust
Support incompatible enable proto toolchain resolution (#2741)
This allows using a shared (generally pre-built) protoc definition, rather than needing to supply one via a label. We allow (but deprecate) users to still bring along their own protoc as a label, but if they want to do so, they will need to ensure they have the correct repositories registered in order to build/bring their protoc, rather than us setting them up by default.
This commit is contained in:
parent
ca7a3df6d2
commit
ffe8eff049
|
@ -765,6 +765,12 @@ tasks:
|
|||
working_directory: examples/bzlmod/proto
|
||||
build_targets:
|
||||
- "//..."
|
||||
bzlmod_proto:
|
||||
name: Proto and Prost with prebuilt protoc with bzlmod
|
||||
platform: ubuntu2004
|
||||
working_directory: examples/bzlmod/proto_with_toolchain
|
||||
build_targets:
|
||||
- "//..."
|
||||
compile_one_dependency:
|
||||
name: --compile_one_dependency flag
|
||||
platform: ubuntu2004
|
||||
|
|
|
@ -27,7 +27,7 @@ bazel_dep(
|
|||
)
|
||||
bazel_dep(
|
||||
name = "rules_proto",
|
||||
version = "5.3.0-21.7",
|
||||
version = "6.0.2",
|
||||
)
|
||||
bazel_dep(
|
||||
name = "apple_support",
|
||||
|
@ -68,7 +68,6 @@ use_repo(
|
|||
"cargo_bazel.buildifier-linux-amd64",
|
||||
"cargo_bazel.buildifier-linux-arm64",
|
||||
"cargo_bazel.buildifier-windows-amd64.exe",
|
||||
"com_google_googleapis",
|
||||
"cui",
|
||||
"cui__anyhow-1.0.75",
|
||||
"cui__camino-1.1.6",
|
||||
|
|
|
@ -11,6 +11,7 @@ bzl_library(
|
|||
"@com_google_protobuf//:bzl_srcs",
|
||||
],
|
||||
deps = [
|
||||
"@bazel_features//:deps",
|
||||
"@bazel_features//:features",
|
||||
"@bazel_skylib//lib:paths",
|
||||
"@bazel_skylib//lib:selects",
|
||||
|
|
|
@ -8,5 +8,5 @@ bazel_dep(
|
|||
)
|
||||
bazel_dep(
|
||||
name = "bazel_features",
|
||||
version = "1.11.0",
|
||||
version = "1.14.0",
|
||||
)
|
||||
|
|
|
@ -809,7 +809,7 @@ Rust Prost toolchain rule.
|
|||
| <a id="rust_prost_toolchain-prost_plugin_flag"></a>prost_plugin_flag | Prost plugin flag format. (e.g. `--plugin=protoc-gen-prost=%s`) | String | optional | `"--plugin=protoc-gen-prost=%s"` |
|
||||
| <a id="rust_prost_toolchain-prost_runtime"></a>prost_runtime | The Prost runtime crates to use. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="rust_prost_toolchain-prost_types"></a>prost_types | The Prost types crates to use. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="rust_prost_toolchain-proto_compiler"></a>proto_compiler | The protoc compiler to use. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="rust_prost_toolchain-proto_compiler"></a>proto_compiler | The protoc compiler to use. Note that this attribute is deprecated - prefer to use --incompatible_enable_proto_toolchain_resolution. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="rust_prost_toolchain-tonic_opts"></a>tonic_opts | Additional options to add to Tonic. | List of strings | optional | `[]` |
|
||||
| <a id="rust_prost_toolchain-tonic_plugin"></a>tonic_plugin | Additional plugins to add to Tonic. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="rust_prost_toolchain-tonic_plugin_flag"></a>tonic_plugin_flag | Tonic plugin flag format. (e.g. `--plugin=protoc-gen-tonic=%s`)) | String | optional | `"--plugin=protoc-gen-tonic=%s"` |
|
||||
|
@ -1778,14 +1778,18 @@ This macro should be called immediately after the `rust_protobuf_dependencies` m
|
|||
rust_proto_protobuf_dependencies(<a href="#rust_proto_protobuf_dependencies-bzlmod">bzlmod</a>)
|
||||
</pre>
|
||||
|
||||
|
||||
Sets up dependencies for rules_rust's proto support.
|
||||
|
||||
**PARAMETERS**
|
||||
|
||||
|
||||
| Name | Description | Default Value |
|
||||
| :------------- | :------------- | :------------- |
|
||||
| <a id="rust_proto_protobuf_dependencies-bzlmod"></a>bzlmod | <p align="center"> - </p> | `False` |
|
||||
| <a id="rust_proto_protobuf_dependencies-bzlmod"></a>bzlmod | Whether this function is being called from a bzlmod context rather than a workspace context. | `False` |
|
||||
|
||||
**RETURNS**
|
||||
|
||||
A list of structs containing information about root module deps to report to bzlmod's extension_metadata.
|
||||
|
||||
|
||||
<a id="rust_proto_protobuf_register_toolchains"></a>
|
||||
|
|
|
@ -319,7 +319,7 @@ Rust Prost toolchain rule.
|
|||
| <a id="rust_prost_toolchain-prost_plugin_flag"></a>prost_plugin_flag | Prost plugin flag format. (e.g. `--plugin=protoc-gen-prost=%s`) | String | optional | `"--plugin=protoc-gen-prost=%s"` |
|
||||
| <a id="rust_prost_toolchain-prost_runtime"></a>prost_runtime | The Prost runtime crates to use. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="rust_prost_toolchain-prost_types"></a>prost_types | The Prost types crates to use. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="rust_prost_toolchain-proto_compiler"></a>proto_compiler | The protoc compiler to use. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="rust_prost_toolchain-proto_compiler"></a>proto_compiler | The protoc compiler to use. Note that this attribute is deprecated - prefer to use --incompatible_enable_proto_toolchain_resolution. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="rust_prost_toolchain-tonic_opts"></a>tonic_opts | Additional options to add to Tonic. | List of strings | optional | `[]` |
|
||||
| <a id="rust_prost_toolchain-tonic_plugin"></a>tonic_plugin | Additional plugins to add to Tonic. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="rust_prost_toolchain-tonic_plugin_flag"></a>tonic_plugin_flag | Tonic plugin flag format. (e.g. `--plugin=protoc-gen-tonic=%s`)) | String | optional | `"--plugin=protoc-gen-tonic=%s"` |
|
||||
|
@ -434,14 +434,18 @@ This macro should be called immediately after the `rust_protobuf_dependencies` m
|
|||
rust_proto_protobuf_dependencies(<a href="#rust_proto_protobuf_dependencies-bzlmod">bzlmod</a>)
|
||||
</pre>
|
||||
|
||||
|
||||
Sets up dependencies for rules_rust's proto support.
|
||||
|
||||
**PARAMETERS**
|
||||
|
||||
|
||||
| Name | Description | Default Value |
|
||||
| :------------- | :------------- | :------------- |
|
||||
| <a id="rust_proto_protobuf_dependencies-bzlmod"></a>bzlmod | <p align="center"> - </p> | `False` |
|
||||
| <a id="rust_proto_protobuf_dependencies-bzlmod"></a>bzlmod | Whether this function is being called from a bzlmod context rather than a workspace context. | `False` |
|
||||
|
||||
**RETURNS**
|
||||
|
||||
A list of structs containing information about root module deps to report to bzlmod's extension_metadata.
|
||||
|
||||
|
||||
<a id="rust_proto_protobuf_register_toolchains"></a>
|
||||
|
|
|
@ -11,6 +11,10 @@ bazel_dep(name = "bazel_skylib", version = "1.7.1")
|
|||
|
||||
# https://github.com/bazelbuild/rules_rust/releases
|
||||
bazel_dep(name = "rules_rust", version = "0.46.0")
|
||||
local_path_override(
|
||||
module_name = "rules_rust",
|
||||
path = "../../..",
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# T O O L C H A I N S
|
||||
|
|
|
@ -8,6 +8,10 @@ module(
|
|||
###############################################################################
|
||||
# https://github.com/bazelbuild/rules_rust/releases
|
||||
bazel_dep(name = "rules_rust", version = "0.46.0")
|
||||
local_path_override(
|
||||
module_name = "rules_rust",
|
||||
path = "../../..",
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# T O O L C H A I N S
|
||||
|
|
|
@ -5,6 +5,10 @@ module(
|
|||
|
||||
# https://github.com/bazelbuild/rules_rust/releases
|
||||
bazel_dep(name = "rules_rust", version = "0.46.0")
|
||||
local_path_override(
|
||||
module_name = "rules_rust",
|
||||
path = "../../..",
|
||||
)
|
||||
|
||||
# Rules for cross compilation
|
||||
bazel_dep(name = "toolchains_musl", version = "0.1.16", dev_dependency = True)
|
||||
|
|
|
@ -8,6 +8,10 @@ module(
|
|||
###############################################################################
|
||||
# https://github.com/bazelbuild/rules_rust/releases
|
||||
bazel_dep(name = "rules_rust", version = "0.46.0")
|
||||
local_path_override(
|
||||
module_name = "rules_rust",
|
||||
path = "../../..",
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# T O O L C H A I N S
|
||||
|
|
|
@ -8,6 +8,10 @@ module(
|
|||
###############################################################################
|
||||
# https://github.com/bazelbuild/rules_rust/releases
|
||||
bazel_dep(name = "rules_rust", version = "0.46.0")
|
||||
local_path_override(
|
||||
module_name = "rules_rust",
|
||||
path = "../../..",
|
||||
)
|
||||
|
||||
#
|
||||
# Rules for protobuf / gRPC
|
||||
|
|
|
@ -21,7 +21,6 @@ rust_prost_toolchain(
|
|||
prost_plugin = "@crates//:protoc-gen-prost__protoc-gen-prost",
|
||||
prost_runtime = ":prost_runtime",
|
||||
prost_types = "@crates//:prost-types",
|
||||
proto_compiler = "@protobuf//:protoc",
|
||||
tonic_plugin = "@crates//:protoc-gen-tonic__protoc-gen-tonic",
|
||||
tonic_runtime = ":tonic_runtime",
|
||||
)
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# Required on windows
|
||||
common --enable_platform_specific_config
|
||||
startup --windows_enable_symlinks
|
||||
build:windows --enable_runfiles
|
||||
|
||||
# Required for cargo_build_script support before Bazel 7
|
||||
build --incompatible_merge_fixed_and_default_shell_env
|
||||
|
||||
common --incompatible_enable_proto_toolchain_resolution
|
|
@ -0,0 +1 @@
|
|||
../.bazelversion
|
|
@ -0,0 +1,5 @@
|
|||
/bazel-*
|
||||
.DS_Store
|
||||
/proto/.DS_Store
|
||||
/proto/grpc_server/.DS_Store
|
||||
/proto/proto_bindings/.DS_Store
|
|
@ -0,0 +1,6 @@
|
|||
config_setting(
|
||||
name = "release",
|
||||
values = {
|
||||
"compilation_mode": "opt",
|
||||
},
|
||||
)
|
|
@ -0,0 +1,42 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
|
||||
members = [
|
||||
"proto_bindings",
|
||||
"grpc_server",
|
||||
"grpc_client",
|
||||
]
|
||||
|
||||
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
rust-version = "1.78.0"
|
||||
readme = "README.md"
|
||||
|
||||
|
||||
[workspace.dependencies]
|
||||
# Internal crates
|
||||
proto_bindings = { path = "proto_bindings" }
|
||||
# External crates
|
||||
prost = { version = "0.12.6" }
|
||||
prost-types = { version = "0.12.6", default-features = false }
|
||||
tonic = { version = "0.11.0", features = ["transport"] }
|
||||
tonic-build = "0.11.0"
|
||||
tokio = { version = "1.38", default-features = false, features = ["macros", "net", "rt-multi-thread", "signal"] }
|
||||
|
||||
|
||||
# Optimize all crates
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
strip = true # Automatically strip debug symbols from the binary
|
||||
lto = true # Enable Link Time Optimization (LTO)
|
||||
codegen-units = 1 # Reduce Parallel Code Generation Units to Increase Optimization
|
||||
|
||||
|
||||
# There's a Cargo feature named profile-overrides
|
||||
# that lets you override the optimization level of dependencies.
|
||||
# https://docs.rust-embedded.org/book/unsorted/speed-vs-size.html
|
||||
[profile.release.package."*"]
|
||||
opt-level = 3
|
||||
strip = 'debuginfo' # Automatically strip debug infos from the binary to reduce size
|
||||
codegen-units = 1 # Reduce Parallel Code Generation Units to Increase Optimization
|
|
@ -0,0 +1,133 @@
|
|||
module(
|
||||
name = "grpc-client-server",
|
||||
version = "0.0.0",
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# B A Z E L C E N T R A L R E G I S T R Y # https://registry.bazel.build/
|
||||
###############################################################################
|
||||
# https://github.com/bazelbuild/rules_rust/releases
|
||||
bazel_dep(name = "rules_rust", version = "0.46.0")
|
||||
local_path_override(
|
||||
module_name = "rules_rust",
|
||||
path = "../../..",
|
||||
)
|
||||
|
||||
#
|
||||
# Rules for protobuf / gRPC
|
||||
# https://github.com/bazelbuild/rules_proto/releases
|
||||
bazel_dep(name = "rules_proto", version = "6.0.2")
|
||||
|
||||
# https://github.com/aspect-build/toolchains_protoc/releases
|
||||
bazel_dep(name = "toolchains_protoc", version = "0.3.1")
|
||||
|
||||
# https://registry.bazel.build/modules/protobuf
|
||||
bazel_dep(name = "protobuf", version = "27.1")
|
||||
|
||||
# https://github.com/bazel-contrib/toolchains_llvm
|
||||
bazel_dep(name = "toolchains_llvm", version = "1.0.0")
|
||||
|
||||
###############################################################################
|
||||
# L L V M
|
||||
# https://github.com/bazel-contrib/toolchains_llvm/blob/master/tests/MODULE.bazel
|
||||
###############################################################################
|
||||
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm")
|
||||
|
||||
# LLVM Versions and platforms
|
||||
# https://github.com/bazel-contrib/toolchains_llvm/blob/master/toolchain/internal/llvm_distributions.bzl
|
||||
LLVM_VERSIONS = {
|
||||
"": "16.0.0",
|
||||
"darwin-aarch64": "16.0.3",
|
||||
"darwin-x86_64": "15.0.7",
|
||||
}
|
||||
|
||||
# Host LLVM toolchain.
|
||||
llvm.toolchain(
|
||||
name = "llvm_toolchain",
|
||||
llvm_versions = LLVM_VERSIONS,
|
||||
)
|
||||
use_repo(llvm, "llvm_toolchain", "llvm_toolchain_llvm")
|
||||
|
||||
register_toolchains("@llvm_toolchain//:all")
|
||||
|
||||
###############################################################################
|
||||
# T O O L C H A I N S
|
||||
###############################################################################
|
||||
|
||||
# Rust toolchain
|
||||
RUST_EDITION = "2021"
|
||||
|
||||
RUST_VERSION = "1.79.0"
|
||||
|
||||
rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
|
||||
rust.toolchain(
|
||||
edition = RUST_EDITION,
|
||||
versions = [RUST_VERSION],
|
||||
)
|
||||
use_repo(rust, "rust_toolchains")
|
||||
|
||||
register_toolchains("@rust_toolchains//:all")
|
||||
|
||||
# Proto toolchain
|
||||
register_toolchains("@rules_rust//proto/protobuf:default-proto-toolchain")
|
||||
|
||||
# Custom Prost toolchain
|
||||
register_toolchains("@//build/prost_toolchain")
|
||||
|
||||
###############################################################################
|
||||
# R U S T C R A T E S
|
||||
###############################################################################
|
||||
crate = use_extension("@rules_rust//crate_universe:extension.bzl", "crate")
|
||||
|
||||
#
|
||||
# protobuf / gRPC dependencies
|
||||
crate.spec(
|
||||
package = "prost",
|
||||
version = "0.12",
|
||||
)
|
||||
crate.spec(
|
||||
default_features = False,
|
||||
package = "prost-types",
|
||||
version = "0.12",
|
||||
)
|
||||
crate.spec(
|
||||
features = ["transport"],
|
||||
package = "tonic",
|
||||
version = "0.11",
|
||||
)
|
||||
crate.spec(
|
||||
package = "tonic-build",
|
||||
version = "0.11",
|
||||
)
|
||||
crate.spec(
|
||||
package = "protoc-gen-prost",
|
||||
version = "0.3.1",
|
||||
)
|
||||
crate.annotation(
|
||||
crate = "protoc-gen-prost",
|
||||
gen_binaries = ["protoc-gen-prost"],
|
||||
)
|
||||
crate.spec(
|
||||
package = "protoc-gen-tonic",
|
||||
version = "0.4.0",
|
||||
)
|
||||
crate.annotation(
|
||||
crate = "protoc-gen-tonic",
|
||||
gen_binaries = ["protoc-gen-tonic"],
|
||||
)
|
||||
|
||||
#
|
||||
# External crates
|
||||
crate.spec(
|
||||
default_features = False,
|
||||
features = [
|
||||
"macros",
|
||||
"net",
|
||||
"rt-multi-thread",
|
||||
"signal",
|
||||
],
|
||||
package = "tokio",
|
||||
version = "1.38",
|
||||
)
|
||||
crate.from_specs()
|
||||
use_repo(crate, "crates")
|
|
@ -0,0 +1,221 @@
|
|||
# gRPC Client & Server
|
||||
|
||||
This example shows how to build a gRPC server and client in Rust with Bazel.
|
||||
There is a Cargo Workspace configuration and a Bazelmod configuration. Furthermore,
|
||||
all binary targets apply optimization from the [compiler optimization example](../03-comp-opt).
|
||||
|
||||
To run the example with Cargo, open one terminal and start the server with:
|
||||
|
||||
`
|
||||
cargo run --bin grpc_server
|
||||
`
|
||||
|
||||
And, in a second terminal, to run the client:
|
||||
|
||||
`
|
||||
cargo run --bin grpc_client
|
||||
`
|
||||
|
||||
The equivalent Bazel targets are:
|
||||
|
||||
Server:
|
||||
|
||||
`bazel run //grpc_server:bin`
|
||||
|
||||
Client:
|
||||
|
||||
`bazel run //grpc_client:bin`
|
||||
|
||||
## Setup
|
||||
|
||||
The Prost and Tonic rules do not specify a default toolchain in order to avoid mismatched dependency issues.
|
||||
While the Tonic toolchain works out of the box when its dependencies are matched, however,
|
||||
Prost requires a custom toolchain that you have to define.
|
||||
|
||||
The setup requires three steps to complete:
|
||||
1. Configure rules and dependencies in MODULE.bazel
|
||||
2. Configure a custom Prost toolchain
|
||||
3. Register custom Prost toolchain.
|
||||
|
||||
To keep the build hermetic, we use the LLVM Clang compiler to compile all C/C++ dependencies.
|
||||
|
||||
### 1) Configure rules and dependencies
|
||||
|
||||
In your MODULE.bazel, you add the following:
|
||||
|
||||
```starlark
|
||||
# rules for proto
|
||||
###############################################################################
|
||||
# https://github.com/bazelbuild/rules_proto/releases
|
||||
bazel_dep(name = "rules_proto", version = "6.0.2")
|
||||
# https://github.com/aspect-build/toolchains_protoc/releases
|
||||
bazel_dep(name = "toolchains_protoc", version = "0.3.1")
|
||||
# https://registry.bazel.build/modules/protobuf
|
||||
bazel_dep(name = "protobuf", version = "27.1")
|
||||
# rules for LLVM
|
||||
# https://github.com/bazel-contrib/toolchains_llvm
|
||||
bazel_dep(name = "toolchains_llvm", version = "1.0.0")
|
||||
|
||||
# 1 Register LLVM
|
||||
###############################################################################
|
||||
# L L V M
|
||||
# https://github.com/bazel-contrib/toolchains_llvm/blob/master/tests/MODULE.bazel
|
||||
###############################################################################
|
||||
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm")
|
||||
LLVM_VERSIONS = { "": "16.0.0",}
|
||||
|
||||
# LLVM toolchain.
|
||||
llvm.toolchain(
|
||||
name = "llvm_toolchain",
|
||||
llvm_versions = LLVM_VERSIONS,
|
||||
)
|
||||
use_repo(llvm, "llvm_toolchain", "llvm_toolchain_llvm")
|
||||
register_toolchains("@llvm_toolchain//:all")
|
||||
|
||||
# 2 Register Proto toolchain
|
||||
###############################################################################
|
||||
# Proto toolchain
|
||||
register_toolchains("@rules_rust//proto/protobuf:default-proto-toolchain")
|
||||
|
||||
# Custom Prost toolchain will be added later. See next section
|
||||
|
||||
# 3 Register proto / prost / tonic crates
|
||||
###############################################################################
|
||||
crate = use_extension("@rules_rust//crate_universe:extension.bzl", "crate")
|
||||
|
||||
# protobufs / gRPC
|
||||
crate.spec(
|
||||
package = "prost",
|
||||
version = "0.12",
|
||||
)
|
||||
crate.spec(
|
||||
default_features = False,
|
||||
package = "prost-types",
|
||||
version = "0.12",
|
||||
)
|
||||
crate.spec(
|
||||
features = ["transport"],
|
||||
package = "tonic",
|
||||
version = "0.11",
|
||||
)
|
||||
crate.spec(
|
||||
package = "tonic-build",
|
||||
version = "0.11",
|
||||
)
|
||||
crate.spec(
|
||||
package = "protoc-gen-prost",
|
||||
version = "0.3.1",
|
||||
)
|
||||
crate.annotation(
|
||||
crate = "protoc-gen-prost",
|
||||
gen_binaries = ["protoc-gen-prost"],
|
||||
)
|
||||
crate.spec(
|
||||
package = "protoc-gen-tonic",
|
||||
version = "0.4.0",
|
||||
)
|
||||
crate.annotation(
|
||||
crate = "protoc-gen-tonic",
|
||||
gen_binaries = ["protoc-gen-tonic"],
|
||||
)
|
||||
|
||||
# Other Rust dependencies ...
|
||||
|
||||
crate.from_specs()
|
||||
use_repo(crate, "crates")
|
||||
```
|
||||
|
||||
### 2) Configure a custom Prost toolchain
|
||||
|
||||
Configuring a custom Prost toolchain is straightforward, you create a new folder with an empty BUILD.bazl file, and add
|
||||
the toolchain definition.
|
||||
As your Bazel setup grows over time, it is a best practice to put all custom macros, rules, and toolchains in a
|
||||
dedicated folder, for example: `build/`.
|
||||
|
||||
Suppose you have your BUILD.bazl file in `build/prost_toolchain/BUILD.bazel`, then add the following content:
|
||||
|
||||
```starlark
|
||||
load("@rules_rust//proto/prost:defs.bzl", "rust_prost_toolchain")
|
||||
load("@rules_rust//rust:defs.bzl", "rust_library_group")
|
||||
|
||||
rust_library_group(
|
||||
name = "prost_runtime",
|
||||
deps = [
|
||||
"@crates//:prost",
|
||||
],
|
||||
)
|
||||
|
||||
rust_library_group(
|
||||
name = "tonic_runtime",
|
||||
deps = [
|
||||
":prost_runtime",
|
||||
"@crates//:tonic",
|
||||
],
|
||||
)
|
||||
|
||||
rust_prost_toolchain(
|
||||
name = "prost_toolchain_impl",
|
||||
prost_plugin = "@crates//:protoc-gen-prost__protoc-gen-prost",
|
||||
prost_runtime = ":prost_runtime",
|
||||
prost_types = "@crates//:prost-types",
|
||||
proto_compiler = "@protobuf//:protoc",
|
||||
tonic_plugin = "@crates//:protoc-gen-tonic__protoc-gen-tonic",
|
||||
tonic_runtime = ":tonic_runtime",
|
||||
)
|
||||
|
||||
toolchain(
|
||||
name = "prost_toolchain",
|
||||
toolchain = "prost_toolchain_impl",
|
||||
toolchain_type = "@rules_rust//proto/prost:toolchain_type",
|
||||
)
|
||||
```
|
||||
|
||||
The Prost and Tonic dependencies are pulled from the previously configured
|
||||
crate dependencies in the MODULE file. With this custom toolchain in place, the last step is to register it.
|
||||
|
||||
### 3. Register custom Prost toolchain.
|
||||
|
||||
In your MODULE.bazel file, locate your toolchains and add the following entry right below the proto toolchain.
|
||||
|
||||
```starlark
|
||||
# 2 Register Proto toolchain
|
||||
###############################################################################
|
||||
# Proto toolchain
|
||||
register_toolchains("@rules_rust//proto/protobuf:default-proto-toolchain")
|
||||
|
||||
# Custom Prost toolchain
|
||||
register_toolchains("@//build/prost_toolchain")
|
||||
```
|
||||
|
||||
Pay attention to the path, `build/prost_toolchain` because if your toolchain
|
||||
is in a different folder, you have to update this path to make the build work.
|
||||
|
||||
## Usage
|
||||
|
||||
Once the setup has been completed, you use the proto & prost targets as you normally do. For example, to configure rust
|
||||
bindings for a proto file, just add the target:
|
||||
|
||||
```starlark
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_rust//proto/prost:defs.bzl", "rust_prost_library")
|
||||
|
||||
# Build proto files
|
||||
# https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_proto_library
|
||||
proto_library(
|
||||
name = "proto_bindings",
|
||||
srcs = [
|
||||
"proto/helloworld.proto",
|
||||
],
|
||||
)
|
||||
|
||||
# Generate Rust bindings from the generated proto files
|
||||
# https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_prost_library
|
||||
rust_prost_library(
|
||||
name = "rust_proto",
|
||||
proto = ":proto_bindings",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
```
|
||||
|
||||
From there, you
|
||||
just [follow the target documentation](https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_proto_library).
|
|
@ -0,0 +1,32 @@
|
|||
load("@rules_rust//proto/prost:defs.bzl", "rust_prost_toolchain")
|
||||
load("@rules_rust//rust:defs.bzl", "rust_library_group")
|
||||
|
||||
rust_library_group(
|
||||
name = "prost_runtime",
|
||||
deps = [
|
||||
"@crates//:prost",
|
||||
],
|
||||
)
|
||||
|
||||
rust_library_group(
|
||||
name = "tonic_runtime",
|
||||
deps = [
|
||||
":prost_runtime",
|
||||
"@crates//:tonic",
|
||||
],
|
||||
)
|
||||
|
||||
rust_prost_toolchain(
|
||||
name = "prost_toolchain_impl",
|
||||
prost_plugin = "@crates//:protoc-gen-prost__protoc-gen-prost",
|
||||
prost_runtime = ":prost_runtime",
|
||||
prost_types = "@crates//:prost-types",
|
||||
tonic_plugin = "@crates//:protoc-gen-tonic__protoc-gen-tonic",
|
||||
tonic_runtime = ":tonic_runtime",
|
||||
)
|
||||
|
||||
toolchain(
|
||||
name = "prost_toolchain",
|
||||
toolchain = "prost_toolchain_impl",
|
||||
toolchain_type = "@rules_rust//proto/prost:toolchain_type",
|
||||
)
|
|
@ -0,0 +1,47 @@
|
|||
load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_doc", "rust_doc_test")
|
||||
|
||||
# Build binary
|
||||
# https://bazelbuild.github.io/rules_rust/defs.html#rust_binary
|
||||
rust_binary(
|
||||
name = "bin",
|
||||
srcs = glob([
|
||||
"src/*.rs",
|
||||
]),
|
||||
crate_root = "src/main.rs",
|
||||
rustc_flags = select({
|
||||
"//:release": [
|
||||
"-Clto",
|
||||
"-Ccodegen-units=1",
|
||||
"-Cpanic=abort",
|
||||
"-Copt-level=3",
|
||||
"-Cstrip=symbols",
|
||||
],
|
||||
"//conditions:default": [
|
||||
"-Copt-level=0",
|
||||
],
|
||||
}),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
# Internal crates
|
||||
"//proto_bindings:rust_proto",
|
||||
# External crates
|
||||
"@crates//:tokio",
|
||||
"@crates//:tonic",
|
||||
],
|
||||
)
|
||||
|
||||
# Build documentation
|
||||
# https://bazelbuild.github.io/rules_rust/rust_doc.html
|
||||
rust_doc(
|
||||
name = "client_doc",
|
||||
crate = ":bin",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
# Test documentation
|
||||
# https://bazelbuild.github.io/rules_rust/rust_doc.html#rust_doc_test
|
||||
rust_doc_test(
|
||||
name = "client_doc_test",
|
||||
crate = ":bin",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "grpc_client"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
readme.workspace = true
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "grpc_client"
|
||||
path = "src/main.rs"
|
||||
|
||||
|
||||
[dependencies]
|
||||
# Internal crates
|
||||
proto_bindings = { workspace = true }
|
||||
# External crates
|
||||
tokio = { workspace = true }
|
||||
tonic = { workspace = true }
|
|
@ -0,0 +1,23 @@
|
|||
use proto_bindings::proto::greeter_client::GreeterClient;
|
||||
use proto_bindings::proto::HelloRequest;
|
||||
|
||||
// https://github.com/hyperium/tonic/blob/master/examples/src/helloworld/client.rs
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut client = GreeterClient::connect("http://[::1]:5042")
|
||||
.await
|
||||
.expect("[Client]: Failed to connect to server.");
|
||||
|
||||
let request = tonic::Request::new(HelloRequest {
|
||||
name: "Hello gRPC".into(),
|
||||
});
|
||||
|
||||
let response = client
|
||||
.say_hello(request)
|
||||
.await
|
||||
.expect("[Client]: Failed to get a response from the server");
|
||||
|
||||
println!("RESPONSE={:?}", response);
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_doc", "rust_doc_test", "rust_test_suite")
|
||||
|
||||
# Build binary
|
||||
# https://bazelbuild.github.io/rules_rust/defs.html#rust_binary
|
||||
rust_binary(
|
||||
name = "bin",
|
||||
srcs = glob([
|
||||
"src/*.rs",
|
||||
]),
|
||||
crate_root = "src/main.rs",
|
||||
rustc_flags = select({
|
||||
"//:release": [
|
||||
"-Clto",
|
||||
"-Ccodegen-units=1",
|
||||
"-Cpanic=abort",
|
||||
"-Copt-level=3",
|
||||
"-Cstrip=symbols",
|
||||
],
|
||||
"//conditions:default": [
|
||||
"-Copt-level=0",
|
||||
],
|
||||
}),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
# Internal crates
|
||||
"//proto_bindings:rust_proto",
|
||||
# External crates
|
||||
"@crates//:tokio",
|
||||
"@crates//:tonic",
|
||||
],
|
||||
)
|
||||
|
||||
# Build documentation
|
||||
# https://bazelbuild.github.io/rules_rust/rust_doc.html
|
||||
rust_doc(
|
||||
name = "server_doc",
|
||||
crate = ":bin",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
# Test documentation
|
||||
# https://bazelbuild.github.io/rules_rust/rust_doc.html#rust_doc_test
|
||||
rust_doc_test(
|
||||
name = "server_doc_test",
|
||||
crate = ":bin",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
rust_test_suite(
|
||||
name = "demo_tests",
|
||||
srcs = glob([
|
||||
"tests/*_tests.rs",
|
||||
]),
|
||||
tags = ["unit"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
# Crate to test
|
||||
"//proto_bindings:rust_proto",
|
||||
# External crates
|
||||
],
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "grpc_server"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
readme.workspace = true
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "grpc_server"
|
||||
path = "src/main.rs"
|
||||
|
||||
|
||||
[dependencies]
|
||||
# Internal crates
|
||||
proto_bindings = { workspace = true }
|
||||
# External crates
|
||||
tokio = { workspace = true }
|
||||
tonic = { workspace = true }
|
|
@ -0,0 +1,40 @@
|
|||
use std::error::Error;
|
||||
|
||||
use tonic::transport::Server;
|
||||
|
||||
use proto_bindings::proto::greeter_server::GreeterServer;
|
||||
|
||||
use crate::server::MyGreeter;
|
||||
|
||||
mod server;
|
||||
mod shutdown_utils;
|
||||
|
||||
// https://github.com/hyperium/tonic/blob/master/examples/src/helloworld/server.rs
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
let addr = "[::1]:5042"
|
||||
.parse()
|
||||
.expect("[Server]: Failed to parse socket address");
|
||||
|
||||
let grpc_svc = GreeterServer::new(MyGreeter::new());
|
||||
|
||||
// Shutdown signal handler
|
||||
let signal = shutdown_utils::signal_handler("gRPC Greeter server");
|
||||
|
||||
let grpc_server = Server::builder()
|
||||
.add_service(grpc_svc)
|
||||
.serve_with_shutdown(addr, signal);
|
||||
|
||||
let grpc_handle = tokio::spawn(grpc_server);
|
||||
|
||||
println!("GreeterServer listening on {}", addr);
|
||||
match tokio::try_join!(grpc_handle) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
println!("[Server]: Error: Failed to start gRPC Greeter server.");
|
||||
println!("[Server]: Error: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
use tonic::{Request, Response, Status};
|
||||
|
||||
use proto_bindings::proto::greeter_server::Greeter;
|
||||
use proto_bindings::proto::{HelloReply, HelloRequest};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct MyGreeter {}
|
||||
|
||||
impl MyGreeter {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl Greeter for MyGreeter {
|
||||
async fn say_hello(
|
||||
&self,
|
||||
request: Request<HelloRequest>,
|
||||
) -> Result<Response<HelloReply>, Status> {
|
||||
println!("Got a request from {:?}", request.remote_addr());
|
||||
|
||||
let reply = HelloReply {
|
||||
message: format!("Hello {}!", request.into_inner().name),
|
||||
};
|
||||
Ok(Response::new(reply))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
/// Registers a signal handler that waits for a signal that indicates a shutdown request.
|
||||
// https://stackoverflow.com/questions/77585473/rust-tokio-how-to-handle-more-signals-than-just-sigint-i-e-sigquit?noredirect=1#comment136778587_77585473
|
||||
pub async fn signal_handler(svc: &str) {
|
||||
wait_for_signal_impl(svc).await
|
||||
}
|
||||
|
||||
/// Waits for a signal that requests a graceful shutdown. Supports the following signals on unix:
|
||||
/// * SIGTERM
|
||||
/// * SIGINT (Ctrl-C)
|
||||
/// * SIGQUIT
|
||||
/// * SIGHUP
|
||||
#[cfg(unix)]
|
||||
async fn wait_for_signal_impl(svc: &str) {
|
||||
use tokio::signal::unix::{signal, SignalKind};
|
||||
|
||||
// Docs: https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
|
||||
let mut signal_terminate = signal(SignalKind::terminate()).unwrap();
|
||||
let mut signal_interrupt = signal(SignalKind::interrupt()).unwrap();
|
||||
let mut signal_quit = signal(SignalKind::quit()).unwrap();
|
||||
let mut signal_hang = signal(SignalKind::hangup()).unwrap();
|
||||
|
||||
// https://docs.rs/tokio/latest/tokio/macro.select.html
|
||||
tokio::select! {
|
||||
_ = signal_terminate.recv() => println!("* {svc} received SIGTERM"),
|
||||
_ = signal_interrupt.recv() => println!("* {svc} received SIGINT"),
|
||||
_ = signal_quit.recv() => println!("* {svc} received SIGQUIT"),
|
||||
_ = signal_hang.recv() => println!(" * {svc} received SIGHUP"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits for a signal that requests a graceful shutdown. Supports the following signals on Windows:
|
||||
/// * ctrl_c
|
||||
/// * ctrl_break
|
||||
/// * ctrl_close
|
||||
/// * ctrl_shutdown
|
||||
#[cfg(windows)]
|
||||
async fn wait_for_signal_impl(svc: &str) {
|
||||
use tokio::signal::windows;
|
||||
|
||||
// Docs: https://learn.microsoft.com/en-us/windows/console/handlerroutine
|
||||
let mut signal_c = windows::ctrl_c().unwrap();
|
||||
let mut signal_break = windows::ctrl_break().unwrap();
|
||||
let mut signal_close = windows::ctrl_close().unwrap();
|
||||
let mut signal_shutdown = windows::ctrl_shutdown().unwrap();
|
||||
|
||||
// https://docs.rs/tokio/latest/tokio/macro.select.html
|
||||
tokio::select! {
|
||||
_ = signal_c.recv() => println!("* {svc} received CTRL_C."),
|
||||
_ = signal_break.recv() => println!("* {svc} received CTRL_BREAK."),
|
||||
_ = signal_close.recv() => println!("* {svc} received CTRL_CLOSE."),
|
||||
_ = signal_shutdown.recv() => println!("* {svc} received CTRL_SHUTDOWN."),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#[test]
|
||||
fn demo_test() {
|
||||
assert_eq!(4 + 4, 8);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_rust//proto/prost:defs.bzl", "rust_prost_library")
|
||||
|
||||
# Build proto files
|
||||
# https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_proto_library
|
||||
proto_library(
|
||||
name = "proto_bindings",
|
||||
srcs = [
|
||||
"proto/helloworld.proto",
|
||||
],
|
||||
)
|
||||
|
||||
# Generate Rust bindings from the generated proto files
|
||||
# https://bazelbuild.github.io/rules_rust/rust_proto.html#rust_prost_library
|
||||
rust_prost_library(
|
||||
name = "rust_proto",
|
||||
proto = ":proto_bindings",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "proto_bindings"
|
||||
version = "0.1.0"
|
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "proto_bindings"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
readme.workspace = true
|
||||
|
||||
|
||||
|
||||
[lib]
|
||||
name = "proto_bindings"
|
||||
path = "src/lib.rs"
|
||||
|
||||
|
||||
[dependencies]
|
||||
tonic = { workspace = true }
|
||||
prost = { workspace = true }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = { workspace = true }
|
|
@ -0,0 +1,6 @@
|
|||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
tonic_build::configure()
|
||||
.compile(&["proto/helloworld.proto"], &["proto"])
|
||||
.expect("Failed to compile proto specification");
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2015 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
// https://github.com/hyperium/tonic/blob/master/examples/proto/helloworld/helloworld.proto
|
||||
package proto;
|
||||
|
||||
// The greeting service definition.
|
||||
service Greeter {
|
||||
// Sends a greeting
|
||||
rpc SayHello(HelloRequest) returns (HelloReply) {}
|
||||
}
|
||||
|
||||
// The request message containing the user's name.
|
||||
message HelloRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
// The response message containing the greetings
|
||||
message HelloReply {
|
||||
string message = 1;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
pub mod proto {
|
||||
tonic::include_proto!("proto");
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
exports_files(["BUILD.zlib.bazel"])
|
|
@ -0,0 +1,76 @@
|
|||
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
_ZLIB_HEADERS = [
|
||||
"crc32.h",
|
||||
"deflate.h",
|
||||
"gzguts.h",
|
||||
"inffast.h",
|
||||
"inffixed.h",
|
||||
"inflate.h",
|
||||
"inftrees.h",
|
||||
"trees.h",
|
||||
"zconf.h",
|
||||
"zlib.h",
|
||||
"zutil.h",
|
||||
]
|
||||
|
||||
# In order to limit the damage from the `includes` propagation
|
||||
# via `:zlib`, copy the public headers to a subdirectory and
|
||||
# expose those.
|
||||
_ZLIB_HEADER_PREFIX = "zlib/include"
|
||||
|
||||
_ZLIB_PREFIXED_HEADERS = ["{}/{}".format(_ZLIB_HEADER_PREFIX, hdr) for hdr in _ZLIB_HEADERS]
|
||||
|
||||
[
|
||||
copy_file(
|
||||
name = "{}.copy".format(hdr),
|
||||
src = hdr,
|
||||
out = "{}/{}".format(_ZLIB_HEADER_PREFIX, hdr),
|
||||
)
|
||||
for hdr in _ZLIB_HEADERS
|
||||
]
|
||||
|
||||
_COMMON_COPTS = [
|
||||
"-Wno-deprecated-non-prototype",
|
||||
"-Wno-unused-variable",
|
||||
"-Wno-implicit-function-declaration",
|
||||
]
|
||||
|
||||
cc_library(
|
||||
name = "zlib",
|
||||
srcs = [
|
||||
"adler32.c",
|
||||
"compress.c",
|
||||
"crc32.c",
|
||||
"deflate.c",
|
||||
"gzclose.c",
|
||||
"gzlib.c",
|
||||
"gzread.c",
|
||||
"gzwrite.c",
|
||||
"infback.c",
|
||||
"inffast.c",
|
||||
"inflate.c",
|
||||
"inftrees.c",
|
||||
"trees.c",
|
||||
"uncompr.c",
|
||||
"zutil.c",
|
||||
# Include the un-prefixed headers in srcs to work
|
||||
# around the fact that zlib isn't consistent in its
|
||||
# choice of <> or "" delimiter when including itself.
|
||||
] + _ZLIB_HEADERS,
|
||||
hdrs = _ZLIB_PREFIXED_HEADERS,
|
||||
copts = select({
|
||||
"@platforms//os:linux": [
|
||||
# Required for opt builds to avoid
|
||||
# `libzlib.a(crc32.o): requires unsupported dynamic reloc 11; recompile with -fPIC`
|
||||
"-fPIC",
|
||||
# Silence all warnings
|
||||
"-w",
|
||||
] + _COMMON_COPTS,
|
||||
"@platforms//os:windows": [],
|
||||
"//conditions:default": _COMMON_COPTS,
|
||||
}),
|
||||
includes = ["zlib/include/"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -55,7 +55,6 @@ rust_prost_toolchain(
|
|||
prost_plugin_flag = "--plugin=protoc-gen-prost=%s",
|
||||
prost_runtime = ":prost_runtime",
|
||||
prost_types = "//proto/prost/private/3rdparty/crates:prost-types",
|
||||
proto_compiler = "@com_google_protobuf//:protoc",
|
||||
tonic_plugin = "//proto/prost/private/3rdparty/crates:protoc-gen-tonic__protoc-gen-tonic",
|
||||
tonic_plugin_flag = "--plugin=protoc-gen-tonic=%s",
|
||||
tonic_runtime = ":tonic_runtime",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Rules for building protos in Rust with Prost and Tonic."""
|
||||
|
||||
load("@rules_proto//proto:defs.bzl", "ProtoInfo", "proto_common")
|
||||
load("@rules_proto//proto:proto_common.bzl", proto_toolchains = "toolchains")
|
||||
load("//proto/prost:providers.bzl", "ProstProtoInfo")
|
||||
load("//rust:defs.bzl", "rust_common")
|
||||
|
||||
|
@ -49,7 +50,7 @@ def _compile_proto(ctx, crate_name, proto_info, deps, prost_toolchain, rustfmt_t
|
|||
package_info_file = ctx.actions.declare_file(ctx.label.name + ".prost_package_info")
|
||||
lib_rs = ctx.actions.declare_file("{}.lib.rs".format(ctx.label.name))
|
||||
|
||||
proto_compiler = prost_toolchain.proto_compiler[DefaultInfo].files_to_run
|
||||
proto_compiler = prost_toolchain.proto_compiler
|
||||
tools = depset([proto_compiler.executable])
|
||||
|
||||
additional_args = ctx.actions.args()
|
||||
|
@ -349,13 +350,23 @@ def _rust_prost_toolchain_impl(ctx):
|
|||
if any(tonic_attrs) and not all(tonic_attrs):
|
||||
fail("When one tonic attribute is added, all must be added")
|
||||
|
||||
if ctx.attr.proto_compiler:
|
||||
# buildifier: disable=print
|
||||
print("WARN: rust_prost_toolchain's proto_compiler attribute is deprecated. Make sure your rules_proto dependency is at least version 6.0.0 and stop setting proto_compiler")
|
||||
|
||||
proto_toolchain = proto_toolchains.find_toolchain(
|
||||
ctx,
|
||||
legacy_attr = "_legacy_proto_toolchain",
|
||||
toolchain_type = "@rules_proto//proto:toolchain_type",
|
||||
)
|
||||
|
||||
return [platform_common.ToolchainInfo(
|
||||
prost_opts = ctx.attr.prost_opts,
|
||||
prost_plugin = ctx.attr.prost_plugin,
|
||||
prost_plugin_flag = ctx.attr.prost_plugin_flag,
|
||||
prost_runtime = ctx.attr.prost_runtime,
|
||||
prost_types = ctx.attr.prost_types,
|
||||
proto_compiler = ctx.attr.proto_compiler,
|
||||
proto_compiler = ctx.attr.proto_compiler or proto_toolchain.proto_compiler,
|
||||
protoc_opts = ctx.fragments.proto.experimental_protoc_opts,
|
||||
tonic_opts = ctx.attr.tonic_opts,
|
||||
tonic_plugin = ctx.attr.tonic_plugin,
|
||||
|
@ -367,7 +378,7 @@ rust_prost_toolchain = rule(
|
|||
implementation = _rust_prost_toolchain_impl,
|
||||
doc = "Rust Prost toolchain rule.",
|
||||
fragments = ["proto"],
|
||||
attrs = {
|
||||
attrs = dict({
|
||||
"prost_opts": attr.string_list(
|
||||
doc = "Additional options to add to Prost.",
|
||||
),
|
||||
|
@ -392,10 +403,9 @@ rust_prost_toolchain = rule(
|
|||
mandatory = True,
|
||||
),
|
||||
"proto_compiler": attr.label(
|
||||
doc = "The protoc compiler to use.",
|
||||
doc = "The protoc compiler to use. Note that this attribute is deprecated - prefer to use --incompatible_enable_proto_toolchain_resolution.",
|
||||
cfg = "exec",
|
||||
executable = True,
|
||||
mandatory = True,
|
||||
),
|
||||
"tonic_opts": attr.string_list(
|
||||
doc = "Additional options to add to Tonic.",
|
||||
|
@ -413,7 +423,12 @@ rust_prost_toolchain = rule(
|
|||
doc = "The Tonic runtime crates to use.",
|
||||
providers = [[rust_common.crate_info], [rust_common.crate_group_info]],
|
||||
),
|
||||
},
|
||||
}, **proto_toolchains.if_legacy_toolchain({
|
||||
"_legacy_proto_toolchain": attr.label(
|
||||
default = "//proto/protobuf:legacy_proto_toolchain",
|
||||
),
|
||||
})),
|
||||
toolchains = proto_toolchains.use_toolchain("@rules_proto//proto:toolchain_type"),
|
||||
)
|
||||
|
||||
def _current_prost_runtime_impl(ctx):
|
||||
|
|
|
@ -28,12 +28,9 @@ def rust_prost_dependencies(bzlmod = False):
|
|||
maybe(
|
||||
http_archive,
|
||||
name = "rules_proto",
|
||||
sha256 = "dc3fb206a2cb3441b485eb1e423165b231235a1ea9b031b4433cf7bc1fa460dd",
|
||||
strip_prefix = "rules_proto-5.3.0-21.7",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz",
|
||||
],
|
||||
sha256 = "6fb6767d1bef535310547e03247f7518b03487740c11b6c6adb7952033fe1295",
|
||||
strip_prefix = "rules_proto-6.0.2",
|
||||
url = "https://github.com/bazelbuild/rules_proto/releases/download/6.0.2/rules_proto-6.0.2.tar.gz",
|
||||
)
|
||||
|
||||
maybe(
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Definitions for loading transitive `@rules_rust//proto` dependencies"""
|
||||
|
||||
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
|
||||
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
|
||||
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")
|
||||
|
||||
def rust_prost_transitive_repositories():
|
||||
"""Load transitive dependencies of the `@rules_rust//proto` rules.
|
||||
|
@ -9,7 +8,3 @@ def rust_prost_transitive_repositories():
|
|||
This macro should be called immediately after the `rust_proto_dependencies` macro.
|
||||
"""
|
||||
rules_proto_dependencies()
|
||||
|
||||
rules_proto_toolchains()
|
||||
|
||||
protobuf_deps()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
|
||||
load("//rust:defs.bzl", "rust_binary")
|
||||
load(":legacy_proto_toolchain.bzl", "legacy_proto_toolchain")
|
||||
load(":toolchain.bzl", "rust_proto_toolchain")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
@ -33,3 +34,8 @@ bzl_library(
|
|||
"//proto/protobuf/3rdparty:bzl_lib",
|
||||
],
|
||||
)
|
||||
|
||||
legacy_proto_toolchain(
|
||||
name = "legacy_proto_toolchain",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
"""Helper that wraps --proto_compiler into a ProtoLangToolchainInfo for backwards
|
||||
compatibility with --noincompatible_enable_proto_toolchain_resolution.
|
||||
|
||||
Borrowed from https://github.com/bazelbuild/rules_go/pull/3919
|
||||
"""
|
||||
|
||||
load(
|
||||
"@rules_proto//proto:proto_common.bzl",
|
||||
"ProtoLangToolchainInfo",
|
||||
)
|
||||
|
||||
def _legacy_proto_toolchain_impl(ctx):
|
||||
return [
|
||||
ProtoLangToolchainInfo(
|
||||
proto_compiler = ctx.attr._protoc.files_to_run,
|
||||
),
|
||||
]
|
||||
|
||||
legacy_proto_toolchain = rule(
|
||||
implementation = _legacy_proto_toolchain_impl,
|
||||
attrs = {
|
||||
"_protoc": attr.label(
|
||||
cfg = "exec",
|
||||
default = configuration_field(fragment = "proto", name = "proto_compiler"),
|
||||
),
|
||||
},
|
||||
fragments = ["proto"],
|
||||
)
|
|
@ -19,16 +19,22 @@ load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
|
|||
load("//proto/protobuf/3rdparty/crates:defs.bzl", "crate_repositories")
|
||||
|
||||
def rust_proto_protobuf_dependencies(bzlmod = False):
|
||||
"""Sets up dependencies for rules_rust's proto support.
|
||||
|
||||
Args:
|
||||
bzlmod (bool): Whether this function is being called from a bzlmod context rather than a workspace context.
|
||||
|
||||
Returns:
|
||||
A list of structs containing information about root module deps to report to bzlmod's extension_metadata.
|
||||
|
||||
"""
|
||||
if not bzlmod:
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "rules_proto",
|
||||
sha256 = "dc3fb206a2cb3441b485eb1e423165b231235a1ea9b031b4433cf7bc1fa460dd",
|
||||
strip_prefix = "rules_proto-5.3.0-21.7",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz",
|
||||
],
|
||||
sha256 = "6fb6767d1bef535310547e03247f7518b03487740c11b6c6adb7952033fe1295",
|
||||
strip_prefix = "rules_proto-6.0.2",
|
||||
url = "https://github.com/bazelbuild/rules_proto/releases/download/6.0.2/rules_proto-6.0.2.tar.gz",
|
||||
)
|
||||
|
||||
maybe(
|
||||
|
@ -46,6 +52,14 @@ def rust_proto_protobuf_dependencies(bzlmod = False):
|
|||
],
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "bazel_features",
|
||||
sha256 = "5d7e4eb0bb17aee392143cd667b67d9044c270a9345776a5e5a3cccbc44aa4b3",
|
||||
strip_prefix = "bazel_features-1.13.0",
|
||||
url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.13.0/bazel_features-v1.13.0.tar.gz",
|
||||
)
|
||||
|
||||
return crate_repositories()
|
||||
|
||||
# buildifier: disable=unnamed-macro
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
"""Toolchain for compiling rust stubs from protobuf and gRPC."""
|
||||
|
||||
load("@rules_proto//proto:proto_common.bzl", proto_toolchains = "toolchains")
|
||||
|
||||
# buildifier: disable=bzl-visibility
|
||||
load("//rust/private:utils.bzl", "name_to_crate_name")
|
||||
|
||||
|
@ -71,6 +73,10 @@ def rust_generate_proto(
|
|||
outs = [ctx.actions.declare_file(path + ".rs") for path in paths]
|
||||
output_directory = outs[0].dirname
|
||||
|
||||
# Throughout we use rules_rust as the name as the plugin, not rust, because rust is an unstable builtin language in protoc.
|
||||
# If we use rust as the plugin name, it triggers protoc to try to use its in-built support, which is experimental.
|
||||
# The naming here doesn't matter, it's arbitrary, just the plugin name and the out dir need to match, so we pick rules_rust.
|
||||
|
||||
if is_grpc:
|
||||
# Add grpc stubs to the list of outputs
|
||||
grpc_files = [ctx.actions.declare_file(path + "_grpc.rs") for path in paths]
|
||||
|
@ -84,14 +90,14 @@ def rust_generate_proto(
|
|||
args.add_all([
|
||||
"--",
|
||||
proto_toolchain.protoc,
|
||||
"--plugin=protoc-gen-grpc-rust=" + proto_toolchain.grpc_plugin.path,
|
||||
"--grpc-rust_out=" + output_directory,
|
||||
"--plugin=protoc-gen-grpc-rules_rust=" + proto_toolchain.grpc_plugin.path,
|
||||
"--grpc-rules_rust_out=" + output_directory,
|
||||
])
|
||||
executable = ctx.executable._optional_output_wrapper
|
||||
|
||||
args.add_all([
|
||||
"--plugin=protoc-gen-rust=" + proto_toolchain.proto_plugin.path,
|
||||
"--rust_out=" + output_directory,
|
||||
"--plugin=protoc-gen-rules_rust=" + proto_toolchain.proto_plugin.path,
|
||||
"--rules_rust_out=" + output_directory,
|
||||
])
|
||||
|
||||
args.add_joined(
|
||||
|
@ -118,13 +124,23 @@ def rust_generate_proto(
|
|||
return outs
|
||||
|
||||
def _rust_proto_toolchain_impl(ctx):
|
||||
if ctx.attr.protoc:
|
||||
# buildifier: disable=print
|
||||
print("WARN: rust_prost_toolchain's proto_compiler attribute is deprecated. Make sure your rules_proto dependency is at least version 6.0.0 and stop setting proto_compiler")
|
||||
|
||||
proto_toolchain = proto_toolchains.find_toolchain(
|
||||
ctx,
|
||||
legacy_attr = "_legacy_proto_toolchain",
|
||||
toolchain_type = "@rules_proto//proto:toolchain_type",
|
||||
)
|
||||
|
||||
return platform_common.ToolchainInfo(
|
||||
edition = ctx.attr.edition,
|
||||
grpc_compile_deps = ctx.attr.grpc_compile_deps,
|
||||
grpc_plugin = ctx.file.grpc_plugin,
|
||||
grpc_plugin = ctx.attr.protoc or ctx.file.grpc_plugin,
|
||||
proto_compile_deps = ctx.attr.proto_compile_deps,
|
||||
proto_plugin = ctx.file.proto_plugin,
|
||||
protoc = ctx.executable.protoc,
|
||||
protoc = ctx.executable.protoc or proto_toolchain.proto_compiler,
|
||||
)
|
||||
|
||||
# Default dependencies needed to compile protobuf stubs.
|
||||
|
@ -141,7 +157,7 @@ GRPC_COMPILE_DEPS = PROTO_COMPILE_DEPS + [
|
|||
|
||||
rust_proto_toolchain = rule(
|
||||
implementation = _rust_proto_toolchain_impl,
|
||||
attrs = {
|
||||
attrs = dict({
|
||||
"edition": attr.string(
|
||||
doc = "The edition used by the generated rust source.",
|
||||
),
|
||||
|
@ -168,12 +184,15 @@ rust_proto_toolchain = rule(
|
|||
default = Label("//proto/protobuf/3rdparty/crates:protobuf-codegen__protoc-gen-rust"),
|
||||
),
|
||||
"protoc": attr.label(
|
||||
doc = "The location of the `protoc` binary. It should be an executable target.",
|
||||
doc = "The location of the `protoc` binary. It should be an executable target. Note that this attribute is deprecated - prefer to use --incompatible_enable_proto_toolchain_resolution.",
|
||||
executable = True,
|
||||
cfg = "exec",
|
||||
default = Label("@com_google_protobuf//:protoc"),
|
||||
),
|
||||
},
|
||||
}, **proto_toolchains.if_legacy_toolchain({
|
||||
"_legacy_proto_toolchain": attr.label(
|
||||
default = "//proto/protobuf:legacy_proto_toolchain",
|
||||
),
|
||||
})),
|
||||
doc = """\
|
||||
Declares a Rust Proto toolchain for use.
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
"""Definitions for loading transitive `@rules_rust//proto/protobuf` dependencies"""
|
||||
|
||||
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
|
||||
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
|
||||
load("@bazel_features//:deps.bzl", "bazel_features_deps")
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
|
||||
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")
|
||||
|
||||
def rust_proto_protobuf_transitive_repositories():
|
||||
"""Load transitive dependencies of the `@rules_rust//proto/protobuf` rules.
|
||||
|
@ -10,6 +12,16 @@ def rust_proto_protobuf_transitive_repositories():
|
|||
"""
|
||||
rules_proto_dependencies()
|
||||
|
||||
rules_proto_toolchains()
|
||||
bazel_features_deps()
|
||||
|
||||
protobuf_deps()
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "zlib",
|
||||
build_file = Label("//proto/private:BUILD.zlib.bazel"),
|
||||
sha256 = "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1",
|
||||
strip_prefix = "zlib-1.2.11",
|
||||
urls = [
|
||||
"https://zlib.net/zlib-1.2.11.tar.gz",
|
||||
"https://storage.googleapis.com/mirror.tensorflow.org/zlib.net/zlib-1.2.11.tar.gz",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -63,10 +63,19 @@ def rules_rust_test_deps():
|
|||
sha256 = "b8c487191eb942361af905e40172644eab490190e717c3d09bf83e87f3994fff",
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "rules_python",
|
||||
sha256 = "778aaeab3e6cfd56d681c89f5c10d7ad6bf8d2f1a72de9de55b23081b2d31618",
|
||||
strip_prefix = "rules_python-0.34.0",
|
||||
url = "https://github.com/bazelbuild/rules_python/releases/download/0.34.0/rules_python-0.34.0.tar.gz",
|
||||
)
|
||||
|
||||
direct_deps.extend([
|
||||
struct(repo = "libc", is_dev_dep = True),
|
||||
struct(repo = "rules_rust_toolchain_test_target_json", is_dev_dep = True),
|
||||
struct(repo = "com_google_googleapis", is_dev_dep = True),
|
||||
struct(repo = "rules_python", is_dev_dep = True),
|
||||
])
|
||||
|
||||
return direct_deps
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
"""Rules rust test dependencies transitive dependencies."""
|
||||
|
||||
load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language")
|
||||
load("@rules_python//python:repositories.bzl", "py_repositories")
|
||||
|
||||
def rules_rust_test_deps_transitive():
|
||||
py_repositories()
|
||||
|
||||
switched_rules_by_language(
|
||||
name = "com_google_googleapis_imports",
|
||||
cc = False,
|
||||
|
|
Loading…
Reference in New Issue