Implement a minimal, internal, experimental rust_proto_library rule.
The internal design is consistent with other <lang>_proto_library rules. rust_proto_library attaches rust_proto_library_aspect on its `deps` attribute. The aspect traverses the dependency, and when it visits proto_library (detected by ProtoInfo provider) it registers 2 actions: 1) to run protoc with Rust backend to emit gencode 2) to compile the gencode using Rustc Action (2) gets the Rust proto runtime as an input as well. Coming in a followup is support and test coverage for proto_library.deps. PiperOrigin-RevId: 514521285pull/12156/head
parent
77e3f2c38d
commit
3dc546daff
|
@ -24,4 +24,4 @@ jobs:
|
|||
with:
|
||||
check_filenames: true
|
||||
skip: ./.git,./third_party,./conformance/third_party,*.snk,*.pb,*.pb.cc,*.pb.h,./src/google/protobuf/testdata,./objectivec/Tests,./python/compatibility_tests/v2.5.0/tests/google/protobuf/internal,./.github/workflows/codespell.yml
|
||||
ignore_words_list: "alow,alse,atleast,ba,chec,cleare,copyable,cloneable,dedup,dur,errorprone,falsy,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',ro,te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,optin,streem,sur,falsy"
|
||||
ignore_words_list: "alow,alse,atleast,ba,chec,cleare,copyable,cloneable,crate,dedup,dur,errorprone,falsy,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',ro,te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,optin,streem,sur,falsy"
|
||||
|
|
|
@ -136,4 +136,4 @@ http_archive(
|
|||
|
||||
load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains")
|
||||
rules_rust_dependencies()
|
||||
rust_register_toolchains()
|
||||
rust_register_toolchains(edition = "2021")
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Protobuf Rust runtime packages.
|
||||
|
||||
load("@rules_rust//rust:defs.bzl", "rust_library")
|
||||
|
||||
package(default_visibility = ["//src/google/protobuf:__subpackages__"])
|
||||
|
||||
rust_library(
|
||||
name = "protobuf",
|
||||
srcs = ["lib.rs"],
|
||||
)
|
||||
|
||||
# TODO(b/270125787): Move to the right location once rust_proto_library is no longer experimental.
|
||||
proto_lang_toolchain(
|
||||
name = "proto_lang_toolchain",
|
||||
command_line = "--rust_out=experimental-codegen=enabled:$(OUT)",
|
||||
progress_message = "Generating Rust proto_library %{label}",
|
||||
runtime = ":protobuf",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -1,10 +0,0 @@
|
|||
# Protobuf Rust runtime packages.
|
||||
|
||||
load("@rules_rust//rust:defs.bzl", "rust_library")
|
||||
|
||||
package(default_visibility = ["//src/google/protobuf:__subpackages__"])
|
||||
|
||||
rust_library(
|
||||
name = "protobuf",
|
||||
srcs = ["lib.rs"],
|
||||
)
|
|
@ -0,0 +1,242 @@
|
|||
"""This file implements an experimental, do-not-use-kind of rust_proto_library.
|
||||
|
||||
Disclaimer: This project is experimental, under heavy development, and should not
|
||||
be used yet."""
|
||||
|
||||
# buildifier: disable=bzl-visibility
|
||||
load("@rules_rust//rust/private:providers.bzl", "CrateInfo", "DepInfo", "DepVariantInfo")
|
||||
|
||||
# buildifier: disable=bzl-visibility
|
||||
load("@rules_rust//rust/private:rustc.bzl", "rustc_compile_action")
|
||||
load("@rules_rust//rust:defs.bzl", "rust_common")
|
||||
|
||||
proto_common = proto_common_do_not_use
|
||||
|
||||
RustProtoInfo = provider(
|
||||
doc = "Rust protobuf provider info",
|
||||
fields = {
|
||||
"dep_variant_info": "DepVariantInfo for the compiled Rust gencode (also covers its " +
|
||||
"transitive dependencies)",
|
||||
},
|
||||
)
|
||||
|
||||
def _generate_rust_gencode(
|
||||
ctx,
|
||||
proto_info,
|
||||
proto_lang_toolchain):
|
||||
"""Generates Rust gencode
|
||||
|
||||
This function uses proto_common APIs and a ProtoLangToolchain to register an action
|
||||
that invokes protoc with the right flags.
|
||||
Args:
|
||||
ctx (RuleContext): current rule context
|
||||
proto_info (ProtoInfo): ProtoInfo of the proto_library target for which we are generating
|
||||
gencode
|
||||
proto_lang_toolchain (ProtoLangToolchainInfo): proto lang toolchain for Rust
|
||||
Returns:
|
||||
rs_outputs ([File]): generated Rust source files
|
||||
"""
|
||||
actions = ctx.actions
|
||||
rs_outputs = proto_common.declare_generated_files(
|
||||
actions = actions,
|
||||
proto_info = proto_info,
|
||||
extension = ".pb.rs",
|
||||
)
|
||||
|
||||
proto_common.compile(
|
||||
actions = ctx.actions,
|
||||
proto_info = proto_info,
|
||||
generated_files = rs_outputs,
|
||||
proto_lang_toolchain_info = proto_lang_toolchain,
|
||||
plugin_output = ctx.bin_dir.path,
|
||||
)
|
||||
return rs_outputs
|
||||
|
||||
def _get_crate_info(providers):
|
||||
for provider in providers:
|
||||
if hasattr(provider, "name"):
|
||||
return provider
|
||||
fail("Couldn't find a CrateInfo in the list of providers")
|
||||
|
||||
def _get_dep_info(providers):
|
||||
for provider in providers:
|
||||
if hasattr(provider, "direct_crates"):
|
||||
return provider
|
||||
fail("Couldn't find a DepInfo in the list of providers")
|
||||
|
||||
def _get_cc_info(providers):
|
||||
for provider in providers:
|
||||
if hasattr(provider, "linking_context"):
|
||||
return provider
|
||||
fail("Couldn't find a CcInfo in the list of providers")
|
||||
|
||||
def _compile_rust(ctx, attr, src, extra_srcs, deps):
|
||||
"""Compiles a Rust source file.
|
||||
|
||||
Eventually this function could be upstreamed into rules_rust and be made present in rust_common.
|
||||
|
||||
Args:
|
||||
ctx (RuleContext): The rule context.
|
||||
attr (Attrs): The current rule's attributes (`ctx.attr` for rules, `ctx.rule.attr` for aspects)
|
||||
src (File): The crate root source file to be compiled.
|
||||
extra_srcs ([File]): Additional source files to include in the crate.
|
||||
deps (List[DepVariantInfo]): A list of dependencies needed.
|
||||
|
||||
Returns:
|
||||
A DepVariantInfo provider.
|
||||
"""
|
||||
toolchain = ctx.toolchains["@rules_rust//rust:toolchain"]
|
||||
output_hash = repr(hash(src.path))
|
||||
|
||||
# TODO(b/270124215): Use the import! macro once available
|
||||
crate_name = ctx.label.name.replace("-", "_")
|
||||
|
||||
lib_name = "{prefix}{name}-{lib_hash}{extension}".format(
|
||||
prefix = "lib",
|
||||
name = crate_name,
|
||||
lib_hash = output_hash,
|
||||
extension = ".rlib",
|
||||
)
|
||||
|
||||
rmeta_name = "{prefix}{name}-{lib_hash}{extension}".format(
|
||||
prefix = "lib",
|
||||
name = crate_name,
|
||||
lib_hash = output_hash,
|
||||
extension = ".rmeta",
|
||||
)
|
||||
|
||||
lib = ctx.actions.declare_file(lib_name)
|
||||
rmeta = ctx.actions.declare_file(rmeta_name)
|
||||
|
||||
providers = rustc_compile_action(
|
||||
ctx = ctx,
|
||||
attr = attr,
|
||||
toolchain = toolchain,
|
||||
crate_info = rust_common.create_crate_info(
|
||||
name = crate_name,
|
||||
type = "rlib",
|
||||
root = src,
|
||||
srcs = depset([src] + extra_srcs),
|
||||
deps = depset(deps),
|
||||
proc_macro_deps = depset([]),
|
||||
aliases = {},
|
||||
output = lib,
|
||||
metadata = rmeta,
|
||||
edition = "2021",
|
||||
is_test = False,
|
||||
rustc_env = {},
|
||||
compile_data = depset([]),
|
||||
compile_data_targets = depset([]),
|
||||
owner = ctx.label,
|
||||
),
|
||||
output_hash = output_hash,
|
||||
)
|
||||
|
||||
return DepVariantInfo(
|
||||
crate_info = _get_crate_info(providers),
|
||||
dep_info = _get_dep_info(providers),
|
||||
cc_info = _get_cc_info(providers),
|
||||
build_info = None,
|
||||
)
|
||||
|
||||
def _rust_proto_aspect_impl(target, ctx):
|
||||
if ProtoInfo not in target:
|
||||
return None
|
||||
|
||||
proto_lang_toolchain = ctx.attr._proto_lang_toolchain[proto_common.ProtoLangToolchainInfo]
|
||||
|
||||
gencode = _generate_rust_gencode(ctx, target[ProtoInfo], proto_lang_toolchain)
|
||||
|
||||
runtime = proto_lang_toolchain.runtime
|
||||
dep_variant_info_for_runtime = DepVariantInfo(
|
||||
crate_info = runtime[CrateInfo] if CrateInfo in runtime else None,
|
||||
dep_info = runtime[DepInfo] if DepInfo in runtime else None,
|
||||
cc_info = runtime[CcInfo] if CcInfo in runtime else None,
|
||||
build_info = None,
|
||||
)
|
||||
|
||||
dep_variant_info = _compile_rust(
|
||||
ctx = ctx,
|
||||
attr = ctx.rule.attr,
|
||||
src = gencode[0],
|
||||
extra_srcs = gencode[1:],
|
||||
deps = [dep_variant_info_for_runtime],
|
||||
)
|
||||
return [RustProtoInfo(
|
||||
dep_variant_info = dep_variant_info,
|
||||
)]
|
||||
|
||||
rust_proto_library_aspect = aspect(
|
||||
implementation = _rust_proto_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("@rules_rust//util:collect_coverage"),
|
||||
executable = True,
|
||||
cfg = "exec",
|
||||
),
|
||||
"_error_format": attr.label(
|
||||
default = Label("@rules_rust//:error_format"),
|
||||
),
|
||||
"_extra_exec_rustc_flag": attr.label(
|
||||
default = Label("@rules_rust//:extra_exec_rustc_flag"),
|
||||
),
|
||||
"_extra_exec_rustc_flags": attr.label(
|
||||
default = Label("@rules_rust//:extra_exec_rustc_flags"),
|
||||
),
|
||||
"_extra_rustc_flag": attr.label(
|
||||
default = Label("@rules_rust//:extra_rustc_flag"),
|
||||
),
|
||||
"_extra_rustc_flags": attr.label(
|
||||
default = Label("@rules_rust//:extra_rustc_flags"),
|
||||
),
|
||||
"_process_wrapper": attr.label(
|
||||
doc = "A process wrapper for running rustc on all platforms.",
|
||||
default = Label("@rules_rust//util/process_wrapper"),
|
||||
executable = True,
|
||||
allow_single_file = True,
|
||||
cfg = "exec",
|
||||
),
|
||||
"_proto_lang_toolchain": attr.label(
|
||||
default = Label("//rust:proto_lang_toolchain"),
|
||||
),
|
||||
},
|
||||
fragments = ["cpp"],
|
||||
host_fragments = ["cpp"],
|
||||
toolchains = [
|
||||
str(Label("@rules_rust//rust:toolchain")),
|
||||
"@bazel_tools//tools/cpp:toolchain_type",
|
||||
],
|
||||
incompatible_use_toolchain_transition = True,
|
||||
)
|
||||
|
||||
def _rust_proto_library_impl(ctx):
|
||||
deps = ctx.attr.deps
|
||||
if not deps:
|
||||
fail("Exactly 1 dependency in `deps` attribute expected, none were provided.")
|
||||
if len(deps) > 1:
|
||||
fail("Exactly 1 dependency in `deps` attribute expected, too many were provided.")
|
||||
|
||||
dep = deps[0]
|
||||
rust_proto_info = dep[RustProtoInfo]
|
||||
dep_variant_info = rust_proto_info.dep_variant_info
|
||||
return [dep_variant_info.crate_info, dep_variant_info.dep_info, dep_variant_info.cc_info]
|
||||
|
||||
rust_proto_library = rule(
|
||||
implementation = _rust_proto_library_impl,
|
||||
attrs = {
|
||||
"deps": attr.label_list(
|
||||
mandatory = True,
|
||||
providers = [ProtoInfo],
|
||||
aspects = [rust_proto_library_aspect],
|
||||
),
|
||||
},
|
||||
)
|
|
@ -31,3 +31,6 @@
|
|||
//! Rust Protobuf Runtime
|
||||
|
||||
// Not yet implemented.
|
||||
|
||||
// TODO(b/270138878): Remove once we have real logic in the runtime.
|
||||
pub fn do_nothing() {}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
load("//rust:defs.bzl", "rust_proto_library")
|
||||
load("@rules_rust//rust:defs.bzl", "rust_test")
|
||||
|
||||
rust_proto_library(
|
||||
name = "hello_world_rs_proto",
|
||||
testonly = True,
|
||||
deps = ["//third_party/protobuf:unittest_proto"],
|
||||
)
|
||||
|
||||
rust_test(
|
||||
name = "hello_world_test",
|
||||
srcs = ["hello_world_test.rs"],
|
||||
# TODO(b/270274576): Enable testing on arm once we have a Rust Arm toolchain.
|
||||
tags = ["not_build:arm"],
|
||||
deps = [":hello_world_rs_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.
|
||||
|
||||
fn main() {
|
||||
// This is currently just a smoke test checking that we can generate gencode, compile it, and
|
||||
// link the test binary.
|
||||
let _test_all_types: unittest_proto::TestAllTypes;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
load(":rust_proto_library_unit_test.bzl", "rust_proto_library_unit_test")
|
||||
|
||||
rust_proto_library_unit_test(name = "rust_proto_library_unit_test")
|
|
@ -0,0 +1,19 @@
|
|||
"""Support for rust_proto_library_aspect unit-tests."""
|
||||
|
||||
load("//rust:defs.bzl", "RustProtoInfo", "rust_proto_library_aspect")
|
||||
|
||||
ActionsInfo = provider(
|
||||
doc = ("A provider that exposes what actions were registered by rust_proto_library_aspect " +
|
||||
"on proto_libraries."),
|
||||
fields = {"actions": "List[Action]: actions registered on proto_libraries."},
|
||||
)
|
||||
|
||||
def _attach_aspect_impl(ctx):
|
||||
return [ctx.attr.dep[RustProtoInfo], ActionsInfo(actions = ctx.attr.dep.actions)]
|
||||
|
||||
attach_aspect = rule(
|
||||
implementation = _attach_aspect_impl,
|
||||
attrs = {
|
||||
"dep": attr.label(aspects = [rust_proto_library_aspect]),
|
||||
},
|
||||
)
|
|
@ -0,0 +1,61 @@
|
|||
"""This module contains unit tests for rust_proto_library and its aspect."""
|
||||
|
||||
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
|
||||
load(":defs.bzl", "ActionsInfo", "attach_aspect")
|
||||
|
||||
def _find_action_with_mnemonic(actions, mnemonic):
|
||||
action = [a for a in actions if a.mnemonic == mnemonic]
|
||||
if not action:
|
||||
fail("Couldn't find action with mnemonic {} among {}".format(mnemonic, actions))
|
||||
return action[0]
|
||||
|
||||
def _find_rust_lib_input(inputs, target_name):
|
||||
inputs = inputs.to_list()
|
||||
input = [i for i in inputs if i.basename.startswith("lib" + target_name) and
|
||||
(i.basename.endswith(".rlib") or i.basename.endswith(".rmeta"))]
|
||||
if not input:
|
||||
fail("Couldn't find lib{}-<hash>.rlib or lib{}-<hash>.rmeta among {}".format(
|
||||
target_name,
|
||||
target_name,
|
||||
[i.basename for i in inputs],
|
||||
))
|
||||
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)
|
||||
actions = target_under_test[ActionsInfo].actions
|
||||
rustc_action = _find_action_with_mnemonic(actions, "Rustc")
|
||||
_find_rust_lib_input(rustc_action.inputs, "protobuf")
|
||||
asserts.true(env, rustc_action.outputs.to_list()[0].path.endswith(".rlib"))
|
||||
|
||||
return analysistest.end(env)
|
||||
|
||||
rust_compilation_action_has_runtime_as_input_test = analysistest.make(
|
||||
_rust_compilation_action_has_runtime_as_input_test_impl,
|
||||
)
|
||||
|
||||
def _test_rust_compilation_action_has_runtime_as_input():
|
||||
native.proto_library(name = "some_proto", srcs = ["some_proto.proto"])
|
||||
attach_aspect(name = "some_proto_with_aspect", dep = ":some_proto")
|
||||
|
||||
rust_compilation_action_has_runtime_as_input_test(
|
||||
name = "rust_compilation_action_has_runtime_as_input_test",
|
||||
target_under_test = ":some_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()
|
||||
|
||||
native.test_suite(
|
||||
name = name,
|
||||
tests = [
|
||||
":rust_compilation_action_has_runtime_as_input_test",
|
||||
],
|
||||
)
|
|
@ -0,0 +1,39 @@
|
|||
// 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.
|
||||
|
||||
// This file exists because of the design of the Starlark unit testing
|
||||
// framework. We call these tests unittests, but Blaze still sees them as full
|
||||
// builds. And while Blaze doesn't build the test-setup targets unless it really
|
||||
// needs to, it checks that all input files are present. Therefore, we need
|
||||
// these "empty" files to be present.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package third_party_protobuf_rust_test_rust_proto_library_unit_test;
|
|
@ -75,9 +75,20 @@ bool RustGenerator::Generate(const FileDescriptor* file,
|
|||
auto outfile = absl::WrapUnique(
|
||||
generator_context->Open(absl::StrCat(basename, ".pb.rs")));
|
||||
|
||||
google::protobuf::io::Printer(outfile.get()).Emit(R"cc(
|
||||
// TODO: Generate Bindings
|
||||
)cc");
|
||||
google::protobuf::io::Printer p(outfile.get());
|
||||
// TODO(b/270138878): Remove `do_nothing` import once we have real logic. This
|
||||
// is there only to smoke test rustc actions in rust_proto_library.
|
||||
p.Emit(R"rs(
|
||||
#[allow(unused_imports)]
|
||||
use protobuf::do_nothing;
|
||||
)rs");
|
||||
for (int i = 0; i < file->message_type_count(); ++i) {
|
||||
// TODO(b/270138878): Implement real logic
|
||||
p.Emit({{"Msg", file->message_type(i)->name()}}, R"rs(
|
||||
pub struct $Msg$ {}
|
||||
)rs");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue