Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 40 additions & 9 deletions rust/bazel/aspects.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ CrateMappingInfo = provider(
RustProtoInfo = provider(
doc = "Rust protobuf provider info",
fields = {
"dep_variant_infos": "List of DepVariantInfo for the compiled Rust " +
"gencode (also covers its transitive dependencies)",
"dep_variant_infos": "List of DepVariantInfo for the compiled Rust gencode",
"exports_dep_variant_infos": "List(DepVariantInfo): Transitive infos from targets from the proto_library.exports attribute. \
This is a list instead of a depset, since we pass them as direct dependencies when compiling rust code. \
We assume the proto exports feature is not widely used in a way where this will lead to unacceptable analysis-time overhead.",
"crate_mapping": "depset(CrateMappingInfo) containing mappings of all transitive " +
"dependencies of the current proto_library.",
},
Expand All @@ -43,6 +45,9 @@ def _rust_version_ge(version):
return _version_parts(RUST_VERSION) >= _version_parts(version)

def label_to_crate_name(ctx, label, toolchain):
return compute_crate_name(ctx.workspace_name, label, toolchain)

def encode_label_as_crate_name(label):
return label.name.replace("-", "_")

def proto_rust_toolchain_label(is_upb):
Expand Down Expand Up @@ -219,7 +224,7 @@ def _compile_cc(
linking_context = linking_context,
)

def _compile_rust(ctx, attr, src, extra_srcs, deps, runtime):
def _compile_rust(ctx, attr, src, extra_srcs, deps, aliases, runtime):
"""Compiles a Rust source file.

Eventually this function could be upstreamed into rules_rust and be made present in rust_common.
Expand All @@ -230,6 +235,7 @@ def _compile_rust(ctx, attr, src, extra_srcs, deps, runtime):
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.
aliases (dict[Target, str]): A mapping from dependency target to its crate name.
runtime: The protobuf runtime target.

Returns:
Expand All @@ -238,7 +244,7 @@ def _compile_rust(ctx, attr, src, extra_srcs, deps, runtime):
toolchain = ctx.toolchains["@rules_rust//rust:toolchain_type"]
output_hash = repr(hash(src.path))

crate_name = label_to_crate_name(ctx, ctx.label, toolchain)
crate_name = compute_crate_name(ctx, ctx.label, toolchain)

lib_name = "{prefix}{name}-{lib_hash}{extension}".format(
prefix = "lib",
Expand Down Expand Up @@ -285,7 +291,7 @@ def _compile_rust(ctx, attr, src, extra_srcs, deps, runtime):
# generated code to use a consistent name, even though the actual
# name of the runtime crate varies depending on the protobuf kernel
# and build system.
aliases = {runtime: "protobuf"},
aliases = {runtime: "protobuf"} | aliases,
output = lib,
metadata = rmeta,
edition = "2024",
Expand All @@ -296,7 +302,7 @@ def _compile_rust(ctx, attr, src, extra_srcs, deps, runtime):
owner = ctx.label,
),
# Needed to make transitive public imports not violate layering.
force_all_deps_direct = True,
# force_all_deps_direct = True,
output_hash = output_hash,
)

Expand Down Expand Up @@ -339,12 +345,19 @@ def _rust_proto_aspect_common(target, ctx, is_upb):
for info in [d[RustProtoInfo].dep_variant_infos for d in proto_deps]:
dep_variant_infos += info

exported_proto_deps = getattr(ctx.rule.attr, "exports", [])
exports_dep_variant_infos = []
for d in exported_proto_deps:
exports_dep_variant_infos.extend(d[RustProtoInfo].dep_variant_infos)
exports_dep_variant_infos.extend(d[RustProtoInfo].exports_dep_variant_infos)

# If there are no srcs, then this is an alias library (which in Rust acts as a middle
# library in a dependency chain). Don't generate any Rust code for it, but do propagate the
# crate mappings.
if not proto_srcs:
return [RustProtoInfo(
dep_variant_infos = dep_variant_infos,
exports_dep_variant_infos = exports_dep_variant_infos,
crate_mapping = depset(transitive = transitive_crate_mappings),
)]

Expand Down Expand Up @@ -415,19 +428,37 @@ def _rust_proto_aspect_common(target, ctx, is_upb):
for dep in ctx.attr._extra_deps
]

proto_deps_for_aliases = dep_variant_infos + exports_dep_variant_infos

aliases = {}

for d in proto_deps_for_aliases:
label = Label(d.crate_info.owner)
target = struct(label = label)
qualified_name = encode_label_as_crate_name(label)
aliases[target] = qualified_name

deps = ([dep_variant_info_for_runtime] +
dep_variant_info_for_native_gencode +
dep_variant_infos +
extra_dep_variant_infos +
exports_dep_variant_infos)

dep_variant_info = _compile_rust(
ctx = ctx,
attr = ctx.rule.attr,
src = entry_point_rs_output,
extra_srcs = rs_gencode,
deps = [dep_variant_info_for_runtime] + dep_variant_info_for_native_gencode + dep_variant_infos + extra_dep_variant_infos,
deps = deps,
aliases = aliases,
runtime = runtime,
)
return [RustProtoInfo(
dep_variant_infos = [dep_variant_info],
exports_dep_variant_infos = exports_dep_variant_infos,
crate_mapping = depset(
direct = [CrateMappingInfo(
crate_name = label_to_crate_name(ctx, target.label, toolchain),
crate_name = encode_label_as_crate_name(ctx.label),
import_paths = tuple([get_import_path(f) for f in proto_srcs]),
)],
transitive = transitive_crate_mappings,
Expand All @@ -437,7 +468,7 @@ def _rust_proto_aspect_common(target, ctx, is_upb):
def _make_proto_library_aspect(is_upb):
return aspect(
implementation = (_rust_upb_proto_aspect_impl if is_upb else _rust_cc_proto_aspect_impl),
attr_aspects = ["deps"],
attr_aspects = ["deps", "exports"],
requires = ([] if is_upb else [cc_proto_aspect]),
attrs = {
"_collect_cc_coverage": attr.label(
Expand Down
Loading