xref: /aosp_15_r20/external/bazelbuild-rules_rust/proto/protobuf/proto.bzl (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1*d4726bddSHONG Yifan# Copyright 2018 The Bazel Authors. All rights reserved.
2*d4726bddSHONG Yifan#
3*d4726bddSHONG Yifan# Licensed under the Apache License, Version 2.0 (the "License");
4*d4726bddSHONG Yifan# you may not use this file except in compliance with the License.
5*d4726bddSHONG Yifan# You may obtain a copy of the License at
6*d4726bddSHONG Yifan#
7*d4726bddSHONG Yifan#    http://www.apache.org/licenses/LICENSE-2.0
8*d4726bddSHONG Yifan#
9*d4726bddSHONG Yifan# Unless required by applicable law or agreed to in writing, software
10*d4726bddSHONG Yifan# distributed under the License is distributed on an "AS IS" BASIS,
11*d4726bddSHONG Yifan# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*d4726bddSHONG Yifan# See the License for the specific language governing permissions and
13*d4726bddSHONG Yifan# limitations under the License.
14*d4726bddSHONG Yifan
15*d4726bddSHONG Yifan"""Rust Protobuf Rules"""
16*d4726bddSHONG Yifan
17*d4726bddSHONG Yifanload("@rules_proto//proto:defs.bzl", "ProtoInfo")
18*d4726bddSHONG Yifanload(
19*d4726bddSHONG Yifan    "//proto/protobuf:toolchain.bzl",
20*d4726bddSHONG Yifan    _generate_proto = "rust_generate_proto",
21*d4726bddSHONG Yifan    _generated_file_stem = "generated_file_stem",
22*d4726bddSHONG Yifan)
23*d4726bddSHONG Yifan
24*d4726bddSHONG Yifan# buildifier: disable=bzl-visibility
25*d4726bddSHONG Yifanload("//rust/private:rustc.bzl", "rustc_compile_action")
26*d4726bddSHONG Yifan
27*d4726bddSHONG Yifan# buildifier: disable=bzl-visibility
28*d4726bddSHONG Yifanload("//rust/private:utils.bzl", "can_build_metadata", "compute_crate_name", "determine_output_hash", "find_toolchain", "transform_deps")
29*d4726bddSHONG Yifan
30*d4726bddSHONG YifanRustProtoInfo = provider(
31*d4726bddSHONG Yifan    doc = "Rust protobuf provider info",
32*d4726bddSHONG Yifan    fields = {
33*d4726bddSHONG Yifan        "proto_sources": "List[string]: list of source paths of protos",
34*d4726bddSHONG Yifan        "transitive_proto_sources": "depset[string]",
35*d4726bddSHONG Yifan    },
36*d4726bddSHONG Yifan)
37*d4726bddSHONG Yifan
38*d4726bddSHONG Yifandef _compute_proto_source_path(file, source_root_attr):
39*d4726bddSHONG Yifan    """Take the short path of file and make it suitable for protoc.
40*d4726bddSHONG Yifan
41*d4726bddSHONG Yifan    Args:
42*d4726bddSHONG Yifan        file (File): The target source file.
43*d4726bddSHONG Yifan        source_root_attr (str): The directory relative to which the `.proto` \
44*d4726bddSHONG Yifan            files defined in the proto_library are defined.
45*d4726bddSHONG Yifan
46*d4726bddSHONG Yifan    Returns:
47*d4726bddSHONG Yifan        str: The protoc suitible path of `file`
48*d4726bddSHONG Yifan    """
49*d4726bddSHONG Yifan
50*d4726bddSHONG Yifan    # Bazel creates symlinks to the .proto files under a directory called
51*d4726bddSHONG Yifan    # "_virtual_imports/<rule name>" if we do any sort of munging of import
52*d4726bddSHONG Yifan    # paths (e.g. using strip_import_prefix / import_prefix attributes)
53*d4726bddSHONG Yifan    virtual_imports = "/_virtual_imports/"
54*d4726bddSHONG Yifan    if virtual_imports in file.path:
55*d4726bddSHONG Yifan        return file.path.split(virtual_imports)[1].split("/", 1)[1]
56*d4726bddSHONG Yifan
57*d4726bddSHONG Yifan    # For proto, they need to be requested with their absolute name to be
58*d4726bddSHONG Yifan    # compatible with the descriptor_set passed by proto_library.
59*d4726bddSHONG Yifan    # I.e. if you compile a protobuf at @repo1//package:file.proto, the proto
60*d4726bddSHONG Yifan    # compiler would generate a file descriptor with the path
61*d4726bddSHONG Yifan    # `package/file.proto`. Since we compile from the proto descriptor, we need
62*d4726bddSHONG Yifan    # to pass the list of descriptors and the list of path to compile.
63*d4726bddSHONG Yifan    # For the precedent example, the file (noted `f`) would have
64*d4726bddSHONG Yifan    # `f.short_path` returns `external/repo1/package/file.proto`.
65*d4726bddSHONG Yifan    # In addition, proto_library can provide a proto_source_path to change the base
66*d4726bddSHONG Yifan    # path, which should a be a prefix.
67*d4726bddSHONG Yifan    path = file.short_path
68*d4726bddSHONG Yifan
69*d4726bddSHONG Yifan    # Strip external prefix.
70*d4726bddSHONG Yifan    path = path.split("/", 2)[2] if path.startswith("../") else path
71*d4726bddSHONG Yifan
72*d4726bddSHONG Yifan    # Strip source_root.
73*d4726bddSHONG Yifan    if path.startswith(source_root_attr):
74*d4726bddSHONG Yifan        return path[len(source_root_attr):]
75*d4726bddSHONG Yifan    else:
76*d4726bddSHONG Yifan        return path
77*d4726bddSHONG Yifan
78*d4726bddSHONG Yifandef _rust_proto_aspect_impl(target, ctx):
79*d4726bddSHONG Yifan    """The implementation of the `rust_proto_aspect` aspect
80*d4726bddSHONG Yifan
81*d4726bddSHONG Yifan    Args:
82*d4726bddSHONG Yifan        target (Target): The target to which the aspect is applied
83*d4726bddSHONG Yifan        ctx (ctx): The rule context which the targetis created from
84*d4726bddSHONG Yifan
85*d4726bddSHONG Yifan    Returns:
86*d4726bddSHONG Yifan        list: A list containg a `RustProtoInfo` provider
87*d4726bddSHONG Yifan    """
88*d4726bddSHONG Yifan    if ProtoInfo not in target:
89*d4726bddSHONG Yifan        return None
90*d4726bddSHONG Yifan
91*d4726bddSHONG Yifan    if hasattr(ctx.rule.attr, "proto_source_root"):
92*d4726bddSHONG Yifan        source_root = ctx.rule.attr.proto_source_root
93*d4726bddSHONG Yifan    else:
94*d4726bddSHONG Yifan        source_root = ""
95*d4726bddSHONG Yifan
96*d4726bddSHONG Yifan    if source_root and source_root[-1] != "/":
97*d4726bddSHONG Yifan        source_root += "/"
98*d4726bddSHONG Yifan
99*d4726bddSHONG Yifan    sources = [
100*d4726bddSHONG Yifan        _compute_proto_source_path(f, source_root)
101*d4726bddSHONG Yifan        for f in target[ProtoInfo].direct_sources
102*d4726bddSHONG Yifan    ]
103*d4726bddSHONG Yifan    transitive_sources = [
104*d4726bddSHONG Yifan        f[RustProtoInfo].transitive_proto_sources
105*d4726bddSHONG Yifan        for f in ctx.rule.attr.deps
106*d4726bddSHONG Yifan        if RustProtoInfo in f
107*d4726bddSHONG Yifan    ]
108*d4726bddSHONG Yifan    return [RustProtoInfo(
109*d4726bddSHONG Yifan        proto_sources = sources,
110*d4726bddSHONG Yifan        transitive_proto_sources = depset(transitive = transitive_sources, direct = sources),
111*d4726bddSHONG Yifan    )]
112*d4726bddSHONG Yifan
113*d4726bddSHONG Yifan_rust_proto_aspect = aspect(
114*d4726bddSHONG Yifan    doc = "An aspect that gathers rust proto direct and transitive sources",
115*d4726bddSHONG Yifan    implementation = _rust_proto_aspect_impl,
116*d4726bddSHONG Yifan    attr_aspects = ["deps"],
117*d4726bddSHONG Yifan)
118*d4726bddSHONG Yifan
119*d4726bddSHONG Yifandef _gen_lib(ctx, grpc, srcs, lib):
120*d4726bddSHONG Yifan    """Generate a lib.rs file for the crates.
121*d4726bddSHONG Yifan
122*d4726bddSHONG Yifan    Args:
123*d4726bddSHONG Yifan        ctx (ctx): The current rule's context object
124*d4726bddSHONG Yifan        grpc (bool): True if the current rule is a `gRPC` rule.
125*d4726bddSHONG Yifan        srcs (list): A list of protoc suitible file paths (str).
126*d4726bddSHONG Yifan        lib (File): The File object where the rust source file should be written
127*d4726bddSHONG Yifan    """
128*d4726bddSHONG Yifan    content = ["extern crate protobuf;"]
129*d4726bddSHONG Yifan    if grpc:
130*d4726bddSHONG Yifan        content.append("extern crate grpc;")
131*d4726bddSHONG Yifan        content.append("extern crate tls_api;")
132*d4726bddSHONG Yifan    for f in srcs.to_list():
133*d4726bddSHONG Yifan        content.append("pub mod %s;" % _generated_file_stem(f))
134*d4726bddSHONG Yifan        content.append("pub use %s::*;" % _generated_file_stem(f))
135*d4726bddSHONG Yifan        if grpc:
136*d4726bddSHONG Yifan            content.append("pub mod %s_grpc;" % _generated_file_stem(f))
137*d4726bddSHONG Yifan            content.append("pub use %s_grpc::*;" % _generated_file_stem(f))
138*d4726bddSHONG Yifan    ctx.actions.write(lib, "\n".join(content))
139*d4726bddSHONG Yifan
140*d4726bddSHONG Yifandef _expand_provider(lst, provider):
141*d4726bddSHONG Yifan    """Gathers a list of a specific provider from a list of targets.
142*d4726bddSHONG Yifan
143*d4726bddSHONG Yifan    Args:
144*d4726bddSHONG Yifan        lst (list): A list of Targets
145*d4726bddSHONG Yifan        provider (Provider): The target provider type to extract `lst`
146*d4726bddSHONG Yifan
147*d4726bddSHONG Yifan    Returns:
148*d4726bddSHONG Yifan        list: A list of providers of the type from `provider`.
149*d4726bddSHONG Yifan    """
150*d4726bddSHONG Yifan    return [el[provider] for el in lst if provider in el]
151*d4726bddSHONG Yifan
152*d4726bddSHONG Yifandef _rust_proto_compile(protos, descriptor_sets, imports, crate_name, ctx, is_grpc, compile_deps, toolchain):
153*d4726bddSHONG Yifan    """Create and run a rustc compile action based on the current rule's attributes
154*d4726bddSHONG Yifan
155*d4726bddSHONG Yifan    Args:
156*d4726bddSHONG Yifan        protos (depset): Paths of protos to compile.
157*d4726bddSHONG Yifan        descriptor_sets (depset): A set of transitive protobuf `FileDescriptorSet`s
158*d4726bddSHONG Yifan        imports (depset): A set of transitive protobuf Imports.
159*d4726bddSHONG Yifan        crate_name (str): The name of the Crate for the current target
160*d4726bddSHONG Yifan        ctx (ctx): The current rule's context object
161*d4726bddSHONG Yifan        is_grpc (bool): True if the current rule is a `gRPC` rule.
162*d4726bddSHONG Yifan        compile_deps (list): A list of Rust dependencies (`List[Target]`)
163*d4726bddSHONG Yifan        toolchain (rust_toolchain): the current `rust_toolchain`.
164*d4726bddSHONG Yifan
165*d4726bddSHONG Yifan    Returns:
166*d4726bddSHONG Yifan        list: A list of providers, see `rustc_compile_action`
167*d4726bddSHONG Yifan    """
168*d4726bddSHONG Yifan
169*d4726bddSHONG Yifan    # Create all the source in a specific folder
170*d4726bddSHONG Yifan    proto_toolchain = ctx.toolchains[Label("//proto/protobuf:toolchain_type")]
171*d4726bddSHONG Yifan    output_dir = "%s.%s.rust" % (crate_name, "grpc" if is_grpc else "proto")
172*d4726bddSHONG Yifan
173*d4726bddSHONG Yifan    # Generate the proto stubs
174*d4726bddSHONG Yifan    srcs = _generate_proto(
175*d4726bddSHONG Yifan        ctx,
176*d4726bddSHONG Yifan        descriptor_sets,
177*d4726bddSHONG Yifan        protos = protos,
178*d4726bddSHONG Yifan        imports = imports,
179*d4726bddSHONG Yifan        output_dir = output_dir,
180*d4726bddSHONG Yifan        proto_toolchain = proto_toolchain,
181*d4726bddSHONG Yifan        is_grpc = is_grpc,
182*d4726bddSHONG Yifan    )
183*d4726bddSHONG Yifan
184*d4726bddSHONG Yifan    # and lib.rs
185*d4726bddSHONG Yifan    lib_rs = ctx.actions.declare_file("%s/lib.rs" % output_dir)
186*d4726bddSHONG Yifan    _gen_lib(ctx, is_grpc, protos, lib_rs)
187*d4726bddSHONG Yifan    srcs.append(lib_rs)
188*d4726bddSHONG Yifan
189*d4726bddSHONG Yifan    # And simulate rust_library behavior
190*d4726bddSHONG Yifan    output_hash = determine_output_hash(lib_rs, ctx.label)
191*d4726bddSHONG Yifan    rust_lib = ctx.actions.declare_file("%s/lib%s-%s.rlib" % (
192*d4726bddSHONG Yifan        output_dir,
193*d4726bddSHONG Yifan        crate_name,
194*d4726bddSHONG Yifan        output_hash,
195*d4726bddSHONG Yifan    ))
196*d4726bddSHONG Yifan    rust_metadata = None
197*d4726bddSHONG Yifan    if can_build_metadata(toolchain, ctx, "rlib"):
198*d4726bddSHONG Yifan        rust_metadata = ctx.actions.declare_file("%s/lib%s-%s.rmeta" % (
199*d4726bddSHONG Yifan            output_dir,
200*d4726bddSHONG Yifan            crate_name,
201*d4726bddSHONG Yifan            output_hash,
202*d4726bddSHONG Yifan        ))
203*d4726bddSHONG Yifan
204*d4726bddSHONG Yifan    # Gather all dependencies for compilation
205*d4726bddSHONG Yifan    compile_action_deps = depset(
206*d4726bddSHONG Yifan        transform_deps(
207*d4726bddSHONG Yifan            compile_deps +
208*d4726bddSHONG Yifan            proto_toolchain.grpc_compile_deps if is_grpc else proto_toolchain.proto_compile_deps,
209*d4726bddSHONG Yifan        ),
210*d4726bddSHONG Yifan    )
211*d4726bddSHONG Yifan
212*d4726bddSHONG Yifan    providers = rustc_compile_action(
213*d4726bddSHONG Yifan        ctx = ctx,
214*d4726bddSHONG Yifan        attr = ctx.attr,
215*d4726bddSHONG Yifan        toolchain = toolchain,
216*d4726bddSHONG Yifan        crate_info_dict = dict(
217*d4726bddSHONG Yifan            name = crate_name,
218*d4726bddSHONG Yifan            type = "rlib",
219*d4726bddSHONG Yifan            root = lib_rs,
220*d4726bddSHONG Yifan            srcs = depset(srcs),
221*d4726bddSHONG Yifan            deps = compile_action_deps,
222*d4726bddSHONG Yifan            proc_macro_deps = depset([]),
223*d4726bddSHONG Yifan            aliases = {},
224*d4726bddSHONG Yifan            output = rust_lib,
225*d4726bddSHONG Yifan            metadata = rust_metadata,
226*d4726bddSHONG Yifan            edition = proto_toolchain.edition,
227*d4726bddSHONG Yifan            rustc_env = {},
228*d4726bddSHONG Yifan            is_test = False,
229*d4726bddSHONG Yifan            compile_data = depset([target.files for target in getattr(ctx.attr, "compile_data", [])]),
230*d4726bddSHONG Yifan            compile_data_targets = depset(getattr(ctx.attr, "compile_data", [])),
231*d4726bddSHONG Yifan            wrapped_crate_type = None,
232*d4726bddSHONG Yifan            owner = ctx.label,
233*d4726bddSHONG Yifan        ),
234*d4726bddSHONG Yifan        output_hash = output_hash,
235*d4726bddSHONG Yifan    )
236*d4726bddSHONG Yifan    providers.append(OutputGroupInfo(rust_generated_srcs = srcs))
237*d4726bddSHONG Yifan    return providers
238*d4726bddSHONG Yifan
239*d4726bddSHONG Yifandef _rust_protogrpc_library_impl(ctx, is_grpc):
240*d4726bddSHONG Yifan    """Implementation of the rust_(proto|grpc)_library.
241*d4726bddSHONG Yifan
242*d4726bddSHONG Yifan    Args:
243*d4726bddSHONG Yifan        ctx (ctx): The current rule's context object
244*d4726bddSHONG Yifan        is_grpc (bool): True if the current rule is a `gRPC` rule.
245*d4726bddSHONG Yifan
246*d4726bddSHONG Yifan    Returns:
247*d4726bddSHONG Yifan        list: A list of providers, see `_rust_proto_compile`
248*d4726bddSHONG Yifan    """
249*d4726bddSHONG Yifan    proto = _expand_provider(ctx.attr.deps, ProtoInfo)
250*d4726bddSHONG Yifan    transitive_sources = [
251*d4726bddSHONG Yifan        f[RustProtoInfo].transitive_proto_sources
252*d4726bddSHONG Yifan        for f in ctx.attr.deps
253*d4726bddSHONG Yifan        if RustProtoInfo in f
254*d4726bddSHONG Yifan    ]
255*d4726bddSHONG Yifan
256*d4726bddSHONG Yifan    toolchain = find_toolchain(ctx)
257*d4726bddSHONG Yifan    crate_name = compute_crate_name(ctx.workspace_name, ctx.label, toolchain, ctx.attr.crate_name)
258*d4726bddSHONG Yifan
259*d4726bddSHONG Yifan    return _rust_proto_compile(
260*d4726bddSHONG Yifan        protos = depset(transitive = transitive_sources),
261*d4726bddSHONG Yifan        descriptor_sets = depset(transitive = [p.transitive_descriptor_sets for p in proto]),
262*d4726bddSHONG Yifan        imports = depset(transitive = [p.transitive_imports for p in proto]),
263*d4726bddSHONG Yifan        crate_name = crate_name,
264*d4726bddSHONG Yifan        ctx = ctx,
265*d4726bddSHONG Yifan        is_grpc = is_grpc,
266*d4726bddSHONG Yifan        compile_deps = ctx.attr.rust_deps,
267*d4726bddSHONG Yifan        toolchain = toolchain,
268*d4726bddSHONG Yifan    )
269*d4726bddSHONG Yifan
270*d4726bddSHONG Yifandef _rust_proto_library_impl(ctx):
271*d4726bddSHONG Yifan    """The implementation of the `rust_proto_library` rule
272*d4726bddSHONG Yifan
273*d4726bddSHONG Yifan    Args:
274*d4726bddSHONG Yifan        ctx (ctx): The rule's context object.
275*d4726bddSHONG Yifan
276*d4726bddSHONG Yifan    Returns:
277*d4726bddSHONG Yifan        list: A list of providers, see `_rust_protogrpc_library_impl`
278*d4726bddSHONG Yifan    """
279*d4726bddSHONG Yifan    return _rust_protogrpc_library_impl(ctx, False)
280*d4726bddSHONG Yifan
281*d4726bddSHONG Yifanrust_proto_library = rule(
282*d4726bddSHONG Yifan    implementation = _rust_proto_library_impl,
283*d4726bddSHONG Yifan    attrs = {
284*d4726bddSHONG Yifan        "crate_name": attr.string(
285*d4726bddSHONG Yifan            doc = """\
286*d4726bddSHONG Yifan                Crate name to use for this target.
287*d4726bddSHONG Yifan
288*d4726bddSHONG Yifan                This must be a valid Rust identifier, i.e. it may contain only alphanumeric characters and underscores.
289*d4726bddSHONG Yifan                Defaults to the target name, with any hyphens replaced by underscores.
290*d4726bddSHONG Yifan            """,
291*d4726bddSHONG Yifan        ),
292*d4726bddSHONG Yifan        "deps": attr.label_list(
293*d4726bddSHONG Yifan            doc = (
294*d4726bddSHONG Yifan                "List of proto_library dependencies that will be built. " +
295*d4726bddSHONG Yifan                "One crate for each proto_library will be created with the corresponding stubs."
296*d4726bddSHONG Yifan            ),
297*d4726bddSHONG Yifan            mandatory = True,
298*d4726bddSHONG Yifan            providers = [ProtoInfo],
299*d4726bddSHONG Yifan            aspects = [_rust_proto_aspect],
300*d4726bddSHONG Yifan        ),
301*d4726bddSHONG Yifan        "rust_deps": attr.label_list(
302*d4726bddSHONG Yifan            doc = "The crates the generated library depends on.",
303*d4726bddSHONG Yifan        ),
304*d4726bddSHONG Yifan        "rustc_flags": attr.string_list(
305*d4726bddSHONG Yifan            doc = """\
306*d4726bddSHONG Yifan                List of compiler flags passed to `rustc`.
307*d4726bddSHONG Yifan
308*d4726bddSHONG Yifan                These strings are subject to Make variable expansion for predefined
309*d4726bddSHONG Yifan                source/output path variables like `$location`, `$execpath`, and
310*d4726bddSHONG Yifan                `$rootpath`. This expansion is useful if you wish to pass a generated
311*d4726bddSHONG Yifan                file of arguments to rustc: `@$(location //package:target)`.
312*d4726bddSHONG Yifan            """,
313*d4726bddSHONG Yifan        ),
314*d4726bddSHONG Yifan        "_cc_toolchain": attr.label(
315*d4726bddSHONG Yifan            default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
316*d4726bddSHONG Yifan        ),
317*d4726bddSHONG Yifan        "_optional_output_wrapper": attr.label(
318*d4726bddSHONG Yifan            executable = True,
319*d4726bddSHONG Yifan            cfg = "exec",
320*d4726bddSHONG Yifan            default = Label("//proto/protobuf:optional_output_wrapper"),
321*d4726bddSHONG Yifan        ),
322*d4726bddSHONG Yifan        "_process_wrapper": attr.label(
323*d4726bddSHONG Yifan            default = Label("//util/process_wrapper"),
324*d4726bddSHONG Yifan            executable = True,
325*d4726bddSHONG Yifan            allow_single_file = True,
326*d4726bddSHONG Yifan            cfg = "exec",
327*d4726bddSHONG Yifan        ),
328*d4726bddSHONG Yifan    },
329*d4726bddSHONG Yifan    fragments = ["cpp"],
330*d4726bddSHONG Yifan    toolchains = [
331*d4726bddSHONG Yifan        str(Label("//proto/protobuf:toolchain_type")),
332*d4726bddSHONG Yifan        str(Label("//rust:toolchain_type")),
333*d4726bddSHONG Yifan        "@bazel_tools//tools/cpp:toolchain_type",
334*d4726bddSHONG Yifan    ],
335*d4726bddSHONG Yifan    doc = """\
336*d4726bddSHONG YifanBuilds a Rust library crate from a set of `proto_library`s.
337*d4726bddSHONG Yifan
338*d4726bddSHONG YifanExample:
339*d4726bddSHONG Yifan
340*d4726bddSHONG Yifan```python
341*d4726bddSHONG Yifanload("@rules_rust//proto/protobuf:defs.bzl", "rust_proto_library")
342*d4726bddSHONG Yifan
343*d4726bddSHONG Yifanproto_library(
344*d4726bddSHONG Yifan    name = "my_proto",
345*d4726bddSHONG Yifan    srcs = ["my.proto"]
346*d4726bddSHONG Yifan)
347*d4726bddSHONG Yifan
348*d4726bddSHONG Yifanrust_proto_library(
349*d4726bddSHONG Yifan    name = "rust",
350*d4726bddSHONG Yifan    deps = [":my_proto"],
351*d4726bddSHONG Yifan)
352*d4726bddSHONG Yifan
353*d4726bddSHONG Yifanrust_binary(
354*d4726bddSHONG Yifan    name = "my_proto_binary",
355*d4726bddSHONG Yifan    srcs = ["my_proto_binary.rs"],
356*d4726bddSHONG Yifan    deps = [":rust"],
357*d4726bddSHONG Yifan)
358*d4726bddSHONG Yifan```
359*d4726bddSHONG Yifan""",
360*d4726bddSHONG Yifan)
361*d4726bddSHONG Yifan
362*d4726bddSHONG Yifandef _rust_grpc_library_impl(ctx):
363*d4726bddSHONG Yifan    """The implementation of the `rust_grpc_library` rule
364*d4726bddSHONG Yifan
365*d4726bddSHONG Yifan    Args:
366*d4726bddSHONG Yifan        ctx (ctx): The rule's context object
367*d4726bddSHONG Yifan
368*d4726bddSHONG Yifan    Returns:
369*d4726bddSHONG Yifan        list: A list of providers. See `_rust_protogrpc_library_impl`
370*d4726bddSHONG Yifan    """
371*d4726bddSHONG Yifan    return _rust_protogrpc_library_impl(ctx, True)
372*d4726bddSHONG Yifan
373*d4726bddSHONG Yifanrust_grpc_library = rule(
374*d4726bddSHONG Yifan    implementation = _rust_grpc_library_impl,
375*d4726bddSHONG Yifan    attrs = {
376*d4726bddSHONG Yifan        "crate_name": attr.string(
377*d4726bddSHONG Yifan            doc = """\
378*d4726bddSHONG Yifan                Crate name to use for this target.
379*d4726bddSHONG Yifan
380*d4726bddSHONG Yifan                This must be a valid Rust identifier, i.e. it may contain only alphanumeric characters and underscores.
381*d4726bddSHONG Yifan                Defaults to the target name, with any hyphens replaced by underscores.
382*d4726bddSHONG Yifan            """,
383*d4726bddSHONG Yifan        ),
384*d4726bddSHONG Yifan        "deps": attr.label_list(
385*d4726bddSHONG Yifan            doc = (
386*d4726bddSHONG Yifan                "List of proto_library dependencies that will be built. " +
387*d4726bddSHONG Yifan                "One crate for each proto_library will be created with the corresponding gRPC stubs."
388*d4726bddSHONG Yifan            ),
389*d4726bddSHONG Yifan            mandatory = True,
390*d4726bddSHONG Yifan            providers = [ProtoInfo],
391*d4726bddSHONG Yifan            aspects = [_rust_proto_aspect],
392*d4726bddSHONG Yifan        ),
393*d4726bddSHONG Yifan        "rust_deps": attr.label_list(
394*d4726bddSHONG Yifan            doc = "The crates the generated library depends on.",
395*d4726bddSHONG Yifan        ),
396*d4726bddSHONG Yifan        "rustc_flags": attr.string_list(
397*d4726bddSHONG Yifan            doc = """\
398*d4726bddSHONG Yifan                List of compiler flags passed to `rustc`.
399*d4726bddSHONG Yifan
400*d4726bddSHONG Yifan                These strings are subject to Make variable expansion for predefined
401*d4726bddSHONG Yifan                source/output path variables like `$location`, `$execpath`, and
402*d4726bddSHONG Yifan                `$rootpath`. This expansion is useful if you wish to pass a generated
403*d4726bddSHONG Yifan                file of arguments to rustc: `@$(location //package:target)`.
404*d4726bddSHONG Yifan            """,
405*d4726bddSHONG Yifan        ),
406*d4726bddSHONG Yifan        "_cc_toolchain": attr.label(
407*d4726bddSHONG Yifan            default = "@bazel_tools//tools/cpp:current_cc_toolchain",
408*d4726bddSHONG Yifan        ),
409*d4726bddSHONG Yifan        "_optional_output_wrapper": attr.label(
410*d4726bddSHONG Yifan            executable = True,
411*d4726bddSHONG Yifan            cfg = "exec",
412*d4726bddSHONG Yifan            default = Label("//proto/protobuf:optional_output_wrapper"),
413*d4726bddSHONG Yifan        ),
414*d4726bddSHONG Yifan        "_process_wrapper": attr.label(
415*d4726bddSHONG Yifan            default = Label("//util/process_wrapper"),
416*d4726bddSHONG Yifan            executable = True,
417*d4726bddSHONG Yifan            allow_single_file = True,
418*d4726bddSHONG Yifan            cfg = "exec",
419*d4726bddSHONG Yifan        ),
420*d4726bddSHONG Yifan    },
421*d4726bddSHONG Yifan    fragments = ["cpp"],
422*d4726bddSHONG Yifan    toolchains = [
423*d4726bddSHONG Yifan        str(Label("//proto/protobuf:toolchain_type")),
424*d4726bddSHONG Yifan        str(Label("//rust:toolchain_type")),
425*d4726bddSHONG Yifan        "@bazel_tools//tools/cpp:toolchain_type",
426*d4726bddSHONG Yifan    ],
427*d4726bddSHONG Yifan    doc = """\
428*d4726bddSHONG YifanBuilds a Rust library crate from a set of `proto_library`s suitable for gRPC.
429*d4726bddSHONG Yifan
430*d4726bddSHONG YifanExample:
431*d4726bddSHONG Yifan
432*d4726bddSHONG Yifan```python
433*d4726bddSHONG Yifanload("@rules_rust//proto/protobuf:defs.bzl", "rust_grpc_library")
434*d4726bddSHONG Yifan
435*d4726bddSHONG Yifanproto_library(
436*d4726bddSHONG Yifan    name = "my_proto",
437*d4726bddSHONG Yifan    srcs = ["my.proto"]
438*d4726bddSHONG Yifan)
439*d4726bddSHONG Yifan
440*d4726bddSHONG Yifanrust_grpc_library(
441*d4726bddSHONG Yifan    name = "rust",
442*d4726bddSHONG Yifan    deps = [":my_proto"],
443*d4726bddSHONG Yifan)
444*d4726bddSHONG Yifan
445*d4726bddSHONG Yifanrust_binary(
446*d4726bddSHONG Yifan    name = "my_service",
447*d4726bddSHONG Yifan    srcs = ["my_service.rs"],
448*d4726bddSHONG Yifan    deps = [":rust"],
449*d4726bddSHONG Yifan)
450*d4726bddSHONG Yifan```
451*d4726bddSHONG Yifan""",
452*d4726bddSHONG Yifan)
453