@@ -27,8 +27,10 @@ CrateMappingInfo = provider(
2727RustProtoInfo = provider (
2828 doc = "Rust protobuf provider info" ,
2929 fields = {
30- "dep_variant_infos" : "List of DepVariantInfo for the compiled Rust " +
31- "gencode (also covers its transitive dependencies)" ,
30+ "dep_variant_infos" : "List of DepVariantInfo for the compiled Rust gencode" ,
31+ "exports_dep_variant_infos" : "List(DepVariantInfo): Transitive infos from targets from the proto_library.exports attribute. \
32+ This is a list instead of a depset, since we pass them as direct dependencies when compiling rust code. \
33+ We assume the proto exports feature is not widely used in a way where this will lead to unacceptable analysis-time overhead." ,
3234 "crate_mapping" : "depset(CrateMappingInfo) containing mappings of all transitive " +
3335 "dependencies of the current proto_library." ,
3436 },
@@ -43,6 +45,9 @@ def _rust_version_ge(version):
4345 return _version_parts (RUST_VERSION ) >= _version_parts (version )
4446
4547def label_to_crate_name (ctx , label , toolchain ):
48+ return compute_crate_name (ctx .workspace_name , label , toolchain )
49+
50+ def encode_label_as_crate_name (label ):
4651 return label .name .replace ("-" , "_" )
4752
4853def proto_rust_toolchain_label (is_upb ):
@@ -219,7 +224,7 @@ def _compile_cc(
219224 linking_context = linking_context ,
220225 )
221226
222- def _compile_rust (ctx , attr , src , extra_srcs , deps , runtime ):
227+ def _compile_rust (ctx , attr , src , extra_srcs , deps , aliases , runtime ):
223228 """Compiles a Rust source file.
224229
225230 Eventually this function could be upstreamed into rules_rust and be made present in rust_common.
@@ -230,6 +235,7 @@ def _compile_rust(ctx, attr, src, extra_srcs, deps, runtime):
230235 src (File): The crate root source file to be compiled.
231236 extra_srcs ([File]): Additional source files to include in the crate.
232237 deps (List[DepVariantInfo]): A list of dependencies needed.
238+ aliases (dict[Target, str]): A mapping from dependency target to its crate name.
233239 runtime: The protobuf runtime target.
234240
235241 Returns:
@@ -238,7 +244,7 @@ def _compile_rust(ctx, attr, src, extra_srcs, deps, runtime):
238244 toolchain = ctx .toolchains ["@rules_rust//rust:toolchain_type" ]
239245 output_hash = repr (hash (src .path ))
240246
241- crate_name = label_to_crate_name (ctx , ctx .label , toolchain )
247+ crate_name = compute_crate_name (ctx , ctx .label , toolchain )
242248
243249 lib_name = "{prefix}{name}-{lib_hash}{extension}" .format (
244250 prefix = "lib" ,
@@ -285,7 +291,7 @@ def _compile_rust(ctx, attr, src, extra_srcs, deps, runtime):
285291 # generated code to use a consistent name, even though the actual
286292 # name of the runtime crate varies depending on the protobuf kernel
287293 # and build system.
288- aliases = {runtime : "protobuf" },
294+ aliases = {runtime : "protobuf" } | aliases ,
289295 output = lib ,
290296 metadata = rmeta ,
291297 edition = "2024" ,
@@ -296,7 +302,7 @@ def _compile_rust(ctx, attr, src, extra_srcs, deps, runtime):
296302 owner = ctx .label ,
297303 ),
298304 # Needed to make transitive public imports not violate layering.
299- force_all_deps_direct = True ,
305+ # force_all_deps_direct = True,
300306 output_hash = output_hash ,
301307 )
302308
@@ -339,12 +345,19 @@ def _rust_proto_aspect_common(target, ctx, is_upb):
339345 for info in [d [RustProtoInfo ].dep_variant_infos for d in proto_deps ]:
340346 dep_variant_infos += info
341347
348+ exported_proto_deps = getattr (ctx .rule .attr , "exports" , [])
349+ exports_dep_variant_infos = []
350+ for d in exported_proto_deps :
351+ exports_dep_variant_infos .extend (d [RustProtoInfo ].dep_variant_infos )
352+ exports_dep_variant_infos .extend (d [RustProtoInfo ].exports_dep_variant_infos )
353+
342354 # If there are no srcs, then this is an alias library (which in Rust acts as a middle
343355 # library in a dependency chain). Don't generate any Rust code for it, but do propagate the
344356 # crate mappings.
345357 if not proto_srcs :
346358 return [RustProtoInfo (
347359 dep_variant_infos = dep_variant_infos ,
360+ exports_dep_variant_infos = exports_dep_variant_infos ,
348361 crate_mapping = depset (transitive = transitive_crate_mappings ),
349362 )]
350363
@@ -415,19 +428,37 @@ def _rust_proto_aspect_common(target, ctx, is_upb):
415428 for dep in ctx .attr ._extra_deps
416429 ]
417430
431+ proto_deps_for_aliases = dep_variant_infos + exports_dep_variant_infos
432+
433+ aliases = {}
434+
435+ for d in proto_deps_for_aliases :
436+ label = Label (d .crate_info .owner )
437+ target = struct (label = label )
438+ qualified_name = encode_label_as_crate_name (label )
439+ aliases [target ] = qualified_name
440+
441+ deps = ([dep_variant_info_for_runtime ] +
442+ dep_variant_info_for_native_gencode +
443+ dep_variant_infos +
444+ extra_dep_variant_infos +
445+ exports_dep_variant_infos )
446+
418447 dep_variant_info = _compile_rust (
419448 ctx = ctx ,
420449 attr = ctx .rule .attr ,
421450 src = entry_point_rs_output ,
422451 extra_srcs = rs_gencode ,
423- deps = [dep_variant_info_for_runtime ] + dep_variant_info_for_native_gencode + dep_variant_infos + extra_dep_variant_infos ,
452+ deps = deps ,
453+ aliases = aliases ,
424454 runtime = runtime ,
425455 )
426456 return [RustProtoInfo (
427457 dep_variant_infos = [dep_variant_info ],
458+ exports_dep_variant_infos = exports_dep_variant_infos ,
428459 crate_mapping = depset (
429460 direct = [CrateMappingInfo (
430- crate_name = label_to_crate_name (ctx , target .label , toolchain ),
461+ crate_name = encode_label_as_crate_name (ctx .label ),
431462 import_paths = tuple ([get_import_path (f ) for f in proto_srcs ]),
432463 )],
433464 transitive = transitive_crate_mappings ,
@@ -437,7 +468,7 @@ def _rust_proto_aspect_common(target, ctx, is_upb):
437468def _make_proto_library_aspect (is_upb ):
438469 return aspect (
439470 implementation = (_rust_upb_proto_aspect_impl if is_upb else _rust_cc_proto_aspect_impl ),
440- attr_aspects = ["deps" ],
471+ attr_aspects = ["deps" , "exports" ],
441472 requires = ([] if is_upb else [cc_proto_aspect ]),
442473 attrs = {
443474 "_collect_cc_coverage" : attr .label (
0 commit comments