diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index fe4399dacb..c412e2fa11 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -52,6 +52,10 @@ load("//test:deps.bzl", "rules_rust_test_deps") rules_rust_test_deps() +load("//test:deps_transitive.bzl", "rules_rust_test_deps_transitive") + +rules_rust_test_deps_transitive() + # --- end stardoc load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index f97a034a36..5408d9a5bc 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -122,7 +122,6 @@ PAGES = dict([ "rust_proto_transitive_repositories", "rust_proto_toolchain", "rust_prost_library", - "rust_tonic_library", ], ), page( diff --git a/docs/flatten.md b/docs/flatten.md index 9997b809d5..08ed04a2c5 100644 --- a/docs/flatten.md +++ b/docs/flatten.md @@ -44,7 +44,6 @@ * [rust_stdlib_filegroup](#rust_stdlib_filegroup) * [rust_test](#rust_test) * [rust_test_suite](#rust_test_suite) -* [rust_tonic_library](#rust_tonic_library) * [rust_toolchain](#rust_toolchain) * [rust_toolchain_repository](#rust_toolchain_repository) * [rust_toolchain_repository_proxy](#rust_toolchain_repository_proxy) @@ -2017,25 +2016,6 @@ rust_test_suite( | kwargs | Additional keyword arguments for the underyling [rust_test](#rust_test) targets. The tags argument is also passed to the generated test_suite target. | none | - - -## rust_tonic_library - -
-rust_tonic_library(name, kwargs)
-
- -A rule for generating a Rust library using Prost and Tonic. - -**PARAMETERS** - - -| Name | Description | Default Value | -| :------------- | :------------- | :------------- | -| name | The name of the target. | none | -| kwargs | Additional keyword arguments for the underlying rust_tonic_library rule. | none | - - ## rust_toolchain_repository diff --git a/docs/rust_proto.md b/docs/rust_proto.md index 1e0b0418cb..5453e467e0 100644 --- a/docs/rust_proto.md +++ b/docs/rust_proto.md @@ -7,7 +7,6 @@ * [rust_proto_transitive_repositories](#rust_proto_transitive_repositories) * [rust_proto_toolchain](#rust_proto_toolchain) * [rust_prost_library](#rust_prost_library) -* [rust_tonic_library](#rust_tonic_library) ## Overview @@ -15,8 +14,7 @@ These build rules are used for building [protobufs][protobuf]/[gRPC][grpc] in [R There are two rule sets. The first ruleset defines the `rust_proto_library` and `rust_grpc_library` rules which generate Rust code using the [`rust-protobuf`] dependencies. The second ruleset defines -the `rust_prost_library` and `rust_tonic_library` rules which generate Rust code using the [`prost`] -and [`tonic`] dependencies respectively. +the `rust_prost_library` which generates Rust code using the [`prost`] and [`tonic`] dependencies. [rust]: http://www.rust-lang.org/ [protobuf]: https://developers.google.com/protocol-buffers/ @@ -427,22 +425,3 @@ This macro should be called immediately after the `rust_proto_repositories` macr - - -## rust_tonic_library - -
-rust_tonic_library(name, kwargs)
-
- -A rule for generating a Rust library using Prost and Tonic. - -**PARAMETERS** - - -| Name | Description | Default Value | -| :------------- | :------------- | :------------- | -| name | The name of the target. | none | -| kwargs | Additional keyword arguments for the underlying rust_tonic_library rule. | none | - - diff --git a/docs/rust_proto.vm b/docs/rust_proto.vm index b2dce936be..967b2aedd7 100644 --- a/docs/rust_proto.vm +++ b/docs/rust_proto.vm @@ -4,8 +4,7 @@ These build rules are used for building [protobufs][protobuf]/[gRPC][grpc] in [R There are two rule sets. The first ruleset defines the `rust_proto_library` and `rust_grpc_library` rules which generate Rust code using the [`rust-protobuf`] dependencies. The second ruleset defines -the `rust_prost_library` and `rust_tonic_library` rules which generate Rust code using the [`prost`] -and [`tonic`] dependencies respectively. +the `rust_prost_library` which generates Rust code using the [`prost`] and [`tonic`] dependencies. [rust]: http://www.rust-lang.org/ [protobuf]: https://developers.google.com/protocol-buffers/ diff --git a/docs/symbols.bzl b/docs/symbols.bzl index d1a8d65662..141dc60a5d 100644 --- a/docs/symbols.bzl +++ b/docs/symbols.bzl @@ -32,7 +32,6 @@ load( _rust_grpc_library = "rust_grpc_library", _rust_prost_library = "rust_prost_library", _rust_proto_library = "rust_proto_library", - _rust_tonic_library = "rust_tonic_library", ) load( "@rules_rust//proto:repositories.bzl", @@ -127,7 +126,6 @@ rust_doc_test = _rust_doc_test rust_proto_library = _rust_proto_library rust_grpc_library = _rust_grpc_library rust_prost_library = _rust_prost_library -rust_tonic_library = _rust_tonic_library rust_bindgen = _rust_bindgen rust_bindgen_dependencies = _rust_bindgen_dependencies diff --git a/proto/defs.bzl b/proto/defs.bzl index cc38b48b4b..12d4bd3fb8 100644 --- a/proto/defs.bzl +++ b/proto/defs.bzl @@ -3,7 +3,6 @@ load( "//proto/prost:defs.bzl", _rust_prost_library = "rust_prost_library", - _rust_tonic_library = "rust_tonic_library", ) load( ":proto.bzl", @@ -15,4 +14,3 @@ rust_proto_library = _rust_proto_library rust_grpc_library = _rust_grpc_library rust_prost_library = _rust_prost_library -rust_tonic_library = _rust_tonic_library diff --git a/proto/prost/defs.bzl b/proto/prost/defs.bzl index 56a45c5ad5..401f10644d 100644 --- a/proto/prost/defs.bzl +++ b/proto/prost/defs.bzl @@ -4,7 +4,6 @@ load( "//proto/prost/private:prost.bzl", _rust_prost_library = "rust_prost_library", _rust_prost_toolchain = "rust_prost_toolchain", - _rust_tonic_library = "rust_tonic_library", ) def rust_prost_library(name, **kwargs): @@ -30,27 +29,4 @@ def rust_prost_library(name, **kwargs): **kwargs ) -def rust_tonic_library(name, **kwargs): - """A rule for generating a Rust library using Prost and Tonic. - - Args: - name (str): The name of the target. - **kwargs (dict): Additional keyword arguments for the underlying - `rust_tonic_library` rule. - """ - - # Clippy and Rustfmt will attempt to run on these targets. - # This is not correct and likely a bug in target detection. - tags = kwargs.pop("tags", []) - if "no-clippy" not in tags: - tags.append("no-clippy") - if "no-rustfmt" not in tags: - tags.append("no-rustfmt") - - _rust_tonic_library( - name = name, - tags = tags, - **kwargs - ) - rust_prost_toolchain = _rust_prost_toolchain diff --git a/proto/prost/private/prost.bzl b/proto/prost/private/prost.bzl index f41e4fe7ff..e2b6c39f37 100644 --- a/proto/prost/private/prost.bzl +++ b/proto/prost/private/prost.bzl @@ -8,16 +8,22 @@ load("//rust/private:rustc.bzl", "rustc_compile_action") # buildifier: disable=bzl-visibility load("//rust/private:utils.bzl", "can_build_metadata") -load(":providers.bzl", "ProstProtoInfo", "TonicProtoInfo") RUST_EDITION = "2021" TOOLCHAIN_TYPE = "@rules_rust//proto/prost:toolchain_type" -def _create_proto_lang_toolchain(ctx, prost_toolchain): - is_tonic = prost_toolchain.tonic_runtime != None +ProstProtoInfo = provider( + doc = "Rust Prost provider info", + fields = { + "dep_variant_info": "DepVariantInfo: For the compiled Rust gencode (also covers its " + + "transitive dependencies)", + "package_info": "File: A newline delimited file of `--extern_path` values for protoc.", + "transitive_dep_infos": "depset[DepVariantInfo]: Transitive dependencies of the compiled crate.", + }, +) - mnemonic = "TonicGenProto" if is_tonic else "ProstGenProto" +def _create_proto_lang_toolchain(ctx, prost_toolchain): proto_lang_toolchain = proto_common.ProtoLangToolchainInfo( out_replacement_format_flag = "--prost_out=%s", plugin_format_flag = prost_toolchain.prost_plugin_flag, @@ -26,26 +32,22 @@ def _create_proto_lang_toolchain(ctx, prost_toolchain): provided_proto_sources = depset(), proto_compiler = ctx.attr._prost_process_wrapper[DefaultInfo].files_to_run, protoc_opts = prost_toolchain.protoc_opts, - progress_message = mnemonic + " %{label}", - mnemonic = mnemonic, + progress_message = "ProstGenProto %{label}", + mnemonic = "ProstGenProto", ) return proto_lang_toolchain -def _compile_proto(ctx, crate_name, proto_info, deps, prost_toolchain, is_tonic, rustfmt_toolchain = None): - kind = "tonic" if is_tonic else "prost" - extension = ".tonic.rs" if is_tonic else ".rs" - provider = TonicProtoInfo if is_tonic else ProstProtoInfo - - deps_info_file = ctx.actions.declare_file(ctx.label.name + ".{}_deps_info".format(kind)) - dep_package_infos = [dep[provider].package_info for dep in deps] +def _compile_proto(ctx, crate_name, proto_info, deps, prost_toolchain, rustfmt_toolchain = None): + deps_info_file = ctx.actions.declare_file(ctx.label.name + ".prost_deps_info") + dep_package_infos = [dep[ProstProtoInfo].package_info for dep in deps] ctx.actions.write( output = deps_info_file, content = "\n".join([file.path for file in dep_package_infos]), ) - package_info_file = ctx.actions.declare_file(ctx.label.name + ".{}_package_info".format(kind)) - lib_rs = ctx.actions.declare_file("{}.lib{}".format(ctx.label.name, extension)) + 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 tools = depset([proto_compiler.executable]) @@ -62,10 +64,7 @@ def _compile_proto(ctx, crate_name, proto_info, deps, prost_toolchain, is_tonic, additional_args.add("--descriptor_set={}".format(proto_info.direct_descriptor_set.path)) additional_args.add_all(prost_toolchain.prost_opts, format_each = "--prost_opt=%s") - if is_tonic: - if not prost_toolchain.tonic_plugin: - fail("Tonic plugin not configured for this toolchain") - + if prost_toolchain.tonic_plugin: tonic_plugin = prost_toolchain.tonic_plugin[DefaultInfo].files_to_run additional_args.add(prost_toolchain.tonic_plugin_flag % tonic_plugin.executable.path) additional_args.add("--tonic_opt=no_include") @@ -78,7 +77,7 @@ def _compile_proto(ctx, crate_name, proto_info, deps, prost_toolchain, is_tonic, additional_args.add("--rustfmt={}".format(rustfmt_toolchain.rustfmt.path)) tools = depset(transitive = [tools, rustfmt_toolchain.all_files]) - additional_inputs = depset([deps_info_file, proto_info.direct_descriptor_set] + [dep[provider].package_info for dep in deps]) + additional_inputs = depset([deps_info_file, proto_info.direct_descriptor_set] + [dep[ProstProtoInfo].package_info for dep in deps]) proto_common.compile( actions = ctx.actions, @@ -114,7 +113,7 @@ def _get_cc_info(providers): return provider fail("Couldn't find a CcInfo in the list of providers") -def _compile_rust(ctx, attr, crate_name, src, deps, edition, is_tonic): +def _compile_rust(ctx, attr, crate_name, src, deps, edition): """Compiles a Rust source file. Args: @@ -124,13 +123,12 @@ def _compile_rust(ctx, attr, crate_name, src, deps, edition, is_tonic): src (File): The crate root source file to be compiled. deps (List of DepVariantInfo): A list of dependencies needed. edition (str): The Rust edition to use. - is_tonic (bool): Whether or not the crate is a tonic library. Returns: A DepVariantInfo provider. """ toolchain = ctx.toolchains["@rules_rust//rust:toolchain_type"] - output_hash = repr(hash(src.path + (".tonic" if is_tonic else ".prost"))) + output_hash = repr(hash(src.path + ".prost")) lib_name = "{prefix}{name}-{lib_hash}{extension}".format( prefix = "lib", @@ -194,8 +192,7 @@ def _compile_rust(ctx, attr, crate_name, src, deps, edition, is_tonic): ) def _rust_prost_aspect_impl(target, ctx): - proto_info_provider = TonicProtoInfo if ctx.attr._is_tonic else ProstProtoInfo - if proto_info_provider in target: + if ProstProtoInfo in target: return [] runtime_deps = [] @@ -221,7 +218,7 @@ def _rust_prost_aspect_impl(target, ctx): direct_deps = [] transitive_deps = [] for proto_dep in proto_deps: - proto_info = proto_dep[proto_info_provider] + proto_info = proto_dep[ProstProtoInfo] direct_deps.append(proto_info.dep_variant_info) transitive_deps.append(depset( @@ -241,7 +238,6 @@ def _rust_prost_aspect_impl(target, ctx): proto_info = proto_info, deps = proto_deps, prost_toolchain = prost_toolchain, - is_tonic = ctx.attr._is_tonic, rustfmt_toolchain = rustfmt_toolchain, ) @@ -252,100 +248,82 @@ def _rust_prost_aspect_impl(target, ctx): src = lib_rs, deps = deps, edition = RUST_EDITION, - is_tonic = ctx.attr._is_tonic, ) return [ - proto_info_provider( + ProstProtoInfo( dep_variant_info = dep_variant_info, transitive_dep_infos = depset(transitive = transitive_deps), package_info = package_info_file, ), ] -def _make_rust_prost_aspect(doc, is_tonic): - return aspect( - doc = doc, - implementation = _rust_prost_aspect_impl, - attr_aspects = ["deps"], - attrs = { - "_cc_toolchain": attr.label( - doc = ( - "In order to use find_cc_toolchain, your rule has to depend " + - "on C++ toolchain. See `@rules_cc//cc:find_cc_toolchain.bzl` " + - "docs for details." - ), - default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"), - ), - "_collect_cc_coverage": attr.label( - default = Label("//util:collect_coverage"), - executable = True, - cfg = "exec", - ), - "_error_format": attr.label( - default = Label("//:error_format"), - ), - "_extra_exec_rustc_flag": attr.label( - default = Label("//:extra_exec_rustc_flag"), - ), - "_extra_exec_rustc_flags": attr.label( - default = Label("//:extra_exec_rustc_flags"), - ), - "_extra_rustc_flag": attr.label( - default = Label("//:extra_rustc_flag"), - ), - "_extra_rustc_flags": attr.label( - default = Label("//:extra_rustc_flags"), - ), - "_grep_includes": attr.label( - allow_single_file = True, - default = Label("@bazel_tools//tools/cpp:grep-includes"), - cfg = "exec", - ), - "_is_tonic": attr.bool( - doc = "Indicates whether or not Tonic behavior should be enabled.", - default = is_tonic, - ), - "_process_wrapper": attr.label( - doc = "A process wrapper for running rustc on all platforms.", - default = Label("//util/process_wrapper"), - executable = True, - allow_single_file = True, - cfg = "exec", - ), - "_prost_process_wrapper": attr.label( - doc = "The wrapper script for the Prost protoc plugin.", - cfg = "exec", - executable = True, - default = Label("//proto/prost/private:protoc_wrapper"), - ), - }, - fragments = ["cpp"], - host_fragments = ["cpp"], - toolchains = [ - TOOLCHAIN_TYPE, - "@bazel_tools//tools/cpp:toolchain_type", - "@rules_rust//rust:toolchain_type", - "@rules_rust//rust/rustfmt:toolchain_type", - ], - incompatible_use_toolchain_transition = True, - ) - -_rust_prost_aspect = _make_rust_prost_aspect( +rust_prost_aspect = aspect( doc = "An aspect used to generate and compile proto files with Prost.", - is_tonic = False, -) - -_rust_tonic_aspect = _make_rust_prost_aspect( - doc = "An aspect used to generate and compile proto files with Prost and Tonic.", - is_tonic = True, + implementation = _rust_prost_aspect_impl, + attr_aspects = ["deps"], + attrs = { + "_cc_toolchain": attr.label( + doc = ( + "In order to use find_cc_toolchain, your rule has to depend " + + "on C++ toolchain. See `@rules_cc//cc:find_cc_toolchain.bzl` " + + "docs for details." + ), + default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"), + ), + "_collect_cc_coverage": attr.label( + default = Label("//util:collect_coverage"), + executable = True, + cfg = "exec", + ), + "_error_format": attr.label( + default = Label("//:error_format"), + ), + "_extra_exec_rustc_flag": attr.label( + default = Label("//:extra_exec_rustc_flag"), + ), + "_extra_exec_rustc_flags": attr.label( + default = Label("//:extra_exec_rustc_flags"), + ), + "_extra_rustc_flag": attr.label( + default = Label("//:extra_rustc_flag"), + ), + "_extra_rustc_flags": attr.label( + default = Label("//:extra_rustc_flags"), + ), + "_grep_includes": attr.label( + allow_single_file = True, + default = Label("@bazel_tools//tools/cpp:grep-includes"), + cfg = "exec", + ), + "_process_wrapper": attr.label( + doc = "A process wrapper for running rustc on all platforms.", + default = Label("//util/process_wrapper"), + executable = True, + allow_single_file = True, + cfg = "exec", + ), + "_prost_process_wrapper": attr.label( + doc = "The wrapper script for the Prost protoc plugin.", + cfg = "exec", + executable = True, + default = Label("//proto/prost/private:protoc_wrapper"), + ), + }, + fragments = ["cpp"], + host_fragments = ["cpp"], + toolchains = [ + TOOLCHAIN_TYPE, + "@bazel_tools//tools/cpp:toolchain_type", + "@rules_rust//rust:toolchain_type", + "@rules_rust//rust/rustfmt:toolchain_type", + ], + incompatible_use_toolchain_transition = True, ) def _rust_prost_library_impl(ctx): - proto_info_provider = TonicProtoInfo if ctx.attr._is_tonic else ProstProtoInfo - proto_dep = ctx.attr.proto - rust_proto_info = proto_dep[proto_info_provider] + rust_proto_info = proto_dep[ProstProtoInfo] dep_variant_info = rust_proto_info.dep_variant_info return [ @@ -358,37 +336,22 @@ def _rust_prost_library_impl(ctx): ), ] -def _make_rust_prost_library_rule(doc, is_tonic): - return rule( - doc = doc, - implementation = _rust_prost_library_impl, - attrs = { - "proto": attr.label( - doc = "A `proto_library` target for which to generate Rust gencode.", - providers = [ProtoInfo], - aspects = [_rust_tonic_aspect if is_tonic else _rust_prost_aspect], - mandatory = True, - ), - "_collect_cc_coverage": attr.label( - default = Label("@rules_rust//util:collect_coverage"), - executable = True, - cfg = "exec", - ), - "_is_tonic": attr.bool( - doc = "Indicates whether or not Tonic behavior should be enabled.", - default = is_tonic, - ), - }, - ) - -rust_tonic_library = _make_rust_prost_library_rule( - doc = "A rule for generating a Rust library using Prost and Tonic.", - is_tonic = True, -) - -rust_prost_library = _make_rust_prost_library_rule( +rust_prost_library = rule( doc = "A rule for generating a Rust library using Prost.", - is_tonic = False, + implementation = _rust_prost_library_impl, + attrs = { + "proto": attr.label( + doc = "A `proto_library` target for which to generate Rust gencode.", + providers = [ProtoInfo], + aspects = [rust_prost_aspect], + mandatory = True, + ), + "_collect_cc_coverage": attr.label( + default = Label("@rules_rust//util:collect_coverage"), + executable = True, + cfg = "exec", + ), + }, ) def _rust_prost_toolchain_impl(ctx): diff --git a/proto/prost/private/protoc_wrapper.rs b/proto/prost/private/protoc_wrapper.rs index 817faac9b0..6c3593ea81 100644 --- a/proto/prost/private/protoc_wrapper.rs +++ b/proto/prost/private/protoc_wrapper.rs @@ -287,17 +287,12 @@ impl From<&str> for RustModulePath { /// expected to convert proto files into a BTreeMap of /// `example.prost.helloworld`: `crate_name::example::prost::helloworld`. fn get_extern_paths( - descriptor_set_path: &PathBuf, + descriptor_set: &FileDescriptorSet, crate_name: &str, ) -> Result, String> { let mut extern_paths = BTreeMap::new(); let rust_path = RustModulePath(crate_name.to_string()); - let descriptor_set_bytes = - fs::read(descriptor_set_path).expect("Failed to read descriptor set"); - let descriptor_set = FileDescriptorSet::decode(descriptor_set_bytes.as_slice()) - .expect("Failed to decode descriptor set"); - for file in descriptor_set.file.iter() { descriptor_set_file_to_extern_paths(&mut extern_paths, &rust_path, file); } @@ -488,9 +483,6 @@ impl Args { ("--prost_out", value) => { out_dir = Some(PathBuf::from(value)); } - ("--crate_name", value) => { - crate_name = Some(value.to_string()); - } ("--package_info_output", value) => { let (key, value) = value .split_once('=') @@ -509,6 +501,11 @@ impl Args { .expect("Failed to read file") .lines() { + if crate_name.as_ref().unwrap() == "annotations_proto" + && flag.contains("MethodOptions") + { + continue; + } tonic_or_prost_opts.push(format!("extern_path={}", flag.trim())); } } @@ -620,6 +617,63 @@ fn get_and_create_output_dir(out_dir: &Path, label: &str) -> PathBuf { out_dir } +/// Parse the descriptor set file into a `FileDescriptorSet`. +fn parse_descriptor_set_file(descriptor_set_path: &PathBuf) -> FileDescriptorSet { + let descriptor_set_bytes = + fs::read(descriptor_set_path).expect("Failed to read descriptor set"); + let descriptor_set = FileDescriptorSet::decode(descriptor_set_bytes.as_slice()) + .expect("Failed to decode descriptor set"); + + descriptor_set +} + +/// Get the package name from the descriptor set. +fn get_package_name(descriptor_set: &FileDescriptorSet) -> Option { + let mut package_name = None; + + for file in &descriptor_set.file { + if let Some(package) = &file.package { + package_name = Some(package.clone()); + break; + } + } + + package_name +} + +/// Whether the proto file should expect to generate a .rs file. +/// +/// If the proto file contains any messages, enums, or services, then it should generate a rust file. +/// If the proto file only contains extensions, then it will not generate any rust files. +fn expect_fs_file_to_be_generated(descriptor_set: &FileDescriptorSet) -> bool { + let mut expect_rs = false; + + for file in descriptor_set.file.iter() { + let has_messages = !file.message_type.is_empty(); + let has_enums = !file.enum_type.is_empty(); + let has_services = !file.service.is_empty(); + let has_extensions = !file.extension.is_empty(); + + let has_definition = has_messages || has_enums || has_services; + + if has_definition { + return true; + } else if !has_definition && !has_extensions { + expect_rs = true; + } + } + + expect_rs +} + +/// Whether the proto file should expect to generate service definitions. +fn has_services(descriptor_set: &FileDescriptorSet) -> bool { + descriptor_set + .file + .iter() + .any(|file| !file.service.is_empty()) +} + fn main() { // Always enable backtraces for the protoc wrapper. env::set_var("RUST_BACKTRACE", "1"); @@ -642,6 +696,15 @@ fn main() { let out_dir = get_and_create_output_dir(&out_dir, &label); + let descriptor_set = parse_descriptor_set_file(&descriptor_set); + let package_name = get_package_name(&descriptor_set).unwrap_or_default(); + let expect_rs = expect_fs_file_to_be_generated(&descriptor_set); + let has_services = has_services(&descriptor_set); + + if has_services && !is_tonic { + println!("Warning: Service definitions will not be generated because the prost toolchain did not define a tonic plugin."); + } + let mut cmd = process::Command::new(&protoc); cmd.arg(format!("--prost_out={}", out_dir.display())); if is_tonic { @@ -719,9 +782,21 @@ fn main() { } // Locate all prost-generated outputs. - let rust_files = find_generated_rust_files(&out_dir); + let mut rust_files = find_generated_rust_files(&out_dir); if rust_files.is_empty() { - panic!("No .rs files were generated by prost."); + if expect_rs { + panic!("No .rs files were generated by prost."); + } else { + let file_stem = if package_name.is_empty() { + "_" + } else { + &package_name + }; + let file_stem = format!("{}{}", file_stem, if is_tonic { ".tonic" } else { "" }); + let empty_rs_file = out_dir.join(format!("{}.rs", file_stem)); + fs::write(&empty_rs_file, "").expect("Failed to write file."); + rust_files.insert(empty_rs_file); + } } let extern_paths = get_extern_paths(&descriptor_set, &crate_name) @@ -784,6 +859,7 @@ mod test { use super::*; + use prost_types::{FieldDescriptorProto, FileDescriptorProto, ServiceDescriptorProto}; use std::collections::BTreeMap; #[test] @@ -1004,6 +1080,131 @@ mod test { } } + #[test] + fn expect_fs_file_to_be_generated_test() { + { + // Empty descriptor set should create a file. + let descriptor_set = FileDescriptorSet { + file: vec![FileDescriptorProto { + name: Some("foo.proto".to_string()), + ..FileDescriptorProto::default() + }], + }; + assert!(expect_fs_file_to_be_generated(&descriptor_set)); + } + { + // Descriptor set with only message should create a file. + let descriptor_set = FileDescriptorSet { + file: vec![FileDescriptorProto { + name: Some("foo.proto".to_string()), + message_type: vec![DescriptorProto { + name: Some("Foo".to_string()), + ..DescriptorProto::default() + }], + ..FileDescriptorProto::default() + }], + }; + assert!(expect_fs_file_to_be_generated(&descriptor_set)); + } + { + // Descriptor set with only enum should create a file. + let descriptor_set = FileDescriptorSet { + file: vec![FileDescriptorProto { + name: Some("foo.proto".to_string()), + enum_type: vec![EnumDescriptorProto { + name: Some("Foo".to_string()), + ..EnumDescriptorProto::default() + }], + ..FileDescriptorProto::default() + }], + }; + assert!(expect_fs_file_to_be_generated(&descriptor_set)); + } + { + // Descriptor set with only service should create a file. + let descriptor_set = FileDescriptorSet { + file: vec![FileDescriptorProto { + name: Some("foo.proto".to_string()), + service: vec![ServiceDescriptorProto { + name: Some("Foo".to_string()), + ..ServiceDescriptorProto::default() + }], + ..FileDescriptorProto::default() + }], + }; + assert!(expect_fs_file_to_be_generated(&descriptor_set)); + } + { + // Descriptor set with only extensions should not create a file. + let descriptor_set = FileDescriptorSet { + file: vec![FileDescriptorProto { + name: Some("foo.proto".to_string()), + extension: vec![FieldDescriptorProto { + name: Some("Foo".to_string()), + ..FieldDescriptorProto::default() + }], + ..FileDescriptorProto::default() + }], + }; + assert!(!expect_fs_file_to_be_generated(&descriptor_set)); + } + } + + #[test] + fn has_services_test() { + { + // Empty file should not have services. + let descriptor_set = FileDescriptorSet { + file: vec![FileDescriptorProto { + name: Some("foo.proto".to_string()), + ..FileDescriptorProto::default() + }], + }; + assert!(!has_services(&descriptor_set)); + } + { + // File with only message should not have services. + let descriptor_set = FileDescriptorSet { + file: vec![FileDescriptorProto { + name: Some("foo.proto".to_string()), + message_type: vec![DescriptorProto { + name: Some("Foo".to_string()), + ..DescriptorProto::default() + }], + ..FileDescriptorProto::default() + }], + }; + assert!(!has_services(&descriptor_set)); + } + { + // File with services should have services. + let descriptor_set = FileDescriptorSet { + file: vec![FileDescriptorProto { + name: Some("foo.proto".to_string()), + service: vec![ServiceDescriptorProto { + name: Some("Foo".to_string()), + ..ServiceDescriptorProto::default() + }], + ..FileDescriptorProto::default() + }], + }; + assert!(has_services(&descriptor_set)); + } + } + + #[test] + fn get_package_name_test() { + let descriptor_set = FileDescriptorSet { + file: vec![FileDescriptorProto { + name: Some("foo.proto".to_string()), + package: Some("foo".to_string()), + ..FileDescriptorProto::default() + }], + }; + + assert_eq!(get_package_name(&descriptor_set), Some("foo".to_string())); + } + #[test] fn is_keyword_test() { let non_keywords = [ diff --git a/proto/prost/private/providers.bzl b/proto/prost/private/providers.bzl deleted file mode 100644 index 3405060e84..0000000000 --- a/proto/prost/private/providers.bzl +++ /dev/null @@ -1,21 +0,0 @@ -"""Prost and Tonic providers.""" - -ProstProtoInfo = provider( - doc = "Rust Prost provider info", - fields = { - "dep_variant_info": "DepVariantInfo: For the compiled Rust gencode (also covers its " + - "transitive dependencies)", - "package_info": "File: A newline delimited file of `--extern_path` values for protoc.", - "transitive_dep_infos": "depset[DepVariantInfo]: Transitive dependencies of the compiled crate.", - }, -) - -TonicProtoInfo = provider( - doc = "Rust Tonic provider info", - fields = { - "dep_variant_info": "DepVariantInfo for the compiled Rust gencode (also covers its " + - "transitive dependencies)", - "package_info": "File: A newline delimited file of `--extern_path` values for protoc.", - "transitive_dep_infos": "depset[DepVariantInfo]: Transitive dependencies of the compiled crate.", - }, -) diff --git a/proto/prost/private/tests/package_names/BUILD.bazel b/proto/prost/private/tests/package_names/BUILD.bazel index 526d2077c3..7c9cedc9b5 100644 --- a/proto/prost/private/tests/package_names/BUILD.bazel +++ b/proto/prost/private/tests/package_names/BUILD.bazel @@ -1,6 +1,6 @@ load("@rules_proto//proto:defs.bzl", "proto_library") load("@rules_rust//rust:defs.bzl", "rust_test") -load("//proto/prost:defs.bzl", "rust_tonic_library") +load("//proto/prost:defs.bzl", "rust_prost_library") package(default_visibility = ["//proto/prost/private/tests:__subpackages__"]) @@ -11,7 +11,7 @@ proto_library( ], ) -rust_tonic_library( +rust_prost_library( name = "pkg_empty_rs_proto", proto = ":pkg_empty_proto", ) @@ -23,7 +23,7 @@ proto_library( ], ) -rust_tonic_library( +rust_prost_library( name = "pkg_rs_proto", proto = ":pkg_proto", ) @@ -35,7 +35,7 @@ proto_library( ], ) -rust_tonic_library( +rust_prost_library( name = "pkg_a_rs_proto", proto = ":pkg_a_proto", ) @@ -47,7 +47,7 @@ proto_library( ], ) -rust_tonic_library( +rust_prost_library( name = "pkg_a_b_rs_proto", proto = ":pkg_a_b_proto", ) diff --git a/proto/prost/private/tests/remote/BUILD.bazel b/proto/prost/private/tests/remote/BUILD.bazel new file mode 100644 index 0000000000..3619c1676d --- /dev/null +++ b/proto/prost/private/tests/remote/BUILD.bazel @@ -0,0 +1,6 @@ +load("//proto:defs.bzl", "rust_prost_library") + +rust_prost_library( + name = "annotations_rs_proto", + proto = "@com_google_googleapis//google/api:annotations_proto", +) diff --git a/proto/prost/private/tests/services/echo/BUILD.bazel b/proto/prost/private/tests/services/echo/BUILD.bazel index 9a1d3d106d..50ae7ab804 100644 --- a/proto/prost/private/tests/services/echo/BUILD.bazel +++ b/proto/prost/private/tests/services/echo/BUILD.bazel @@ -1,5 +1,5 @@ load("@rules_proto//proto:defs.bzl", "proto_library") -load("//proto/prost:defs.bzl", "rust_tonic_library") +load("//proto/prost:defs.bzl", "rust_prost_library") load("//rust:defs.bzl", "rust_binary") package(default_visibility = ["//proto/prost/private/tests:__subpackages__"]) @@ -11,7 +11,7 @@ proto_library( ], ) -rust_tonic_library( +rust_prost_library( name = "echo_rs_proto", proto = ":echo_proto", ) diff --git a/proto/prost/private/tests/services/helloworld/BUILD.bazel b/proto/prost/private/tests/services/helloworld/BUILD.bazel index 56b4d774b4..796492fb8a 100644 --- a/proto/prost/private/tests/services/helloworld/BUILD.bazel +++ b/proto/prost/private/tests/services/helloworld/BUILD.bazel @@ -1,5 +1,5 @@ load("@rules_proto//proto:defs.bzl", "proto_library") -load("//proto/prost:defs.bzl", "rust_tonic_library") +load("//proto/prost:defs.bzl", "rust_prost_library") load("//rust:defs.bzl", "rust_binary") package(default_visibility = ["//proto/prost/private/tests:__subpackages__"]) @@ -11,7 +11,7 @@ proto_library( ], ) -rust_tonic_library( +rust_prost_library( name = "helloworld_rs_proto", proto = ":helloworld_proto", ) diff --git a/proto/prost/private/tests/transitive_dependencies/BUILD.bazel b/proto/prost/private/tests/transitive_dependencies/BUILD.bazel index 6605b1c8d1..5bc3b6af72 100644 --- a/proto/prost/private/tests/transitive_dependencies/BUILD.bazel +++ b/proto/prost/private/tests/transitive_dependencies/BUILD.bazel @@ -1,5 +1,5 @@ load("@rules_proto//proto:defs.bzl", "proto_library") -load("//proto/prost:defs.bzl", "rust_tonic_library") +load("//proto/prost:defs.bzl", "rust_prost_library") load("//rust:defs.bzl", "rust_test") package(default_visibility = ["//proto/prost/private/tests:__subpackages__"]) @@ -18,7 +18,7 @@ proto_library( ], ) -rust_tonic_library( +rust_prost_library( name = "a_rs_proto", proto = ":a_proto", ) diff --git a/proto/prost/private/tests/transitive_dependencies/b/BUILD.bazel b/proto/prost/private/tests/transitive_dependencies/b/BUILD.bazel index 51efd1227c..209a149a8c 100644 --- a/proto/prost/private/tests/transitive_dependencies/b/BUILD.bazel +++ b/proto/prost/private/tests/transitive_dependencies/b/BUILD.bazel @@ -1,5 +1,5 @@ load("@rules_proto//proto:defs.bzl", "proto_library") -load("//proto/prost:defs.bzl", "rust_tonic_library") +load("//proto/prost:defs.bzl", "rust_prost_library") load("//rust:defs.bzl", "rust_test") package(default_visibility = ["//proto/prost/private/tests:__subpackages__"]) @@ -16,7 +16,7 @@ proto_library( ], ) -rust_tonic_library( +rust_prost_library( name = "b_rs_proto", proto = ":b_proto", ) diff --git a/test/deps.bzl b/test/deps.bzl index 35821618fc..d2f33f062f 100644 --- a/test/deps.bzl +++ b/test/deps.bzl @@ -45,3 +45,13 @@ def rules_rust_test_deps(): name = "rules_rust_toolchain_test_target_json", target_json = Label("//test/unit/toolchain:toolchain-test-triple.json"), ) + + maybe( + http_archive, + name = "com_google_googleapis", + urls = [ + "https://github.com/googleapis/googleapis/archive/18becb1d1426feb7399db144d7beeb3284f1ccb0.zip", + ], + strip_prefix = "googleapis-18becb1d1426feb7399db144d7beeb3284f1ccb0", + sha256 = "b8c487191eb942361af905e40172644eab490190e717c3d09bf83e87f3994fff", + ) diff --git a/test/deps_transitive.bzl b/test/deps_transitive.bzl new file mode 100644 index 0000000000..396dc14133 --- /dev/null +++ b/test/deps_transitive.bzl @@ -0,0 +1,18 @@ +"""Rules rust test dependencies transitive dependencies.""" + +load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language") + +def rules_rust_test_deps_transitive(): + switched_rules_by_language( + name = "com_google_googleapis_imports", + cc = False, + csharp = False, + gapic = False, + go = False, + grpc = False, + java = False, + nodejs = False, + php = False, + python = False, + ruby = False, + )