forked from protocolbuffers/protobuf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdefs.bzl
133 lines (117 loc) · 4.61 KB
/
defs.bzl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""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."""
load("@rules_rust//rust:defs.bzl", "rust_common")
load("//bazel/common:proto_common.bzl", "proto_common")
load("//bazel/common:proto_info.bzl", "ProtoInfo")
load(
"//rust:aspects.bzl",
"RustProtoInfo",
"label_to_crate_name",
"proto_rust_toolchain_label",
"rust_cc_proto_library_aspect",
"rust_upb_proto_library_aspect",
)
def rust_proto_library(name, deps, **args):
"""Declares all the boilerplate needed to use Rust protobufs conveniently.
Hopefully no user will ever need to read this code.
Args:
name: name of the Rust protobuf target.
deps: proto_library target for which to generate Rust gencode.
**args: other args passed to the rust_<kernel>_proto_library targets.
"""
if not name.endswith("_rust_proto"):
fail(
"{}: Name rust_proto_library target should end with `_rust_proto`, but was '{}'"
.format(name),
)
name = name.removesuffix("_rust_proto")
alias_args = {}
if "visibility" in args:
alias_args["visibility"] = args.pop("visibility")
native.alias(
name = name + "_rust_proto",
actual = select({
"//rust:use_upb_kernel": name + "_upb_rust_proto",
"//conditions:default": name + "_cpp_rust_proto",
}),
**alias_args
)
rust_upb_proto_library(
name = name + "_upb_rust_proto",
deps = deps,
visibility = ["//visibility:private"],
**args
)
rust_cc_proto_library(
name = name + "_cpp_rust_proto",
deps = deps,
visibility = ["//visibility:private"],
**args
)
def _user_visible_label(ctx):
label = str(ctx.label)
label = label.removesuffix("_cpp_rust_proto")
label = label.removesuffix("_upb_rust_proto")
return label + "_rust_proto"
def _rust_proto_library_impl(ctx):
if not ctx.label.name.endswith("_rust_proto"):
fail(
"{}: Name of rust_proto_library target should end with `_rust_proto`."
.format(_user_visible_label(ctx)),
)
deps = ctx.attr.deps
if not deps:
fail(
"{}: Exactly 1 dependency in `deps` attribute expected, none were provided."
.format(_user_visible_label(ctx)),
)
if len(deps) > 1:
fail(
"{}: Exactly 1 dependency in `deps` attribute expected, too many were provided."
.format(_user_visible_label(ctx)),
)
dep = deps[0]
rust_proto_info = dep[RustProtoInfo]
dep_variant_info = rust_proto_info.dep_variant_info
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.
#
# When the aspect visits proto_libraries, it doesn't know and cannot deduce the name of the
# rust_proto_library (although the name of rust_proto_libraries is consistently ending with
# _rust_proto, we can't rely on all proto_libraries to have a name consistently ending with
# _proto), therefore we have to modify it after the fact here.
#
# Since Starlark providers are frozen once they leave the _impl function that defines them,
# we have to create a shallow copy.
toolchain = ctx.toolchains["@rules_rust//rust:toolchain_type"]
fields = {field: getattr(crate_info, field) for field in dir(crate_info)}
pkg, name = _user_visible_label(ctx).rsplit(":")
label = struct(**{"name": name, "pkg": pkg})
fields["name"] = label_to_crate_name(ctx, label, toolchain)
crate_info_with_rust_proto_name = rust_common.crate_info(**fields)
return [
crate_info_with_rust_proto_name,
dep_variant_info.dep_info,
dep_variant_info.cc_info,
DefaultInfo(files = dep_variant_info.crate_info.srcs),
]
def _make_rust_proto_library(is_upb):
return rule(
implementation = _rust_proto_library_impl,
attrs = {
"deps": attr.label_list(
mandatory = True,
providers = [ProtoInfo],
aspects = [rust_upb_proto_library_aspect if is_upb else rust_cc_proto_library_aspect],
),
"_proto_lang_toolchain": attr.label(
default = Label(proto_rust_toolchain_label(is_upb)),
),
},
toolchains = [
"@rules_rust//rust:toolchain_type",
],
)
rust_upb_proto_library = _make_rust_proto_library(is_upb = True)
rust_cc_proto_library = _make_rust_proto_library(is_upb = False)