forked from bazelbuild/rules_rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtoolchain.bzl
More file actions
217 lines (188 loc) · 7 KB
/
toolchain.bzl
File metadata and controls
217 lines (188 loc) · 7 KB
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# Copyright 2018 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Toolchain for compiling rust stubs from protobuf and gRPC."""
load("//rust:defs.bzl", "rust_common")
# buildifier: disable=bzl-visibility
load("//rust/private:utils.bzl", "name_to_crate_name")
def generated_file_stem(file_path):
"""Returns the basename of a file without any extensions.
Example:
```python
content.append("pub mod %s;" % _generated_file_stem(f))
```
Args:
file_path (string): A path to a file
Returns:
string: The file stem of the filename
"""
basename = file_path.rsplit("/", 2)[-1]
basename = name_to_crate_name(basename)
return basename.rsplit(".", 2)[0]
def rust_generate_proto(
ctx,
transitive_descriptor_sets,
protos,
imports,
output_dir,
proto_toolchain,
is_grpc = False):
"""Generate a proto compilation action.
Args:
ctx (ctx): rule context.
transitive_descriptor_sets (depset): descriptor generated by previous protobuf libraries.
protos (list): list of paths of protos to compile.
imports (depset): directory, relative to the package, to output the list of stubs.
output_dir (str): The basename of the output directory for for the output generated stubs
proto_toolchain (ToolchainInfo): The toolchain for rust-proto compilation. See `rust_proto_toolchain`
is_grpc (bool, optional): generate gRPC stubs. Defaults to False.
Returns:
list: the list of generate stubs (File)
"""
tools = [
proto_toolchain.protoc,
proto_toolchain.proto_plugin,
]
executable = proto_toolchain.protoc
args = ctx.actions.args()
if not protos:
fail("Protobuf compilation requested without inputs!")
paths = ["%s/%s" % (output_dir, generated_file_stem(i)) for i in protos.to_list()]
outs = [ctx.actions.declare_file(path + ".rs") for path in paths]
output_directory = outs[0].dirname
if is_grpc:
# Add grpc stubs to the list of outputs
grpc_files = [ctx.actions.declare_file(path + "_grpc.rs") for path in paths]
outs.extend(grpc_files)
# gRPC stubs is generated only if a service is defined in the proto,
# so we create an empty grpc module in the other case.
tools.append(proto_toolchain.grpc_plugin)
tools.append(ctx.executable._optional_output_wrapper)
args.add_all([f.path for f in grpc_files])
args.add_all([
"--",
proto_toolchain.protoc.path,
"--plugin=protoc-gen-grpc-rust=" + proto_toolchain.grpc_plugin.path,
"--grpc-rust_out=" + output_directory,
])
executable = ctx.executable._optional_output_wrapper
args.add_all([
"--plugin=protoc-gen-rust=" + proto_toolchain.proto_plugin.path,
"--rust_out=" + output_directory,
])
args.add_joined(
transitive_descriptor_sets,
join_with = ":",
format_joined = "--descriptor_set_in=%s",
)
args.add_all(protos)
ctx.actions.run(
inputs = depset(
transitive = [
transitive_descriptor_sets,
imports,
],
),
outputs = outs,
tools = tools,
progress_message = "Generating Rust protobuf stubs",
mnemonic = "RustProtocGen",
executable = executable,
arguments = [args],
)
return outs
def _rust_proto_toolchain_impl(ctx):
return platform_common.ToolchainInfo(
edition = ctx.attr.edition,
grpc_compile_deps = ctx.attr.grpc_compile_deps,
grpc_plugin = ctx.file.grpc_plugin,
proto_compile_deps = ctx.attr.proto_compile_deps,
proto_plugin = ctx.file.proto_plugin,
protoc = ctx.executable.protoc,
)
# Default dependencies needed to compile protobuf stubs.
PROTO_COMPILE_DEPS = [
Label("//proto/raze:protobuf"),
]
# Default dependencies needed to compile gRPC stubs.
GRPC_COMPILE_DEPS = PROTO_COMPILE_DEPS + [
Label("//proto/raze:grpc"),
Label("//proto/raze:tls_api"),
Label("//proto/raze:tls_api_stub"),
]
rust_proto_toolchain = rule(
implementation = _rust_proto_toolchain_impl,
attrs = {
"edition": attr.string(
doc = "The edition used by the generated rust source.",
default = rust_common.default_edition,
),
"grpc_compile_deps": attr.label_list(
doc = "The crates the generated grpc libraries depends on.",
cfg = "target",
default = GRPC_COMPILE_DEPS,
),
"grpc_plugin": attr.label(
doc = "The location of the Rust protobuf compiler plugin to generate rust gRPC stubs.",
allow_single_file = True,
cfg = "exec",
default = Label("//proto:protoc_gen_rust_grpc"),
),
"proto_compile_deps": attr.label_list(
doc = "The crates the generated protobuf libraries depends on.",
cfg = "target",
default = PROTO_COMPILE_DEPS,
),
"proto_plugin": attr.label(
doc = "The location of the Rust protobuf compiler plugin used to generate rust sources.",
allow_single_file = True,
cfg = "exec",
default = Label("//proto:protoc_gen_rust"),
),
"protoc": attr.label(
doc = "The location of the `protoc` binary. It should be an executable target.",
executable = True,
cfg = "exec",
default = Label("@com_google_protobuf//:protoc"),
),
},
doc = """\
Declares a Rust Proto toolchain for use.
This is used to configure proto compilation and can be used to set different \
protobuf compiler plugin.
Example:
Suppose a new nicer gRPC plugin has came out. The new plugin can be \
used in Bazel by defining a new toolchain definition and declaration:
```python
load('@rules_rust//proto:toolchain.bzl', 'rust_proto_toolchain')
rust_proto_toolchain(
name="rust_proto_impl",
grpc_plugin="@rust_grpc//:grpc_plugin",
grpc_compile_deps=["@rust_grpc//:grpc_deps"],
)
toolchain(
name="rust_proto",
exec_compatible_with = [
"@platforms//cpu:cpuX",
],
target_compatible_with = [
"@platforms//cpu:cpuX",
],
toolchain = ":rust_proto_impl",
)
```
Then, either add the label of the toolchain rule to register_toolchains in the WORKSPACE, or pass \
it to the `--extra_toolchains` flag for Bazel, and it will be used.
See @rules_rust//proto:BUILD for examples of defining the toolchain.
""",
)