Rust Proto

Overview

These build rules are used for building protobufs/gRPC in Rust with Bazel.

There are two rule sets. The first ruleset defines the rust_prost_library which generates Rust code using the prost and tonic dependencies. The second ruleset defines the rust_proto_library and rust_grpc_library rules which generate Rust code using the rust-protobuf dependencies.

See the protobuf example for a more complete example of use.

Prost Setup

load("@rules_rust//proto/prost:repositories.bzl", "rust_prost_dependencies")

rust_prost_dependencies()

load("@rules_rust//proto/prost:transitive_repositories.bzl", "rust_prost_transitive_repositories")

rust_prost_transitive_repositories()

The prost and tonic rules do not specify a default toolchain in order to avoid mismatched dependency issues. To setup the prost and tonic toolchain, please see the section Customizing prost and tonic Dependencies.

For additional information about Bazel toolchains, see here.

Customizing prost and tonic Dependencies

These rules depend on the prost and tonic dependencies. To setup the necessary toolchain for these rules, you must define a toolchain with the prost, prost-types, tonic, protoc-gen-prost, and protoc-gen-tonic crates as well as the protoc binary.

To get access to these crates, you can use the crate_universe repository rules. For example:

load("//crate_universe:defs.bzl", "crate", "crates_repository")

crates_repository(
    name = "crates_io",
    annotations = {
        "protoc-gen-prost": [crate.annotation(
            gen_binaries = ["protoc-gen-prost"],
            patch_args = [
                "-p1",
            ],
            patches = [
                # Note: You will need to use this patch until a version greater than `0.2.2` of
                # `protoc-gen-prost` is released.
                "@rules_rust//proto/prost/private/3rdparty/patches:protoc-gen-prost.patch",
            ],
        )],
        "protoc-gen-tonic": [crate.annotation(
            gen_binaries = ["protoc-gen-tonic"],
        )],
    },
    cargo_lockfile = "Cargo.Bazel.lock",
    mode = "remote",
    packages = {
        "prost": crate.spec(
            version = "0",
        ),
        "prost-types": crate.spec(
            version = "0",
        ),
        "protoc-gen-prost": crate.spec(
            version = "0",
        ),
        "protoc-gen-tonic": crate.spec(
            version = "0",
        ),
        "tonic": crate.spec(
            version = "0",
        ),
    },
    repository_name = "rules_rust_prost",
    tags = ["manual"],
)

You can then define a toolchain with the rust_prost_toolchain rule which uses the crates defined above. For example:

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_io//:prost",
    ],
)

rust_library_group(
    name = "tonic_runtime",
    deps = [
        ":prost_runtime",
        "@crates_io//:tonic",
    ],
)

rust_prost_toolchain(
    name = "prost_toolchain_impl",
    prost_plugin = "@crates_io//:protoc-gen-prost__protoc-gen-prost",
    prost_runtime = ":prost_runtime",
    prost_types = "@crates_io//:prost-types",
    proto_compiler = "@com_google_protobuf//:protoc",
    tonic_plugin = "@crates_io//: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",
)

Lastly, you must register the toolchain in your WORKSPACE file. For example:

register_toolchains("//toolchains:prost_toolchain")

Rust-Protobuf Setup

To use the Rust proto rules, add the following to your WORKSPACE file to add the external repositories for the Rust proto toolchain (in addition to the rust rules setup):

load("@rules_rust//proto/protobuf:repositories.bzl", "rust_proto_protobuf_dependencies", "rust_proto_protobuf_register_toolchains")

rust_proto_protobuf_dependencies()

rust_proto_protobuf_register_toolchains()

load("@rules_rust//proto/protobuf:transitive_repositories.bzl", "rust_proto_protobuf_transitive_repositories")

rust_proto_protobuf_transitive_repositories()

This will load the required dependencies for the rust-protobuf rules. It will also register a default toolchain for the rust_proto_library and rust_grpc_library rules.

To customize the rust_proto_library and rust_grpc_library toolchain, please see the section Customizing rust-protobuf Dependencies.

For additional information about Bazel toolchains, see here.

Customizing rust-protobuf Dependencies

These rules depend on the protobuf and the grpc crates in addition to the protobuf compiler. To obtain these crates, rust_proto_repositories imports the given crates using BUILD files generated with crate_universe.

If you want to either change the protobuf and gRPC rust compilers, or to simply use crate_universe in a more complex scenario (with more dependencies), you must redefine those dependencies.

To do this, once you've imported the needed dependencies (see our @rules_rust//proto/3rdparty/BUILD.bazel file to see the default dependencies), you need to create your own toolchain. To do so you can create a BUILD file with your toolchain definition, for example:

load("@rules_rust//proto:toolchain.bzl", "rust_proto_toolchain")

rust_proto_toolchain(
    name = "proto-toolchain-impl",
    # Path to the protobuf compiler.
    protoc = "@com_google_protobuf//:protoc",
    # Protobuf compiler plugin to generate rust gRPC stubs.
    grpc_plugin = "//3rdparty/crates:cargo_bin_protoc_gen_rust_grpc",
    # Protobuf compiler plugin to generate rust protobuf stubs.
    proto_plugin = "//3rdparty/crates:cargo_bin_protoc_gen_rust",
)

toolchain(
    name = "proto-toolchain",
    toolchain = ":proto-toolchain-impl",
    toolchain_type = "@rules_rust//proto/protobuf:toolchain_type",
)

Now that you have your own toolchain, you need to register it by inserting the following statement in your WORKSPACE file:

register_toolchains("//my/toolchains:proto-toolchain")

Finally, you might want to set the rust_deps attribute in rust_proto_library and rust_grpc_library to change the compile-time dependencies:

