From 20d33f01a2086a8990b1595480e34e6cce6e7517 Mon Sep 17 00:00:00 2001 From: Damien Martin-Guillerez Date: Fri, 1 Jun 2018 22:30:12 +0200 Subject: [PATCH] Add Rust support --- README.md | 48 +++---- WORKSPACE | 25 +++- examples/helloworld/rust/BUILD | 12 ++ examples/helloworld/rust/greeter_client/BUILD | 8 ++ .../rust/greeter_client/greeter_client.rs | 15 +++ examples/helloworld/rust/greeter_server/BUILD | 8 ++ .../rust/greeter_server/greeter_server.rs | 33 +++++ examples/proto/BUILD | 7 + protobuf/internal/proto_compile.bzl | 13 ++ protobuf/internal/proto_language.bzl | 2 + rust/BUILD | 14 ++ rust/README.md | 86 ++++++++++++ rust/deps.bzl | 96 ++++++++++++++ rust/rules.bzl | 123 ++++++++++++++++++ 14 files changed, 464 insertions(+), 26 deletions(-) create mode 100644 examples/helloworld/rust/BUILD create mode 100644 examples/helloworld/rust/greeter_client/BUILD create mode 100644 examples/helloworld/rust/greeter_client/greeter_client.rs create mode 100644 examples/helloworld/rust/greeter_server/BUILD create mode 100644 examples/helloworld/rust/greeter_server/greeter_server.rs create mode 100644 rust/BUILD create mode 100644 rust/README.md create mode 100644 rust/deps.bzl create mode 100644 rust/rules.bzl diff --git a/README.md b/README.md index fd01aa9d..53cf18cb 100644 --- a/README.md +++ b/README.md @@ -36,20 +36,21 @@ of this project are to: ### Rules -| Language | Compile 1 | Build 2 | gRPC 3 | -| ---------------------------: | -----------: | --------: | -------- | -| [C++](cpp) | [cc_proto_compile](cpp#cc_proto_compile) | [cc_proto_library](cpp#cc_proto_library) [v3.4.0](https://github.com/grpc/grpc/releases/tag/v1.6.1) | [v1.6.1](https://github.com/grpc/grpc/releases/tag/v1.6.1) | -| [C#](csharp) | [csharp_proto_compile](csharp#csharp_proto_compile) | [csharp_proto_library](csharp#csharp_proto_library) | [1.0.0](https://www.nuget.org/packages/Grpc/) | -| [Closure](closure) | [closure_proto_compile](closure#closure_proto_compile) | [closure_proto_library](closure#closure_proto_library) | | -| [Go](go) | [go_proto_compile](go#go_proto_compile) | [go_proto_library](go#go_proto_library) | [v1.6.0](https://github.com/grpc/grpc-go/releases/tag/v1.6.0) | -| [Go (gogo)](gogo) | [gogo_proto_compile](gogo#gogo_proto_compile) | [gogo_proto_library](gogo#gogo_proto_library) | [fb8a35](https://github.com/gogo/protobuf/commit/fb8a359905af6e2b6517cccda0ba25915322ee88) | -| [gRPC gateway](grpc_gateway) | [grpc_gateway_proto_compile](grpc_gateway#grpc_gateway_proto_compile)
[grpc_gateway_swagger_compile](grpc_gateway#grpc_gateway_swagger_compile) | [grpc_gateway_proto_library](grpc_gateway#grpc_gateway_proto_library)
[grpc_gateway_binary](grpc_gateway#grpc_gateway_binary) | [v1.2.2+ (f2862b)](https://github.com/grpc-ecosystem/grpc-gateway/commit/f2862b476edcef83412c7af8687c9cd8e4097c0f) | -| [Java](java) | [java_proto_compile](java#java_proto_compile) | [java_proto_library](java#java_proto_library) | [v1.7.0](https://github.com/grpc/grpc-java/releases/tag/v1.7.0) | -| [Node](node) | [node_proto_compile](node#node_proto_compile) | [node_proto_library](node#node_proto_library) | [1.6.0](https://www.npmjs.com/package/grpc) | -| [Objective-C](objc) | [objc_proto_compile](objc#objc_proto_compile) | [objc_proto_library](objc#objc_proto_library) 4 | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) | -| [Python](python) | [py_proto_compile](python#py_proto_compile) | [py_proto_library](python#py_proto_library) | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) | -| [Ruby](ruby) | [ruby_proto_compile](ruby#ruby_proto_compile) | | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) | -| Custom [proto_language](protobuf#proto_language) | [proto_compile](protobuf#proto_compile) | | | +| Language | Compile 1 | Build 2 | gRPC 3 | +| -----------------------------------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------: | --------------------------------------------------------------------------------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------ | +| [C++](cpp) | [cc_proto_compile](cpp#cc_proto_compile) | [cc_proto_library](cpp#cc_proto_library) [v3.4.0](https://github.com/grpc/grpc/releases/tag/v1.6.1) | [v1.6.1](https://github.com/grpc/grpc/releases/tag/v1.6.1) | +| [C#](csharp) | [csharp_proto_compile](csharp#csharp_proto_compile) | [csharp_proto_library](csharp#csharp_proto_library) | [1.0.0](https://www.nuget.org/packages/Grpc/) | +| [Closure](closure) | [closure_proto_compile](closure#closure_proto_compile) | [closure_proto_library](closure#closure_proto_library) | | +| [Go](go) | [go_proto_compile](go#go_proto_compile) | [go_proto_library](go#go_proto_library) | [v1.6.0](https://github.com/grpc/grpc-go/releases/tag/v1.6.0) | +| [Go (gogo)](gogo) | [gogo_proto_compile](gogo#gogo_proto_compile) | [gogo_proto_library](gogo#gogo_proto_library) | [fb8a35](https://github.com/gogo/protobuf/commit/fb8a359905af6e2b6517cccda0ba25915322ee88) | +| [gRPC gateway](grpc_gateway) | [grpc_gateway_proto_compile](grpc_gateway#grpc_gateway_proto_compile)
[grpc_gateway_swagger_compile](grpc_gateway#grpc_gateway_swagger_compile) | [grpc_gateway_proto_library](grpc_gateway#grpc_gateway_proto_library)
[grpc_gateway_binary](grpc_gateway#grpc_gateway_binary) | [v1.2.2+ (f2862b)](https://github.com/grpc-ecosystem/grpc-gateway/commit/f2862b476edcef83412c7af8687c9cd8e4097c0f) | +| [Java](java) | [java_proto_compile](java#java_proto_compile) | [java_proto_library](java#java_proto_library) | [v1.7.0](https://github.com/grpc/grpc-java/releases/tag/v1.7.0) | +| [Node](node) | [node_proto_compile](node#node_proto_compile) | [node_proto_library](node#node_proto_library) | [1.6.0](https://www.npmjs.com/package/grpc) | +| [Objective-C](objc) | [objc_proto_compile](objc#objc_proto_compile) | [objc_proto_library](objc#objc_proto_library) 4 | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) | +| [Python](python) | [py_proto_compile](python#py_proto_compile) | [py_proto_library](python#py_proto_library) | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) | +| [Ruby](ruby) | [ruby_proto_compile](ruby#ruby_proto_compile) | | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) | +| [Rust](rust) | [rust_proto_compile](rust#rust_proto_compile) | | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) | +| Custom [proto_language](protobuf#proto_language) | [proto_compile](protobuf#proto_compile) | | | > Refer to [`DEPENDENCIES.md`](DEPENDENCIES.md) for a more detailed > summary of workspace dependencies / versions. @@ -101,15 +102,16 @@ go_proto_repositories() Several languages have other `rules_*` dependencies that you'll need to load before the `*_proto_repositories()` function is invoked: -| Language | Requires | -| ---: | :--- | -| closure_proto_repositories | [rules_closure](https://github.com/bazelbuild/rules_closure) | -| csharp_proto_repositories | [rules_dotnet](https://github.com/bazelbuild/rules_dotnet) | -| go_proto_repositories | [rules_go](https://github.com/bazelbuild/rules_go) | -| gogo_proto_repositories | [rules_go](https://github.com/bazelbuild/rules_go) | -| grpc_gateway_proto_repositories | [rules_go](https://github.com/bazelbuild/rules_go) | -| node_proto_repositories | [rules_node](https://github.com/pubref/rules_node) | -| py_proto_repositories 1 | [rules_python](https://github.com/bazelbuild/rules_python) | +| Language | Requires | +| ---------------------------------: | :----------------------------------------------------------- | +| closure_proto_repositories | [rules_closure](https://github.com/bazelbuild/rules_closure) | +| csharp_proto_repositories | [rules_dotnet](https://github.com/bazelbuild/rules_dotnet) | +| go_proto_repositories | [rules_go](https://github.com/bazelbuild/rules_go) | +| gogo_proto_repositories | [rules_go](https://github.com/bazelbuild/rules_go) | +| grpc_gateway_proto_repositories | [rules_go](https://github.com/bazelbuild/rules_go) | +| node_proto_repositories | [rules_node](https://github.com/pubref/rules_node) | +| py_proto_repositories 1 | [rules_python](https://github.com/bazelbuild/rules_python) | +| rust_proto_repositories | [rules_rust](https://github.com/bazelbuild/rules_rust) | > 1 Only needed for python grpc support. diff --git a/WORKSPACE b/WORKSPACE index 5b95929b..574a46f3 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -88,19 +88,34 @@ github_archive( sha256 = "7d06126d0d10ea8e63cc7eaf774d9ecebcd9583094ee8e93b0035da659eab5c1", ) -load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories", "pip_import") +load("@io_bazel_rules_python//python:pip.bzl", "pip_import", "pip_repositories") pip_repositories() pip_import( - name = "pip_grpcio", - requirements = "//python:requirements.txt", + name = "pip_grpcio", + requirements = "//python:requirements.txt", ) load("@pip_grpcio//:requirements.bzl", pip_grpcio_install = "pip_install") pip_grpcio_install() +# ================================================================ +# rust_proto_library support requires rules_rust (HEAD) +# ================================================================ + +github_archive( + name = "io_bazel_rules_rust", + commit = "67503c5bff487136d12fc530e3760ac7b31d330b", + org = "bazelbuild", + repo = "rules_rust", + sha256 = "6725a05ab1aac5aecb8ab20d1d86af30818bf8e657ee80ea2eba57bf73f6d676", +) + +load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repositories") + +rust_repositories() # ================================================================ # Specific Languages Support @@ -156,3 +171,7 @@ py_proto_repositories() load("//ruby:rules.bzl", "ruby_proto_repositories") ruby_proto_repositories() + +load("//rust:rules.bzl", "rust_proto_repositories") + +rust_proto_repositories() diff --git a/examples/helloworld/rust/BUILD b/examples/helloworld/rust/BUILD new file mode 100644 index 00000000..ef66a9a4 --- /dev/null +++ b/examples/helloworld/rust/BUILD @@ -0,0 +1,12 @@ +load("//rust:rules.bzl", "rust_proto_library") + +rust_proto_library( + name = "helloworld", + proto_deps = [ + "//examples/proto:rust", + ], + protos = ["//examples/helloworld/proto:protos"], + verbose = 0, + visibility = ["//examples/helloworld/rust:__subpackages__"], + with_grpc = True, +) diff --git a/examples/helloworld/rust/greeter_client/BUILD b/examples/helloworld/rust/greeter_client/BUILD new file mode 100644 index 00000000..dff0ca9d --- /dev/null +++ b/examples/helloworld/rust/greeter_client/BUILD @@ -0,0 +1,8 @@ +load("@io_bazel_rules_rust//rust:rust.bzl", "rust_binary") +load("//rust:rules.bzl", "GRPC_COMPILE_DEPS", "rust_proto_library") + +rust_binary( + name = "greeter_client", + srcs = ["greeter_client.rs"], + deps = ["//examples/helloworld/rust:helloworld"] + GRPC_COMPILE_DEPS, +) diff --git a/examples/helloworld/rust/greeter_client/greeter_client.rs b/examples/helloworld/rust/greeter_client/greeter_client.rs new file mode 100644 index 00000000..6e230eba --- /dev/null +++ b/examples/helloworld/rust/greeter_client/greeter_client.rs @@ -0,0 +1,15 @@ +extern crate grpc; +extern crate helloworld; + +use std::env; + +use helloworld::*; + +fn main() { + let name = env::args().nth(1).unwrap_or("world".to_owned()); + let client = GreeterClient::new_plain("::1", 50051, Default::default()).unwrap(); + let mut req = HelloRequest::new(); + req.set_name(name); + let resp = client.say_hello(grpc::RequestOptions::new(), req); + println!("{:?}", resp.wait()); +} diff --git a/examples/helloworld/rust/greeter_server/BUILD b/examples/helloworld/rust/greeter_server/BUILD new file mode 100644 index 00000000..13bd2128 --- /dev/null +++ b/examples/helloworld/rust/greeter_server/BUILD @@ -0,0 +1,8 @@ +load("@io_bazel_rules_rust//rust:rust.bzl", "rust_binary") +load("//rust:rules.bzl", "GRPC_COMPILE_DEPS", "rust_proto_library") + +rust_binary( + name = "greeter_server", + srcs = ["greeter_server.rs"], + deps = ["//examples/helloworld/rust:helloworld"] + GRPC_COMPILE_DEPS, +) diff --git a/examples/helloworld/rust/greeter_server/greeter_server.rs b/examples/helloworld/rust/greeter_server/greeter_server.rs new file mode 100644 index 00000000..7fc2dc97 --- /dev/null +++ b/examples/helloworld/rust/greeter_server/greeter_server.rs @@ -0,0 +1,33 @@ +extern crate helloworld; +extern crate grpc; +extern crate tls_api_stub; + +use std::thread; + +use helloworld::*; + +struct GreeterImpl; + +impl Greeter for GreeterImpl { + fn say_hello(&self, _m: grpc::RequestOptions, req: HelloRequest) -> grpc::SingleResponse { + let mut r = HelloReply::new(); + let name = if req.get_name().is_empty() { "world" } else { req.get_name() }; + println!("greeting request from {}", name); + r.set_message(format!("Hello {}", name)); + grpc::SingleResponse::completed(r) + } +} + +fn main() { + let mut server = grpc::ServerBuilder::::new(); + server.http.set_port(50051); + server.add_service(GreeterServer::new_service_def(GreeterImpl)); + server.http.set_cpu_pool_threads(4); + let _server = server.build().expect("server"); + + println!("greeter server started on port 50051"); + + loop { + thread::park(); + } +} diff --git a/examples/proto/BUILD b/examples/proto/BUILD index 21617e03..f9b1686b 100644 --- a/examples/proto/BUILD +++ b/examples/proto/BUILD @@ -10,6 +10,7 @@ load("//objc:rules.bzl", "objc_proto_compile") load("//python:rules.bzl", "py_proto_library") load("//protobuf:rules.bzl", "proto_compile") load("//ruby:rules.bzl", "ruby_proto_compile") +load("//rust:rules.bzl", "rust_proto_library") filegroup( name = "protos", @@ -69,6 +70,12 @@ ruby_proto_compile( with_grpc = False, ) +rust_proto_library( + name = "rust", + protos = [":protos"], + with_grpc = False, +) + # This conflicts with outputs from other rules here but demonstrates # how to generate multiple language outputs simultaneously. # diff --git a/protobuf/internal/proto_compile.bzl b/protobuf/internal/proto_compile.bzl index 21ccdbe1..c02f8c2c 100644 --- a/protobuf/internal/proto_compile.bzl +++ b/protobuf/internal/proto_compile.bzl @@ -210,6 +210,8 @@ def _build_output_files(run, builder): build_package_path = generated_path + "/" + build_package_path path = _get_relative_dirname(run, build_package_path, file) + if run.lang.output_to_libsubdir: + path.append(ctx.label.name) for ext in exts: temppath = list(path) @@ -236,6 +238,15 @@ def _build_output_libdir(run, builder): _build_output_files(run, builder) +def _build_output_libsubdir(run, builder): + # This is currently rust-specific, to output to a specific crate. + ctx = run.ctx + execdir = run.data.execdir + name = run.lang.name + builder[name + "_outdir"] = _get_offset_path(execdir, run.data.descriptor_set.dirname) + "/" + ctx.label.name + _build_output_files(run, builder) + + def _build_descriptor_set(data, builder): """Build a list of files we expect to be generated.""" builder["args"] += ["--descriptor_set_out=" + _get_offset_path(data.execdir, data.descriptor_set.path)] @@ -687,6 +698,8 @@ def _proto_compile_impl(ctx): _build_output_library(run, builder) elif run.lang.output_to_libdir: _build_output_libdir(run, builder) + elif run.lang.output_to_libsubdir: + _build_output_libsubdir(run, builder) else: _build_output_files(run, builder) if run.lang.go_prefix or ctx.attr.go_importpath: # golang-specific diff --git a/protobuf/internal/proto_language.bzl b/protobuf/internal/proto_language.bzl index 2abd8a51..46d58b65 100644 --- a/protobuf/internal/proto_language.bzl +++ b/protobuf/internal/proto_language.bzl @@ -11,6 +11,7 @@ def _proto_language_impl(ctx): output_to_jar = ctx.attr.output_to_jar, output_to_library = ctx.attr.output_to_library, output_to_libdir = ctx.attr.output_to_libdir, + output_to_libsubdir = ctx.attr.output_to_libsubdir, output_file_style = ctx.attr.output_file_style, supports_pb = ctx.attr.supports_pb, pb_plugin_implements_grpc = ctx.attr.pb_plugin_implements_grpc, @@ -45,6 +46,7 @@ proto_language_attrs = { "output_to_jar": attr.bool(), "output_to_library": attr.bool(), "output_to_libdir": attr.bool(), + "output_to_libsubdir": attr.bool(), "output_file_style": attr.string(), "supports_pb": attr.bool(default = True), diff --git a/rust/BUILD b/rust/BUILD new file mode 100644 index 00000000..b35b9917 --- /dev/null +++ b/rust/BUILD @@ -0,0 +1,14 @@ +package(default_visibility = ["//visibility:public"]) + +load("//protobuf:rules.bzl", "proto_language") + +proto_language( + name = "rust", + grpc_file_extensions = ["_grpc.rs"], + grpc_plugin = "@com_github_stepancheg_grpc_rust//:protoc_gen_rust_grpc", + output_to_libsubdir = True, + pb_file_extensions = [".rs"], + pb_plugin = "@com_github_stepancheg_rust_protobuf//:protoc_gen_rust", + pb_plugin_implements_grpc = False, + supports_grpc = True, +) diff --git a/rust/README.md b/rust/README.md new file mode 100644 index 00000000..880e5b0e --- /dev/null +++ b/rust/README.md @@ -0,0 +1,86 @@ +# Rust Rules + +| Rule | Description | +| --------------------------------------------------: | :------------------------------------------- | +| [rust_proto_repositories](#rust_proto_repositories) | Load WORKSPACE dependencies. | +| [rust_proto_compile](#rust_proto_compile) | Generate protobuf source files. | +| [rust_proto_library](#rust_proto_library) | Generate and compiles protobuf source files. | + +## rust\_proto\_repositories + +Enable Rust support by loading the dependencies in your workspace. + +> IMPORTANT: Rust currently requires a custom branch of [rules_rust](https://github.com/bazelbuild/rules_rust) having +> support for Rust 1.26. + +```python +http_repository( + name = "io_bazel_rules_rust", + urls = ["https://github.com/damienmg/rules_rust/archive/67503c5bff487136d12fc530e3760ac7b31d330b.tar.gz"], + strip_prefix = "rules_rust-67503c5bff487136d12fc530e3760ac7b31d330b", + sha256 = "6725a05ab1aac5aecb8ab20d1d86af30818bf8e657ee80ea2eba57bf73f6d676", +) + +load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repositories") +rust_repositories() +load("@org_pubref_rules_protobuf//rust:rules.bzl", "rust_proto_repositories") +rust_proto_repositories() +``` + +## rust\_proto\_compile + +This is a thin wrapper over the +[proto_compile](../protobuf#proto_compile) rule having language +`@org_pubref_rules_protobuf//rust`. + +```python +load("@org_pubref_rules_protobuf//rust:rules.bzl", "rust_proto_compile") + +rust_proto_compile( + name = "protos", + protos = ["message.proto"], + with_grpc = True, +) +``` + +```sh +$ bazel build :protos +Target //:protos up-to-date: + bazel-genfiles/protos.rs +``` + +## rust\_proto\_library + +Pass the set of protobuf source files to the `protos` attribute. + +```python +load("@org_pubref_rules_protobuf//rust:rules.bzl", "rust_proto_library") + +rust_proto_library( + name = "helloworld", + protos = ["message.proto"], + with_grpc = True, +) +``` + +```sh +$ bazel build :helloworld +Target //:helloworld up-to-date: + bazel-bin/libhelloworld--2112777365.rlib +``` + +To get the list of required compile-time dependencies in other contexts for grpc-related code, load the list from the rules.bzl file: + +```python +load("@org_pubref_rules_protobuf//rust:rules.bzl", "GRPC_COMPILE_DEPS") + +rust_library( + name = "mylib", + srcs = ['mylib.rs'], + deps = [ + ":protolib" + ] + GRPC_COMPILE_DEPS, +) +``` + +Consult source files in the [examples/helloworld/rust](../examples/helloworld/rust) directory for additional information. diff --git a/rust/deps.bzl b/rust/deps.bzl new file mode 100644 index 00000000..0fb10891 --- /dev/null +++ b/rust/deps.bzl @@ -0,0 +1,96 @@ +_RUST_PROTOBUF_VERSION = "2.0.1" +_RUST_PROTOBUF_SHA256 = "9fb966a5bba4d0fd4926356d6374ef5f7437cfe4a2943d60e3e8073ac066419d" +_RUST_GRPC_VERSION = "0.4.0" +_RUST_GRPC_SHA256 = "a298d14957043bd9d631ae3928b0678895f57d685d5054ad8dc154778be5f50a" + +PROTOBUF_BUILD_FILE = """ +package(default_visibility = ["//visibility:public"]) + +load("@io_bazel_rules_rust//rust:rust.bzl", "rust_binary", "rust_library") + +VERSION = "%s" +rust_library( + name = "protobuf", + srcs = glob(["protobuf/src/**/*.rs"]), + version = VERSION, + crate_features = ["bytes"], + deps = ["@raze__bytes__0_4_8//:bytes"] +) + +rust_library( + name = "protobuf_codegen", + srcs = glob(["protobuf-codegen/src/*.rs"]), + version = VERSION, + deps = [":protobuf"], +) + +rust_binary( + name = "protoc_gen_rust", + srcs = ["protobuf-codegen/src/bin/protoc-gen-rust.rs"], + version = VERSION, + deps = [":protobuf_codegen"], +) +""" % _RUST_PROTOBUF_VERSION + +GRPC_BUILD_FILE = """ +package(default_visibility = ["//visibility:public"]) + +load("@io_bazel_rules_rust//rust:rust.bzl", "rust_binary", "rust_library") + +VERSION="%s" + +rust_library( + name = "grpc", + srcs = glob(["grpc/src/**/*.rs"]), + version = VERSION, + deps = [ + "@com_github_stepancheg_rust_protobuf//:protobuf", + "@raze__base64__0_9_1//:base64", + "@raze__bytes__0_4_8//:bytes", + "@raze__env_logger__0_5_10//:env_logger", + "@raze__futures__0_1_21//:futures", + "@raze__futures_cpupool__0_1_8//:futures_cpupool", + "@raze__httpbis__0_6_1//:httpbis", + "@raze__log__0_4_1//:log", + "@raze__tls_api__0_1_19//:tls_api", + "@raze__tls_api_stub__0_1_19//:tls_api_stub", + "@raze__tokio_core__0_1_17//:tokio_core", + "@raze__tokio_io__0_1_6//:tokio_io", + "@raze__tokio_tls_api__0_1_19//:tokio_tls_api", +], +) + +rust_library( + name = "grpc_compiler", + srcs = glob(["grpc-compiler/src/*.rs"]), + deps = [ + "@com_github_stepancheg_rust_protobuf//:protobuf", + "@com_github_stepancheg_rust_protobuf//:protobuf_codegen", + ], + version = VERSION, +) + +rust_binary( + name = "protoc_gen_rust_grpc", + srcs = glob(["grpc-compiler/src/bin/*.rs"]), + deps = [":grpc_compiler"], + version = VERSION, +) +""" % _RUST_GRPC_VERSION + +DEPS = { + "com_github_stepancheg_rust_protobuf": { + "rule": "new_http_archive", + "sha256": _RUST_PROTOBUF_SHA256, + "strip_prefix": "rust-protobuf-%s" % _RUST_PROTOBUF_VERSION, + "urls": ["https://github.com/stepancheg/rust-protobuf/archive/v%s.tar.gz" % _RUST_PROTOBUF_VERSION], + "build_file_content": PROTOBUF_BUILD_FILE, + }, + "com_github_stepancheg_grpc_rust": { + "rule": "new_http_archive", + "sha256": _RUST_GRPC_SHA256, + "strip_prefix": "grpc-rust-%s" % _RUST_GRPC_VERSION, + "urls": ["https://github.com/stepancheg/grpc-rust/archive/v%s.tar.gz" % _RUST_GRPC_VERSION], + "build_file_content": GRPC_BUILD_FILE, + }, +} diff --git a/rust/rules.bzl b/rust/rules.bzl new file mode 100644 index 00000000..3a568daf --- /dev/null +++ b/rust/rules.bzl @@ -0,0 +1,123 @@ +load("@io_bazel_rules_rust//rust:rust.bzl", "rust_library") +load("//protobuf:rules.bzl", "proto_compile", "proto_language_deps", "proto_repositories") +load("//rust:deps.bzl", "DEPS") +load("//rust:crates.bzl", "raze_fetch_remote_crates") + +def rust_proto_repositories( + lang_deps = DEPS, + lang_requires = DEPS.keys(), + **kwargs): + raze_fetch_remote_crates() + proto_repositories( + lang_deps = lang_deps, + lang_requires = lang_requires, + **kwargs + ) + +def rust_proto_compile(langs = [str(Label("//rust"))], **kwargs): + proto_compile(langs = langs, **kwargs) + +PB_COMPILE_DEPS = [ + "@com_github_stepancheg_rust_protobuf//:protobuf", +] + +GRPC_COMPILE_DEPS = PB_COMPILE_DEPS + [ + "@com_github_stepancheg_grpc_rust//:grpc", + "@raze__tls_api__0_1_19//:tls_api", + "@raze__tls_api_stub__0_1_19//:tls_api_stub", +] + +def _basename(f): + return f.basename[:-len(f.extension) - 1] + +def _gen_lib_impl(ctx): + content = ["extern crate protobuf;"] + if ctx.attr.grpc: + content.append("extern crate grpc;") + content.append("extern crate tls_api;") + for dep in ctx.attr.deps: + content.append("extern crate %s;" % dep.label.name) + content.append("use %s::*;" % dep.label.name) + for f in ctx.files.files: + content.append("pub mod %s;" % _basename(f)) + content.append("pub use %s::*;" % _basename(f)) + if ctx.attr.grpc: + content.append("pub mod %s_grpc;" % _basename(f)) + content.append("pub use %s_grpc::*;" % _basename(f)) + ctx.actions.write( + ctx.outputs.out, + "\n".join(content), + False, + ) + +_gen_lib = rule( + implementation = _gen_lib_impl, + attrs = { + "files": attr.label_list(allow_files = True), + "deps": attr.label_list(), + "grpc": attr.bool(default = True), + }, + outputs = {"out": "%{name}.rs"}, + output_to_genfiles = True, # For compatibility with proto_compile. +) + +def rust_proto_library( + name, + langs = [str(Label("//rust"))], + protos = [], + imports = [], + inputs = [], + proto_deps = [], + output_to_workspace = False, + protoc = None, + pb_plugin = None, + pb_options = [], + grpc_plugin = None, + grpc_options = [], + proto_compile_args = {}, + with_grpc = False, + srcs = [], + deps = [], + verbose = 0, + **kwargs): + proto_compile_args += { + "name": name + "_pb", + "protos": protos, + "deps": [dep + "_pb" for dep in proto_deps], + "langs": langs, + "imports": imports, + "inputs": inputs, + "pb_options": pb_options, + "grpc_options": grpc_options, + "output_to_workspace": output_to_workspace, + "verbose": verbose, + "with_grpc": with_grpc, + } + + if protoc: + proto_compile_args["protoc"] = protoc + if pb_plugin: + proto_compile_args["pb_plugin"] = pb_plugin + if grpc_plugin: + proto_compile_args["grpc_plugin"] = grpc_plugin + + proto_compile(**proto_compile_args) + + _gen_lib( + name = name + "_pb/lib", + files = protos, + deps = proto_deps, + grpc = with_grpc + ) + + if with_grpc: + compile_deps = GRPC_COMPILE_DEPS + else: + compile_deps = PB_COMPILE_DEPS + + rust_library( + name = name, + srcs = srcs + [name + "_pb", name + "_pb/lib"], + deps = depset(deps + compile_deps + proto_deps).to_list(), + **kwargs + )