Squashed 'third_party/rules_rust/' content from commit bf59038ca
git-subtree-dir: third_party/rules_rust
git-subtree-split: bf59038cac11798cbaef9f3bf965bad8182b97fa
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: I5a20e403203d670df467ea97dde9a4ac40339a8d
diff --git a/proto/toolchain.bzl b/proto/toolchain.bzl
new file mode 100644
index 0000000..5192436
--- /dev/null
+++ b/proto/toolchain.bzl
@@ -0,0 +1,217 @@
+# Copyright 2018 The Bazel Authors. All rights reserved.
+#
+# 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.
+
+"""Toolchain for compiling rust stubs from protobuf and gRPC."""
+
+load("//rust:defs.bzl", "rust_common")
+
+# buildifier: disable=bzl-visibility
+load("//rust/private:utils.bzl", "name_to_crate_name")
+
+def generated_file_stem(file_path):
+ """Returns the basename of a file without any extensions.
+
+ Example:
+ ```python
+ content.append("pub mod %s;" % _generated_file_stem(f))
+ ```
+
+ Args:
+ file_path (string): A path to a file
+
+ Returns:
+ string: The file stem of the filename
+ """
+ basename = file_path.rsplit("/", 2)[-1]
+ basename = name_to_crate_name(basename)
+ return basename.rsplit(".", 2)[0]
+
+def rust_generate_proto(
+ ctx,
+ transitive_descriptor_sets,
+ protos,
+ imports,
+ output_dir,
+ proto_toolchain,
+ is_grpc = False):
+ """Generate a proto compilation action.
+
+ Args:
+ ctx (ctx): rule context.
+ transitive_descriptor_sets (depset): descriptor generated by previous protobuf libraries.
+ protos (list): list of paths of protos to compile.
+ imports (depset): directory, relative to the package, to output the list of stubs.
+ output_dir (str): The basename of the output directory for for the output generated stubs
+ proto_toolchain (ToolchainInfo): The toolchain for rust-proto compilation. See `rust_proto_toolchain`
+ is_grpc (bool, optional): generate gRPC stubs. Defaults to False.
+
+ Returns:
+ list: the list of generate stubs (File)
+ """
+
+ tools = [
+ proto_toolchain.protoc,
+ proto_toolchain.proto_plugin,
+ ]
+ executable = proto_toolchain.protoc
+ args = ctx.actions.args()
+
+ if not protos:
+ fail("Protobuf compilation requested without inputs!")
+ paths = ["%s/%s" % (output_dir, generated_file_stem(i)) for i in protos.to_list()]
+ outs = [ctx.actions.declare_file(path + ".rs") for path in paths]
+ output_directory = outs[0].dirname
+
+ if is_grpc:
+ # Add grpc stubs to the list of outputs
+ grpc_files = [ctx.actions.declare_file(path + "_grpc.rs") for path in paths]
+ outs.extend(grpc_files)
+
+ # gRPC stubs is generated only if a service is defined in the proto,
+ # so we create an empty grpc module in the other case.
+ tools.append(proto_toolchain.grpc_plugin)
+ tools.append(ctx.executable._optional_output_wrapper)
+ args.add_all([f.path for f in grpc_files])
+ args.add_all([
+ "--",
+ proto_toolchain.protoc.path,
+ "--plugin=protoc-gen-grpc-rust=" + proto_toolchain.grpc_plugin.path,
+ "--grpc-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,
+ ])
+
+ args.add_joined(
+ transitive_descriptor_sets,
+ join_with = ":",
+ format_joined = "--descriptor_set_in=%s",
+ )
+
+ args.add_all(protos)
+ ctx.actions.run(
+ inputs = depset(
+ transitive = [
+ transitive_descriptor_sets,
+ imports,
+ ],
+ ),
+ outputs = outs,
+ tools = tools,
+ progress_message = "Generating Rust protobuf stubs",
+ mnemonic = "RustProtocGen",
+ executable = executable,
+ arguments = [args],
+ )
+ return outs
+
+def _rust_proto_toolchain_impl(ctx):
+ return platform_common.ToolchainInfo(
+ edition = ctx.attr.edition,
+ grpc_compile_deps = ctx.attr.grpc_compile_deps,
+ grpc_plugin = ctx.file.grpc_plugin,
+ proto_compile_deps = ctx.attr.proto_compile_deps,
+ proto_plugin = ctx.file.proto_plugin,
+ protoc = ctx.executable.protoc,
+ )
+
+# Default dependencies needed to compile protobuf stubs.
+PROTO_COMPILE_DEPS = [
+ Label("//proto/raze:protobuf"),
+]
+
+# Default dependencies needed to compile gRPC stubs.
+GRPC_COMPILE_DEPS = PROTO_COMPILE_DEPS + [
+ Label("//proto/raze:grpc"),
+ Label("//proto/raze:tls_api"),
+ Label("//proto/raze:tls_api_stub"),
+]
+
+rust_proto_toolchain = rule(
+ implementation = _rust_proto_toolchain_impl,
+ attrs = {
+ "edition": attr.string(
+ doc = "The edition used by the generated rust source.",
+ default = rust_common.default_edition,
+ ),
+ "grpc_compile_deps": attr.label_list(
+ doc = "The crates the generated grpc libraries depends on.",
+ cfg = "target",
+ default = GRPC_COMPILE_DEPS,
+ ),
+ "grpc_plugin": attr.label(
+ doc = "The location of the Rust protobuf compiler plugin to generate rust gRPC stubs.",
+ allow_single_file = True,
+ cfg = "exec",
+ default = Label("//proto:protoc_gen_rust_grpc"),
+ ),
+ "proto_compile_deps": attr.label_list(
+ doc = "The crates the generated protobuf libraries depends on.",
+ cfg = "target",
+ default = PROTO_COMPILE_DEPS,
+ ),
+ "proto_plugin": attr.label(
+ doc = "The location of the Rust protobuf compiler plugin used to generate rust sources.",
+ allow_single_file = True,
+ cfg = "exec",
+ default = Label("//proto:protoc_gen_rust"),
+ ),
+ "protoc": attr.label(
+ doc = "The location of the `protoc` binary. It should be an executable target.",
+ executable = True,
+ cfg = "exec",
+ default = Label("@com_google_protobuf//:protoc"),
+ ),
+ },
+ doc = """\
+Declares a Rust Proto toolchain for use.
+
+This is used to configure proto compilation and can be used to set different \
+protobuf compiler plugin.
+
+Example:
+
+Suppose a new nicer gRPC plugin has came out. The new plugin can be \
+used in Bazel by defining a new toolchain definition and declaration:
+
+```python
+load('@rules_rust//proto:toolchain.bzl', 'rust_proto_toolchain')
+
+rust_proto_toolchain(
+ name="rust_proto_impl",
+ grpc_plugin="@rust_grpc//:grpc_plugin",
+ grpc_compile_deps=["@rust_grpc//:grpc_deps"],
+)
+
+toolchain(
+ name="rust_proto",
+ exec_compatible_with = [
+ "@platforms//cpu:cpuX",
+ ],
+ target_compatible_with = [
+ "@platforms//cpu:cpuX",
+ ],
+ toolchain = ":rust_proto_impl",
+)
+```
+
+Then, either add the label of the toolchain rule to register_toolchains in the WORKSPACE, or pass \
+it to the `--extra_toolchains` flag for Bazel, and it will be used.
+
+See @rules_rust//proto:BUILD for examples of defining the toolchain.
+""",
+)