From 26af540a7ac4caba41d98395b88ea375e8a66f79 Mon Sep 17 00:00:00 2001 From: Marcel Hlopko Date: Tue, 7 Mar 2023 06:50:24 -0800 Subject: [PATCH] Add support for proto dependencies to rust_proto_library PiperOrigin-RevId: 514719215 --- rust/BUILD | 1 + rust/defs.bzl | 3 +- rust/test/BUILD | 33 +++++++++++++++ rust/test/child.proto | 40 +++++++++++++++++++ rust/test/child_parent_test.rs | 37 +++++++++++++++++ rust/test/parent.proto | 35 ++++++++++++++++ .../rust_proto_library_unit_test/child.proto | 33 +++++++++++++++ .../rust_proto_library_unit_test/parent.proto | 33 +++++++++++++++ .../rust_proto_library_unit_test.bzl | 34 ++++++++++++++++ .../protobuf/compiler/rust/generator.cc | 25 ++++++++++++ 10 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 rust/test/child.proto create mode 100644 rust/test/child_parent_test.rs create mode 100644 rust/test/parent.proto create mode 100644 rust/test/rust_proto_library_unit_test/child.proto create mode 100644 rust/test/rust_proto_library_unit_test/parent.proto diff --git a/rust/BUILD b/rust/BUILD index bd2eeb78a7..ac72f0781a 100644 --- a/rust/BUILD +++ b/rust/BUILD @@ -1,6 +1,7 @@ # Protobuf Rust runtime packages. load("@rules_rust//rust:defs.bzl", "rust_library") +load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain") package(default_visibility = ["//src/google/protobuf:__subpackages__"]) diff --git a/rust/defs.bzl b/rust/defs.bzl index 11f8f71150..8e7d47eaf3 100644 --- a/rust/defs.bzl +++ b/rust/defs.bzl @@ -155,12 +155,13 @@ def _rust_proto_aspect_impl(target, ctx): build_info = None, ) + proto_dep = getattr(ctx.rule.attr, "deps", []) dep_variant_info = _compile_rust( ctx = ctx, attr = ctx.rule.attr, src = gencode[0], extra_srcs = gencode[1:], - deps = [dep_variant_info_for_runtime], + deps = [dep_variant_info_for_runtime] + ([proto_dep[0][RustProtoInfo].dep_variant_info] if proto_dep else []), ) return [RustProtoInfo( dep_variant_info = dep_variant_info, diff --git a/rust/test/BUILD b/rust/test/BUILD index 2b5bbec0bf..6e61e153de 100644 --- a/rust/test/BUILD +++ b/rust/test/BUILD @@ -14,3 +14,36 @@ rust_test( tags = ["not_build:arm"], deps = [":hello_world_rs_proto"], ) + +proto_library( + name = "parent_proto", + srcs = ["parent.proto"], +) + +proto_library( + name = "child_proto", + srcs = ["child.proto"], + exports = [":parent_proto"], + deps = [":parent_proto"], +) + +rust_proto_library( + name = "parent_rs_proto", + deps = [":parent_proto"], +) + +rust_proto_library( + name = "child_rs_proto", + deps = [":child_proto"], +) + +rust_test( + name = "child_parent_test", + srcs = ["child_parent_test.rs"], + # TODO(b/270274576): Enable testing on arm once we have a Rust Arm toolchain. + tags = ["not_build:arm"], + deps = [ + ":child_rs_proto", + ":parent_rs_proto", + ], +) diff --git a/rust/test/child.proto b/rust/test/child.proto new file mode 100644 index 0000000000..cb43465ca4 --- /dev/null +++ b/rust/test/child.proto @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package third_party_protobuf_rust_test; + +// copybara:strip_begin(Replace import path for Bazel) +import public "google/protobuf/rust/test/parent.proto"; + +// copybara:strip_end_and_replace import public "rust/test/parent.proto"; + +message Child {} diff --git a/rust/test/child_parent_test.rs b/rust/test/child_parent_test.rs new file mode 100644 index 0000000000..0bfb332f87 --- /dev/null +++ b/rust/test/child_parent_test.rs @@ -0,0 +1,37 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +fn main() { + let _child = child_proto::Child {}; + let _parent = parent_proto::Parent {}; + // Parent from child_proto crate should be the same type as Parent from + // parent_proto crate. + let _parent_from_child: child_proto::Parent = parent_proto::Parent {}; +} diff --git a/rust/test/parent.proto b/rust/test/parent.proto new file mode 100644 index 0000000000..fa3b204ef2 --- /dev/null +++ b/rust/test/parent.proto @@ -0,0 +1,35 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package third_party_protobuf_rust_test; + +message Parent {} diff --git a/rust/test/rust_proto_library_unit_test/child.proto b/rust/test/rust_proto_library_unit_test/child.proto new file mode 100644 index 0000000000..acb7dc4a0e --- /dev/null +++ b/rust/test/rust_proto_library_unit_test/child.proto @@ -0,0 +1,33 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package third_party_protobuf_rust_test_rust_proto_library_unit_test; diff --git a/rust/test/rust_proto_library_unit_test/parent.proto b/rust/test/rust_proto_library_unit_test/parent.proto new file mode 100644 index 0000000000..acb7dc4a0e --- /dev/null +++ b/rust/test/rust_proto_library_unit_test/parent.proto @@ -0,0 +1,33 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package third_party_protobuf_rust_test_rust_proto_library_unit_test; diff --git a/rust/test/rust_proto_library_unit_test/rust_proto_library_unit_test.bzl b/rust/test/rust_proto_library_unit_test/rust_proto_library_unit_test.bzl index 78c2e1e0d8..6749cf9005 100644 --- a/rust/test/rust_proto_library_unit_test/rust_proto_library_unit_test.bzl +++ b/rust/test/rust_proto_library_unit_test/rust_proto_library_unit_test.bzl @@ -21,6 +21,8 @@ def _find_rust_lib_input(inputs, target_name): )) return input[0] +#################################################################################################### + def _rust_compilation_action_has_runtime_as_input_test_impl(ctx): env = analysistest.begin(ctx) target_under_test = analysistest.target_under_test(env) @@ -46,16 +48,48 @@ def _test_rust_compilation_action_has_runtime_as_input(): tags = ["not_build:arm"], ) +#################################################################################################### + +def _rust_compilation_action_has_deps_as_inputs_test_impl(ctx): + env = analysistest.begin(ctx) + target_under_test = analysistest.target_under_test(env) + actions = target_under_test[ActionsInfo].actions + rustc_action = _find_action_with_mnemonic(actions, "Rustc") + _find_rust_lib_input(rustc_action.inputs, "parent") + + return analysistest.end(env) + +rust_compilation_action_has_deps_as_input_test = analysistest.make( + _rust_compilation_action_has_deps_as_inputs_test_impl, +) + +def _test_rust_compilation_action_has_deps_as_input(): + native.proto_library(name = "parent_proto", srcs = ["parent.proto"]) + native.proto_library(name = "child_proto", srcs = ["child.proto"], deps = [":parent_proto"]) + + attach_aspect(name = "child_proto_with_aspect", dep = ":child_proto") + + rust_compilation_action_has_deps_as_input_test( + name = "rust_compilation_action_has_deps_as_input_test", + target_under_test = ":child_proto_with_aspect", + # TODO(b/270274576): Enable testing on arm once we have a Rust Arm toolchain. + tags = ["not_build:arm"], + ) + +#################################################################################################### + def rust_proto_library_unit_test(name): """Sets up rust_proto_library_unit_test test suite. Args: name: name of the test suite""" _test_rust_compilation_action_has_runtime_as_input() + _test_rust_compilation_action_has_deps_as_input() native.test_suite( name = name, tests = [ ":rust_compilation_action_has_runtime_as_input_test", + ":rust_compilation_action_has_deps_as_input_test", ], ) diff --git a/src/google/protobuf/compiler/rust/generator.cc b/src/google/protobuf/compiler/rust/generator.cc index a01a82aa2b..08a14eb6cc 100644 --- a/src/google/protobuf/compiler/rust/generator.cc +++ b/src/google/protobuf/compiler/rust/generator.cc @@ -36,6 +36,7 @@ #include "absl/algorithm/container.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_replace.h" #include "absl/strings/string_view.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" @@ -56,6 +57,15 @@ bool ExperimentalRustGeneratorEnabled( }); } +std::string get_crate_name(const FileDescriptor* dependency) { + absl::string_view path = dependency->name(); + auto basename = path.substr(path.rfind('/') + 1); + return absl::StrReplaceAll(basename, { + {".", "_"}, + {"-", "_"}, + }); +} + bool RustGenerator::Generate(const FileDescriptor* file, const std::string& parameter, GeneratorContext* generator_context, @@ -88,6 +98,21 @@ bool RustGenerator::Generate(const FileDescriptor* file, pub struct $Msg$ {} )rs"); } + // TODO(b/270124215): Delete the following "placeholder impl" of `import + // public`. Also make sure to figure out how to map FileDescriptor#name to + // Rust crate names (currently Bazel labels). + for (int i = 0; i < file->public_dependency_count(); ++i) { + const FileDescriptor* dep = file->public_dependency(i); + std::string crate_name = get_crate_name(dep); + for (int j = 0; j < dep->message_type_count(); ++j) { + // TODO(b/270138878): Implement real logic + p.Emit( + {{"crate", crate_name}, {"type_name", dep->message_type(j)->name()}}, + R"rs( + pub use $crate$::$type_name$; + )rs"); + } + } return true; }