diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index 03320fb7f6..12c16cc86f 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -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
diff --git a/MODULE.bazel b/MODULE.bazel
index 5484512013..e2ce9d3948 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -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",
diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel
index 76c40e913c..ef6b2a479e 100644
--- a/docs/BUILD.bazel
+++ b/docs/BUILD.bazel
@@ -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",
diff --git a/docs/MODULE.bazel b/docs/MODULE.bazel
index 767b5cf167..23022157dc 100644
--- a/docs/MODULE.bazel
+++ b/docs/MODULE.bazel
@@ -8,5 +8,5 @@ bazel_dep(
)
bazel_dep(
name = "bazel_features",
- version = "1.11.0",
+ version = "1.14.0",
)
diff --git a/docs/flatten.md b/docs/flatten.md
index c828c8df78..7eab948ae9 100644
--- a/docs/flatten.md
+++ b/docs/flatten.md
@@ -809,7 +809,7 @@ Rust Prost toolchain rule.
| prost_plugin_flag | Prost plugin flag format. (e.g. `--plugin=protoc-gen-prost=%s`) | String | optional | `"--plugin=protoc-gen-prost=%s"` |
| prost_runtime | The Prost runtime crates to use. | Label | required | |
| prost_types | The Prost types crates to use. | Label | required | |
-| proto_compiler | The protoc compiler to use. | Label | required | |
+| proto_compiler | The protoc compiler to use. Note that this attribute is deprecated - prefer to use --incompatible_enable_proto_toolchain_resolution. | Label | optional | `None` |
| tonic_opts | Additional options to add to Tonic. | List of strings | optional | `[]` |
| tonic_plugin | Additional plugins to add to Tonic. | Label | optional | `None` |
| 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(bzlmod)
-
+Sets up dependencies for rules_rust's proto support.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
-| bzlmod |
-
| `False` |
+| 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.
diff --git a/docs/rust_proto.md b/docs/rust_proto.md
index 08eca3759f..9d0e1a5a49 100644
--- a/docs/rust_proto.md
+++ b/docs/rust_proto.md
@@ -319,7 +319,7 @@ Rust Prost toolchain rule.
| prost_plugin_flag | Prost plugin flag format. (e.g. `--plugin=protoc-gen-prost=%s`) | String | optional | `"--plugin=protoc-gen-prost=%s"` |
| prost_runtime | The Prost runtime crates to use. | Label | required | |
| prost_types | The Prost types crates to use. | Label | required | |
-| proto_compiler | The protoc compiler to use. | Label | required | |
+| proto_compiler | The protoc compiler to use. Note that this attribute is deprecated - prefer to use --incompatible_enable_proto_toolchain_resolution. | Label | optional | `None` |
| tonic_opts | Additional options to add to Tonic. | List of strings | optional | `[]` |
| tonic_plugin | Additional plugins to add to Tonic. | Label | optional | `None` |
| 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(bzlmod)
-
+Sets up dependencies for rules_rust's proto support.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
-| bzlmod | -
| `False` |
+| 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.
diff --git a/examples/bzlmod/all_deps_vendor/MODULE.bazel b/examples/bzlmod/all_deps_vendor/MODULE.bazel
index fed1e7b81c..654be4e41c 100644
--- a/examples/bzlmod/all_deps_vendor/MODULE.bazel
+++ b/examples/bzlmod/all_deps_vendor/MODULE.bazel
@@ -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
diff --git a/examples/bzlmod/compile_opt/MODULE.bazel b/examples/bzlmod/compile_opt/MODULE.bazel
index 03dd51ecf5..3ba5c5ea46 100644
--- a/examples/bzlmod/compile_opt/MODULE.bazel
+++ b/examples/bzlmod/compile_opt/MODULE.bazel
@@ -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
diff --git a/examples/bzlmod/cross_compile/MODULE.bazel b/examples/bzlmod/cross_compile/MODULE.bazel
index 50457ab537..d2d11a0c7c 100644
--- a/examples/bzlmod/cross_compile/MODULE.bazel
+++ b/examples/bzlmod/cross_compile/MODULE.bazel
@@ -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)
diff --git a/examples/bzlmod/ffi/MODULE.bazel b/examples/bzlmod/ffi/MODULE.bazel
index e3dc485feb..ccb9a2a939 100644
--- a/examples/bzlmod/ffi/MODULE.bazel
+++ b/examples/bzlmod/ffi/MODULE.bazel
@@ -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
diff --git a/examples/bzlmod/proto/MODULE.bazel b/examples/bzlmod/proto/MODULE.bazel
index fc6cd78459..17eda81f10 100644
--- a/examples/bzlmod/proto/MODULE.bazel
+++ b/examples/bzlmod/proto/MODULE.bazel
@@ -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
diff --git a/examples/bzlmod/proto/build/prost_toolchain/BUILD.bazel b/examples/bzlmod/proto/build/prost_toolchain/BUILD.bazel
index 1075543a16..99dc284ccf 100644
--- a/examples/bzlmod/proto/build/prost_toolchain/BUILD.bazel
+++ b/examples/bzlmod/proto/build/prost_toolchain/BUILD.bazel
@@ -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",
)
diff --git a/examples/bzlmod/proto_with_toolchain/.bazelrc b/examples/bzlmod/proto_with_toolchain/.bazelrc
new file mode 100644
index 0000000000..67ff2b3d98
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/.bazelrc
@@ -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
diff --git a/examples/bzlmod/proto_with_toolchain/.bazelversion b/examples/bzlmod/proto_with_toolchain/.bazelversion
new file mode 120000
index 0000000000..b332604979
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/.bazelversion
@@ -0,0 +1 @@
+../.bazelversion
\ No newline at end of file
diff --git a/examples/bzlmod/proto_with_toolchain/.gitignore b/examples/bzlmod/proto_with_toolchain/.gitignore
new file mode 100644
index 0000000000..c29ff2bab2
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/.gitignore
@@ -0,0 +1,5 @@
+/bazel-*
+.DS_Store
+/proto/.DS_Store
+/proto/grpc_server/.DS_Store
+/proto/proto_bindings/.DS_Store
\ No newline at end of file
diff --git a/examples/bzlmod/proto_with_toolchain/BUILD.bazel b/examples/bzlmod/proto_with_toolchain/BUILD.bazel
new file mode 100644
index 0000000000..ed9b5e7a0e
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/BUILD.bazel
@@ -0,0 +1,6 @@
+config_setting(
+ name = "release",
+ values = {
+ "compilation_mode": "opt",
+ },
+)
diff --git a/examples/bzlmod/proto_with_toolchain/Cargo.toml b/examples/bzlmod/proto_with_toolchain/Cargo.toml
new file mode 100644
index 0000000000..3f3017dac4
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/Cargo.toml
@@ -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
diff --git a/examples/bzlmod/proto_with_toolchain/MODULE.bazel b/examples/bzlmod/proto_with_toolchain/MODULE.bazel
new file mode 100644
index 0000000000..17eda81f10
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/MODULE.bazel
@@ -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")
diff --git a/examples/bzlmod/proto_with_toolchain/README.md b/examples/bzlmod/proto_with_toolchain/README.md
new file mode 100644
index 0000000000..8ce7fc6125
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/README.md
@@ -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).
diff --git a/examples/bzlmod/proto_with_toolchain/build/prost_toolchain/BUILD.bazel b/examples/bzlmod/proto_with_toolchain/build/prost_toolchain/BUILD.bazel
new file mode 100644
index 0000000000..99dc284ccf
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/build/prost_toolchain/BUILD.bazel
@@ -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",
+)
diff --git a/examples/bzlmod/proto_with_toolchain/grpc_client/BUILD.bazel b/examples/bzlmod/proto_with_toolchain/grpc_client/BUILD.bazel
new file mode 100644
index 0000000000..94b11e926d
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/grpc_client/BUILD.bazel
@@ -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"],
+)
diff --git a/examples/bzlmod/proto_with_toolchain/grpc_client/Cargo.toml b/examples/bzlmod/proto_with_toolchain/grpc_client/Cargo.toml
new file mode 100644
index 0000000000..357a3919c2
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/grpc_client/Cargo.toml
@@ -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 }
diff --git a/examples/bzlmod/proto_with_toolchain/grpc_client/src/main.rs b/examples/bzlmod/proto_with_toolchain/grpc_client/src/main.rs
new file mode 100644
index 0000000000..4b7cdd3f93
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/grpc_client/src/main.rs
@@ -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> {
+ 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(())
+}
diff --git a/examples/bzlmod/proto_with_toolchain/grpc_server/BUILD.bazel b/examples/bzlmod/proto_with_toolchain/grpc_server/BUILD.bazel
new file mode 100644
index 0000000000..27e0b43e45
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/grpc_server/BUILD.bazel
@@ -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
+ ],
+)
diff --git a/examples/bzlmod/proto_with_toolchain/grpc_server/Cargo.toml b/examples/bzlmod/proto_with_toolchain/grpc_server/Cargo.toml
new file mode 100644
index 0000000000..3c7c6a2fde
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/grpc_server/Cargo.toml
@@ -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 }
\ No newline at end of file
diff --git a/examples/bzlmod/proto_with_toolchain/grpc_server/src/main.rs b/examples/bzlmod/proto_with_toolchain/grpc_server/src/main.rs
new file mode 100644
index 0000000000..6f22bfac0c
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/grpc_server/src/main.rs
@@ -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> {
+ 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(())
+}
diff --git a/examples/bzlmod/proto_with_toolchain/grpc_server/src/server.rs b/examples/bzlmod/proto_with_toolchain/grpc_server/src/server.rs
new file mode 100644
index 0000000000..a1d457326c
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/grpc_server/src/server.rs
@@ -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,
+ ) -> Result, Status> {
+ println!("Got a request from {:?}", request.remote_addr());
+
+ let reply = HelloReply {
+ message: format!("Hello {}!", request.into_inner().name),
+ };
+ Ok(Response::new(reply))
+ }
+}
diff --git a/examples/bzlmod/proto_with_toolchain/grpc_server/src/shutdown_utils.rs b/examples/bzlmod/proto_with_toolchain/grpc_server/src/shutdown_utils.rs
new file mode 100644
index 0000000000..20d60e1b8c
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/grpc_server/src/shutdown_utils.rs
@@ -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."),
+ }
+}
diff --git a/examples/bzlmod/proto_with_toolchain/grpc_server/tests/demo_tests.rs b/examples/bzlmod/proto_with_toolchain/grpc_server/tests/demo_tests.rs
new file mode 100644
index 0000000000..f12bef408b
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/grpc_server/tests/demo_tests.rs
@@ -0,0 +1,4 @@
+#[test]
+fn demo_test() {
+ assert_eq!(4 + 4, 8);
+}
diff --git a/examples/bzlmod/proto_with_toolchain/grpc_server/tests/mod.rs b/examples/bzlmod/proto_with_toolchain/grpc_server/tests/mod.rs
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/grpc_server/tests/mod.rs
@@ -0,0 +1 @@
+
diff --git a/examples/bzlmod/proto_with_toolchain/proto_bindings/BUILD.bazel b/examples/bzlmod/proto_with_toolchain/proto_bindings/BUILD.bazel
new file mode 100644
index 0000000000..d2f9e24f1e
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/proto_bindings/BUILD.bazel
@@ -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"],
+)
diff --git a/examples/bzlmod/proto_with_toolchain/proto_bindings/Cargo.lock b/examples/bzlmod/proto_with_toolchain/proto_bindings/Cargo.lock
new file mode 100644
index 0000000000..9d1ef987af
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/proto_bindings/Cargo.lock
@@ -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"
diff --git a/examples/bzlmod/proto_with_toolchain/proto_bindings/Cargo.toml b/examples/bzlmod/proto_with_toolchain/proto_bindings/Cargo.toml
new file mode 100644
index 0000000000..95255c32ca
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/proto_bindings/Cargo.toml
@@ -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 }
diff --git a/examples/bzlmod/proto_with_toolchain/proto_bindings/build.rs b/examples/bzlmod/proto_with_toolchain/proto_bindings/build.rs
new file mode 100644
index 0000000000..e1da7552bf
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/proto_bindings/build.rs
@@ -0,0 +1,6 @@
+fn main() -> Result<(), Box> {
+ tonic_build::configure()
+ .compile(&["proto/helloworld.proto"], &["proto"])
+ .expect("Failed to compile proto specification");
+ Ok(())
+}
diff --git a/examples/bzlmod/proto_with_toolchain/proto_bindings/proto/helloworld.proto b/examples/bzlmod/proto_with_toolchain/proto_bindings/proto/helloworld.proto
new file mode 100644
index 0000000000..e838ddc9ec
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/proto_bindings/proto/helloworld.proto
@@ -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;
+}
\ No newline at end of file
diff --git a/examples/bzlmod/proto_with_toolchain/proto_bindings/src/lib.rs b/examples/bzlmod/proto_with_toolchain/proto_bindings/src/lib.rs
new file mode 100644
index 0000000000..860d77e5a1
--- /dev/null
+++ b/examples/bzlmod/proto_with_toolchain/proto_bindings/src/lib.rs
@@ -0,0 +1,3 @@
+pub mod proto {
+ tonic::include_proto!("proto");
+}
diff --git a/proto/private/BUILD.bazel b/proto/private/BUILD.bazel
new file mode 100644
index 0000000000..512d913115
--- /dev/null
+++ b/proto/private/BUILD.bazel
@@ -0,0 +1 @@
+exports_files(["BUILD.zlib.bazel"])
diff --git a/proto/private/BUILD.zlib.bazel b/proto/private/BUILD.zlib.bazel
new file mode 100644
index 0000000000..687375d7b3
--- /dev/null
+++ b/proto/private/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"],
+)
diff --git a/proto/prost/private/BUILD.bazel b/proto/prost/private/BUILD.bazel
index 269721089c..4ae38fc902 100644
--- a/proto/prost/private/BUILD.bazel
+++ b/proto/prost/private/BUILD.bazel
@@ -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",
diff --git a/proto/prost/private/prost.bzl b/proto/prost/private/prost.bzl
index 4c454018a3..c3a7d4e043 100644
--- a/proto/prost/private/prost.bzl
+++ b/proto/prost/private/prost.bzl
@@ -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):
diff --git a/proto/prost/repositories.bzl b/proto/prost/repositories.bzl
index 0c9ca063b2..57727cb2c7 100644
--- a/proto/prost/repositories.bzl
+++ b/proto/prost/repositories.bzl
@@ -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(
diff --git a/proto/prost/transitive_repositories.bzl b/proto/prost/transitive_repositories.bzl
index 11010e3574..13725e00fb 100644
--- a/proto/prost/transitive_repositories.bzl
+++ b/proto/prost/transitive_repositories.bzl
@@ -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()
diff --git a/proto/protobuf/BUILD.bazel b/proto/protobuf/BUILD.bazel
index 8ab84afeb6..f8ba82c058 100644
--- a/proto/protobuf/BUILD.bazel
+++ b/proto/protobuf/BUILD.bazel
@@ -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"],
+)
diff --git a/proto/protobuf/legacy_proto_toolchain.bzl b/proto/protobuf/legacy_proto_toolchain.bzl
new file mode 100644
index 0000000000..a64a1d950b
--- /dev/null
+++ b/proto/protobuf/legacy_proto_toolchain.bzl
@@ -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"],
+)
diff --git a/proto/protobuf/repositories.bzl b/proto/protobuf/repositories.bzl
index 747ee3d39c..ea45dbe93a 100644
--- a/proto/protobuf/repositories.bzl
+++ b/proto/protobuf/repositories.bzl
@@ -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
diff --git a/proto/protobuf/toolchain.bzl b/proto/protobuf/toolchain.bzl
index d03268b4c9..848e267c15 100644
--- a/proto/protobuf/toolchain.bzl
+++ b/proto/protobuf/toolchain.bzl
@@ -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.
diff --git a/proto/protobuf/transitive_repositories.bzl b/proto/protobuf/transitive_repositories.bzl
index 822b4e5a00..3cbae8b6e0 100644
--- a/proto/protobuf/transitive_repositories.bzl
+++ b/proto/protobuf/transitive_repositories.bzl
@@ -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",
+ ],
+ )
diff --git a/test/deps.bzl b/test/deps.bzl
index 412128a8d9..53aad9b89e 100644
--- a/test/deps.bzl
+++ b/test/deps.bzl
@@ -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
diff --git a/test/deps_transitive.bzl b/test/deps_transitive.bzl
index 396dc14133..389d959c5b 100644
--- a/test/deps_transitive.bzl
+++ b/test/deps_transitive.bzl
@@ -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,