rust_proto_library(
    ...
    rust_deps = ["//3rdparty/crates:protobuf"],
    ...
)

rust_grpc_library(
    ...
    rust_deps = [
        "//3rdparty/crates:protobuf",
        "//3rdparty/crates:grpc",
        "//3rdparty/crates:tls_api",
        "//3rdparty/crates:tls_api_stub",
    ],
    ...
)

Note: Ideally, we would inject those dependencies from the toolchain, but due to bazelbuild/bazel#6889 all dependencies added via the toolchain ends-up being in the wrong configuration.



rust_grpc_library

rust_grpc_library(name, deps, crate_name, rust_deps, rustc_flags)

Builds a Rust library crate from a set of proto_librarys suitable for gRPC.

Example:

load("@rules_rust//proto/protobuf:defs.bzl", "rust_grpc_library")

proto_library(
    name = "my_proto",
    srcs = ["my.proto"]
)

rust_grpc_library(
    name = "rust",
    deps = [":my_proto"],
)

rust_binary(
    name = "my_service",
    srcs = ["my_service.rs"],
    deps = [":rust"],
)

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsList of proto_library dependencies that will be built. One crate for each proto_library will be created with the corresponding gRPC stubs.List of labelsrequired
crate_nameCrate name to use for this target.

This must be a valid Rust identifier, i.e. it may contain only alphanumeric characters and underscores. Defaults to the target name, with any hyphens replaced by underscores.
Stringoptional""
rust_depsThe crates the generated library depends on.List of labelsoptional[]
rustc_flagsList of compiler flags passed to rustc.

These strings are subject to Make variable expansion for predefined source/output path variables like $location, $execpath, and $rootpath. This expansion is useful if you wish to pass a generated file of arguments to rustc: @$(location //package:target).
List of stringsoptional[]

rust_prost_toolchain

rust_prost_toolchain(name, prost_opts, prost_plugin, prost_plugin_flag, prost_runtime, prost_types,
                     proto_compiler, tonic_opts, tonic_plugin, tonic_plugin_flag, tonic_runtime)

Rust Prost toolchain rule.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
prost_optsAdditional options to add to Prost.List of stringsoptional[]
prost_pluginAdditional plugins to add to Prost.Labelrequired
prost_plugin_flagProst plugin flag format. (e.g. --plugin=protoc-gen-prost=%s)Stringoptional"--plugin=protoc-gen-prost=%s"
prost_runtimeThe Prost runtime crates to use.Labelrequired
prost_typesThe Prost types crates to use.Labelrequired
proto_compilerThe protoc compiler to use. Note that this attribute is deprecated - prefer to use --incompatible_enable_proto_toolchain_resolution.LabeloptionalNone
tonic_optsAdditional options to add to Tonic.List of stringsoptional[]
tonic_pluginAdditional plugins to add to Tonic.LabeloptionalNone
tonic_plugin_flagTonic plugin flag format. (e.g. --plugin=protoc-gen-tonic=%s))Stringoptional"--plugin=protoc-gen-tonic=%s"
tonic_runtimeThe Tonic runtime crates to use.LabeloptionalNone

rust_proto_library

rust_proto_library(name, deps, crate_name, rust_deps, rustc_flags)

Builds a Rust library crate from a set of proto_librarys.

Example:

load("@rules_rust//proto/protobuf:defs.bzl", "rust_proto_library")

proto_library(
    name = "my_proto",
    srcs = ["my.proto"]
)

rust_proto_library(
    name = "rust",
    deps = [":my_proto"],
)

rust_binary(
    name = "my_proto_binary",
    srcs = ["my_proto_binary.rs"],
    deps = [":rust"],
)

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsList of proto_library dependencies that will be built. One crate for each proto_library will be created with the corresponding stubs.List of labelsrequired
crate_nameCrate name to use for this target.

This must be a valid Rust identifier, i.e. it may contain only alphanumeric characters and underscores. Defaults to the target name, with any hyphens replaced by underscores.
Stringoptional""
rust_depsThe crates the generated library depends on.List of labelsoptional[]
rustc_flagsList of compiler flags passed to rustc.

These strings are subject to Make variable expansion for predefined source/output path variables like $location, $execpath, and $rootpath. This expansion is useful if you wish to pass a generated file of arguments to rustc: @$(location //package:target).
List of stringsoptional[]

rust_prost_dependencies

rust_prost_dependencies(bzlmod)

Declares repositories needed for prost.

PARAMETERS

NameDescriptionDefault Value
bzlmodWhether bzlmod is enabled.False

RETURNS

list[struct(repo=str, is_dev_dep=bool)]: A list of the repositories defined by this macro.

rust_prost_library

rust_prost_library(name, kwargs)

A rule for generating a Rust library using Prost.

PARAMETERS

NameDescriptionDefault Value
nameThe name of the target.none
kwargsAdditional keyword arguments for the underlying rust_prost_library rule.none

rust_prost_transitive_repositories

rust_prost_transitive_repositories()

Load transitive dependencies of the @rules_rust//proto/protobuf rules.

This macro should be called immediately after the rust_protobuf_dependencies macro.

rust_proto_protobuf_dependencies

rust_proto_protobuf_dependencies(bzlmod)

Sets up dependencies for rules_rust's proto support.

PARAMETERS

NameDescriptionDefault Value
bzlmodWhether 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.

rust_proto_protobuf_register_toolchains

rust_proto_protobuf_register_toolchains(register_toolchains)

Register toolchains for proto compilation.

PARAMETERS

NameDescriptionDefault Value
register_toolchains

-

True

rust_proto_protobuf_transitive_repositories

rust_proto_protobuf_transitive_repositories()

Load transitive dependencies of the @rules_rust//proto/protobuf rules.

This macro should be called immediately after the rust_protobuf_dependencies macro.