Allow `rust_proto_library` aspect to handle targets with empty `srcs`

There is an old convention that a `proto_library` target with empty `srcs`
should re-export its dependencies. This is sometimes useful as a way of
creating something like an alias target, except that it can point to multiple
dependencies rather than just one.

The `rust_proto_library` aspect currently cannot handle this pattern and will
raise an error if it encounters a `proto_library` without `srcs`. This CL fixes
that problem by updating the `RustProtoInfo` provider generated by the aspect
to include a list of `DepVariantInfo` instead of just one. In the typical case
the provider will have just one `DepVariantInfo`, but this gives us the ability
to return more than one in the case where we're exporting all the dependencies
of a `src`-less `proto_library`.

One thing this CL specifically does not attempt to do is add support for a
`rust_proto_library` directly wrapping a `proto_library` without `srcs`. The
reason for that is that it appears difficult to do in a way that would respect
the layering check. It's also not obvious that we would want to encourage this
pattern anyway. It's still valuable to support `src`-less `proto_library`
targets when they're somewhere else in the transitive dependencies. This way
you can freely create a `rust_proto_library` without having to fix up all your
transitive deps first.

PiperOrigin-RevId: 687344284
pull/18901/head
Adam Cozzette 4 months ago committed by Copybara-Service
parent dcc1c08ef7
commit 9256d0705c
  1. 50
      rust/aspects.bzl
  2. 7
      rust/defs.bzl
  3. 2
      rust/test/rust_proto_library_unit_test/rust_proto_library_unit_test.bzl

@ -24,8 +24,8 @@ CrateMappingInfo = provider(
RustProtoInfo = provider(
doc = "Rust protobuf provider info",
fields = {
"dep_variant_info": "DepVariantInfo for the compiled Rust gencode (also covers its " +
"transitive dependencies)",
"dep_variant_infos": "List of DepVariantInfo for the compiled Rust " +
"gencode (also covers its transitive dependencies)",
"crate_mapping": "depset(CrateMappingInfo) containing mappings of all transitive " +
"dependencies of the current proto_library.",
},
@ -344,25 +344,33 @@ def _rust_proto_aspect_common(target, ctx, is_upb):
)
dep_variant_info_for_native_gencode = DepVariantInfo(cc_info = thunks_cc_info)
dep_variant_info = _compile_rust(
ctx = ctx,
attr = ctx.rule.attr,
src = gencode[0],
extra_srcs = gencode[1:],
deps = [dep_variant_info_for_runtime, dep_variant_info_for_native_gencode] + (
[d[RustProtoInfo].dep_variant_info for d in proto_deps]
),
)
return [RustProtoInfo(
dep_variant_info = dep_variant_info,
crate_mapping = depset(
direct = [CrateMappingInfo(
crate_name = label_to_crate_name(ctx, target.label, toolchain),
import_paths = tuple([get_import_path(f) for f in proto_srcs]),
)],
transitive = transitive_crate_mappings,
),
)]
dep_variant_infos = []
for info in [d[RustProtoInfo].dep_variant_infos for d in proto_deps]:
dep_variant_infos += info
if proto_srcs:
dep_variant_info = _compile_rust(
ctx = ctx,
attr = ctx.rule.attr,
src = gencode[0],
extra_srcs = gencode[1:],
deps = [dep_variant_info_for_runtime, dep_variant_info_for_native_gencode] + dep_variant_infos,
)
return [RustProtoInfo(
dep_variant_infos = [dep_variant_info],
crate_mapping = depset(
direct = [CrateMappingInfo(
crate_name = label_to_crate_name(ctx, target.label, toolchain),
import_paths = tuple([get_import_path(f) for f in proto_srcs]),
)],
transitive = transitive_crate_mappings,
),
)]
else:
return [RustProtoInfo(
dep_variant_infos = dep_variant_infos,
crate_mapping = depset(transitive = transitive_crate_mappings),
)]
def _make_proto_library_aspect(is_upb):
return aspect(

@ -81,7 +81,12 @@ def _rust_proto_library_impl(ctx):
dep = deps[0]
rust_proto_info = dep[RustProtoInfo]
dep_variant_info = rust_proto_info.dep_variant_info
if len(rust_proto_info.dep_variant_infos) != 1:
fail(
"{}: rust_proto_library does not support src-less proto_library targets."
.format(_user_visible_label(ctx)),
)
dep_variant_info = rust_proto_info.dep_variant_infos[0]
crate_info = dep_variant_info.crate_info
# Change the crate name from the hame of the proto_library to the name of the rust_proto_library.

@ -78,7 +78,7 @@ def _relevant_linker_inputs(ltl):
)
def _find_linker_input(rust_proto_info, basename_substring):
cc_info = rust_proto_info.dep_variant_info.cc_info
cc_info = rust_proto_info.dep_variant_infos[0].cc_info
for linker_input in cc_info.linking_context.linker_inputs.to_list():
for ltl in linker_input.libraries:
for file in _relevant_linker_inputs(ltl):

Loading…
Cancel
Save