xref: /aosp_15_r20/external/bazelbuild-rules_rust/proto/prost/private/prost.bzl (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1*d4726bddSHONG Yifan"""Rules for building protos in Rust with Prost and Tonic."""
2*d4726bddSHONG Yifan
3*d4726bddSHONG Yifanload("@rules_proto//proto:defs.bzl", "ProtoInfo", "proto_common")
4*d4726bddSHONG Yifanload("@rules_proto//proto:proto_common.bzl", proto_toolchains = "toolchains")
5*d4726bddSHONG Yifanload("//proto/prost:providers.bzl", "ProstProtoInfo")
6*d4726bddSHONG Yifanload("//rust:defs.bzl", "rust_common")
7*d4726bddSHONG Yifan
8*d4726bddSHONG Yifan# buildifier: disable=bzl-visibility
9*d4726bddSHONG Yifanload("//rust/private:providers.bzl", "RustAnalyzerGroupInfo", "RustAnalyzerInfo")
10*d4726bddSHONG Yifan
11*d4726bddSHONG Yifan# buildifier: disable=bzl-visibility
12*d4726bddSHONG Yifanload("//rust/private:rust.bzl", "RUSTC_ATTRS")
13*d4726bddSHONG Yifan
14*d4726bddSHONG Yifan# buildifier: disable=bzl-visibility
15*d4726bddSHONG Yifanload("//rust/private:rust_analyzer.bzl", "write_rust_analyzer_spec_file")
16*d4726bddSHONG Yifan
17*d4726bddSHONG Yifan# buildifier: disable=bzl-visibility
18*d4726bddSHONG Yifanload("//rust/private:rustc.bzl", "rustc_compile_action")
19*d4726bddSHONG Yifan
20*d4726bddSHONG Yifan# buildifier: disable=bzl-visibility
21*d4726bddSHONG Yifanload("//rust/private:utils.bzl", "can_build_metadata")
22*d4726bddSHONG Yifan
23*d4726bddSHONG YifanRUST_EDITION = "2021"
24*d4726bddSHONG Yifan
25*d4726bddSHONG YifanTOOLCHAIN_TYPE = "@rules_rust//proto/prost:toolchain_type"
26*d4726bddSHONG Yifan
27*d4726bddSHONG Yifandef _create_proto_lang_toolchain(ctx, prost_toolchain):
28*d4726bddSHONG Yifan    proto_lang_toolchain = proto_common.ProtoLangToolchainInfo(
29*d4726bddSHONG Yifan        out_replacement_format_flag = "--prost_out=%s",
30*d4726bddSHONG Yifan        plugin_format_flag = prost_toolchain.prost_plugin_flag,
31*d4726bddSHONG Yifan        plugin = prost_toolchain.prost_plugin[DefaultInfo].files_to_run,
32*d4726bddSHONG Yifan        runtime = prost_toolchain.prost_runtime,
33*d4726bddSHONG Yifan        provided_proto_sources = depset(),
34*d4726bddSHONG Yifan        proto_compiler = ctx.attr._prost_process_wrapper[DefaultInfo].files_to_run,
35*d4726bddSHONG Yifan        protoc_opts = prost_toolchain.protoc_opts,
36*d4726bddSHONG Yifan        progress_message = "ProstGenProto %{label}",
37*d4726bddSHONG Yifan        mnemonic = "ProstGenProto",
38*d4726bddSHONG Yifan    )
39*d4726bddSHONG Yifan
40*d4726bddSHONG Yifan    return proto_lang_toolchain
41*d4726bddSHONG Yifan
42*d4726bddSHONG Yifandef _compile_proto(ctx, crate_name, proto_info, deps, prost_toolchain, rustfmt_toolchain = None):
43*d4726bddSHONG Yifan    deps_info_file = ctx.actions.declare_file(ctx.label.name + ".prost_deps_info")
44*d4726bddSHONG Yifan    dep_package_infos = [dep[ProstProtoInfo].package_info for dep in deps]
45*d4726bddSHONG Yifan    ctx.actions.write(
46*d4726bddSHONG Yifan        output = deps_info_file,
47*d4726bddSHONG Yifan        content = "\n".join([file.path for file in dep_package_infos]),
48*d4726bddSHONG Yifan    )
49*d4726bddSHONG Yifan
50*d4726bddSHONG Yifan    package_info_file = ctx.actions.declare_file(ctx.label.name + ".prost_package_info")
51*d4726bddSHONG Yifan    lib_rs = ctx.actions.declare_file("{}.lib.rs".format(ctx.label.name))
52*d4726bddSHONG Yifan
53*d4726bddSHONG Yifan    proto_compiler = prost_toolchain.proto_compiler
54*d4726bddSHONG Yifan    tools = depset([proto_compiler.executable])
55*d4726bddSHONG Yifan
56*d4726bddSHONG Yifan    additional_args = ctx.actions.args()
57*d4726bddSHONG Yifan
58*d4726bddSHONG Yifan    # Prost process wrapper specific args
59*d4726bddSHONG Yifan    additional_args.add("--protoc={}".format(proto_compiler.executable.path))
60*d4726bddSHONG Yifan    additional_args.add("--label={}".format(ctx.label))
61*d4726bddSHONG Yifan    additional_args.add("--out_librs={}".format(lib_rs.path))
62*d4726bddSHONG Yifan    additional_args.add("--package_info_output={}".format("{}={}".format(crate_name, package_info_file.path)))
63*d4726bddSHONG Yifan    additional_args.add("--deps_info={}".format(deps_info_file.path))
64*d4726bddSHONG Yifan    additional_args.add("--prost_opt=compile_well_known_types")
65*d4726bddSHONG Yifan    additional_args.add("--descriptor_set={}".format(proto_info.direct_descriptor_set.path))
66*d4726bddSHONG Yifan    additional_args.add_all(prost_toolchain.prost_opts, format_each = "--prost_opt=%s")
67*d4726bddSHONG Yifan
68*d4726bddSHONG Yifan    if prost_toolchain.tonic_plugin:
69*d4726bddSHONG Yifan        tonic_plugin = prost_toolchain.tonic_plugin[DefaultInfo].files_to_run
70*d4726bddSHONG Yifan        additional_args.add(prost_toolchain.tonic_plugin_flag % tonic_plugin.executable.path)
71*d4726bddSHONG Yifan        additional_args.add("--tonic_opt=no_include")
72*d4726bddSHONG Yifan        additional_args.add("--tonic_opt=compile_well_known_types")
73*d4726bddSHONG Yifan        additional_args.add("--is_tonic")
74*d4726bddSHONG Yifan        additional_args.add_all(prost_toolchain.tonic_opts, format_each = "--tonic_opt=%s")
75*d4726bddSHONG Yifan        tools = depset([tonic_plugin.executable], transitive = [tools])
76*d4726bddSHONG Yifan
77*d4726bddSHONG Yifan    if rustfmt_toolchain:
78*d4726bddSHONG Yifan        additional_args.add("--rustfmt={}".format(rustfmt_toolchain.rustfmt.path))
79*d4726bddSHONG Yifan        tools = depset(transitive = [tools, rustfmt_toolchain.all_files])
80*d4726bddSHONG Yifan
81*d4726bddSHONG Yifan    additional_inputs = depset([deps_info_file, proto_info.direct_descriptor_set] + [dep[ProstProtoInfo].package_info for dep in deps])
82*d4726bddSHONG Yifan
83*d4726bddSHONG Yifan    proto_common.compile(
84*d4726bddSHONG Yifan        actions = ctx.actions,
85*d4726bddSHONG Yifan        proto_info = proto_info,
86*d4726bddSHONG Yifan        additional_tools = tools.to_list(),
87*d4726bddSHONG Yifan        additional_inputs = additional_inputs,
88*d4726bddSHONG Yifan        additional_args = additional_args,
89*d4726bddSHONG Yifan        generated_files = [lib_rs, package_info_file],
90*d4726bddSHONG Yifan        proto_lang_toolchain_info = _create_proto_lang_toolchain(ctx, prost_toolchain),
91*d4726bddSHONG Yifan        plugin_output = ctx.bin_dir.path,
92*d4726bddSHONG Yifan    )
93*d4726bddSHONG Yifan
94*d4726bddSHONG Yifan    return lib_rs, package_info_file
95*d4726bddSHONG Yifan
96*d4726bddSHONG Yifandef _get_crate_info(providers):
97*d4726bddSHONG Yifan    """Finds the CrateInfo provider in the list of providers."""
98*d4726bddSHONG Yifan    for provider in providers:
99*d4726bddSHONG Yifan        if hasattr(provider, "name"):
100*d4726bddSHONG Yifan            return provider
101*d4726bddSHONG Yifan    fail("Couldn't find a CrateInfo in the list of providers")
102*d4726bddSHONG Yifan
103*d4726bddSHONG Yifandef _get_dep_info(providers):
104*d4726bddSHONG Yifan    """Finds the DepInfo provider in the list of providers."""
105*d4726bddSHONG Yifan    for provider in providers:
106*d4726bddSHONG Yifan        if hasattr(provider, "direct_crates"):
107*d4726bddSHONG Yifan            return provider
108*d4726bddSHONG Yifan    fail("Couldn't find a DepInfo in the list of providers")
109*d4726bddSHONG Yifan
110*d4726bddSHONG Yifandef _get_cc_info(providers):
111*d4726bddSHONG Yifan    """Finds the CcInfo provider in the list of providers."""
112*d4726bddSHONG Yifan    for provider in providers:
113*d4726bddSHONG Yifan        if hasattr(provider, "linking_context"):
114*d4726bddSHONG Yifan            return provider
115*d4726bddSHONG Yifan    fail("Couldn't find a CcInfo in the list of providers")
116*d4726bddSHONG Yifan
117*d4726bddSHONG Yifandef _compile_rust(ctx, attr, crate_name, src, deps, edition):
118*d4726bddSHONG Yifan    """Compiles a Rust source file.
119*d4726bddSHONG Yifan
120*d4726bddSHONG Yifan    Args:
121*d4726bddSHONG Yifan      ctx (RuleContext): The rule context.
122*d4726bddSHONG Yifan      attr (Attrs): The current rule's attributes (`ctx.attr` for rules, `ctx.rule.attr` for aspects)
123*d4726bddSHONG Yifan      crate_name (str): The crate module name to use.
124*d4726bddSHONG Yifan      src (File): The crate root source file to be compiled.
125*d4726bddSHONG Yifan      deps (List of DepVariantInfo): A list of dependencies needed.
126*d4726bddSHONG Yifan      edition (str): The Rust edition to use.
127*d4726bddSHONG Yifan
128*d4726bddSHONG Yifan    Returns:
129*d4726bddSHONG Yifan      A DepVariantInfo provider.
130*d4726bddSHONG Yifan    """
131*d4726bddSHONG Yifan    toolchain = ctx.toolchains["@rules_rust//rust:toolchain_type"]
132*d4726bddSHONG Yifan    output_hash = repr(hash(src.path + ".prost"))
133*d4726bddSHONG Yifan
134*d4726bddSHONG Yifan    lib_name = "{prefix}{name}-{lib_hash}{extension}".format(
135*d4726bddSHONG Yifan        prefix = "lib",
136*d4726bddSHONG Yifan        name = crate_name,
137*d4726bddSHONG Yifan        lib_hash = output_hash,
138*d4726bddSHONG Yifan        extension = ".rlib",
139*d4726bddSHONG Yifan    )
140*d4726bddSHONG Yifan
141*d4726bddSHONG Yifan    rmeta_name = "{prefix}{name}-{lib_hash}{extension}".format(
142*d4726bddSHONG Yifan        prefix = "lib",
143*d4726bddSHONG Yifan        name = crate_name,
144*d4726bddSHONG Yifan        lib_hash = output_hash,
145*d4726bddSHONG Yifan        extension = ".rmeta",
146*d4726bddSHONG Yifan    )
147*d4726bddSHONG Yifan
148*d4726bddSHONG Yifan    lib = ctx.actions.declare_file(lib_name)
149*d4726bddSHONG Yifan    rmeta = None
150*d4726bddSHONG Yifan
151*d4726bddSHONG Yifan    if can_build_metadata(toolchain, ctx, "rlib"):
152*d4726bddSHONG Yifan        rmeta_name = "{prefix}{name}-{lib_hash}{extension}".format(
153*d4726bddSHONG Yifan            prefix = "lib",
154*d4726bddSHONG Yifan            name = crate_name,
155*d4726bddSHONG Yifan            lib_hash = output_hash,
156*d4726bddSHONG Yifan            extension = ".rmeta",
157*d4726bddSHONG Yifan        )
158*d4726bddSHONG Yifan        rmeta = ctx.actions.declare_file(rmeta_name)
159*d4726bddSHONG Yifan
160*d4726bddSHONG Yifan    providers = rustc_compile_action(
161*d4726bddSHONG Yifan        ctx = ctx,
162*d4726bddSHONG Yifan        attr = attr,
163*d4726bddSHONG Yifan        toolchain = toolchain,
164*d4726bddSHONG Yifan        crate_info_dict = dict(
165*d4726bddSHONG Yifan            name = crate_name,
166*d4726bddSHONG Yifan            type = "rlib",
167*d4726bddSHONG Yifan            root = src,
168*d4726bddSHONG Yifan            srcs = depset([src]),
169*d4726bddSHONG Yifan            deps = depset(deps),
170*d4726bddSHONG Yifan            proc_macro_deps = depset([]),
171*d4726bddSHONG Yifan            aliases = {},
172*d4726bddSHONG Yifan            output = lib,
173*d4726bddSHONG Yifan            metadata = rmeta,
174*d4726bddSHONG Yifan            edition = edition,
175*d4726bddSHONG Yifan            is_test = False,
176*d4726bddSHONG Yifan            rustc_env = {},
177*d4726bddSHONG Yifan            compile_data = depset([]),
178*d4726bddSHONG Yifan            compile_data_targets = depset([]),
179*d4726bddSHONG Yifan            owner = ctx.label,
180*d4726bddSHONG Yifan        ),
181*d4726bddSHONG Yifan        output_hash = output_hash,
182*d4726bddSHONG Yifan    )
183*d4726bddSHONG Yifan
184*d4726bddSHONG Yifan    crate_info = _get_crate_info(providers)
185*d4726bddSHONG Yifan    dep_info = _get_dep_info(providers)
186*d4726bddSHONG Yifan    cc_info = _get_cc_info(providers)
187*d4726bddSHONG Yifan
188*d4726bddSHONG Yifan    return rust_common.dep_variant_info(
189*d4726bddSHONG Yifan        crate_info = crate_info,
190*d4726bddSHONG Yifan        dep_info = dep_info,
191*d4726bddSHONG Yifan        cc_info = cc_info,
192*d4726bddSHONG Yifan        build_info = None,
193*d4726bddSHONG Yifan    )
194*d4726bddSHONG Yifan
195*d4726bddSHONG Yifandef _rust_prost_aspect_impl(target, ctx):
196*d4726bddSHONG Yifan    if ProstProtoInfo in target:
197*d4726bddSHONG Yifan        return []
198*d4726bddSHONG Yifan
199*d4726bddSHONG Yifan    runtime_deps = []
200*d4726bddSHONG Yifan
201*d4726bddSHONG Yifan    rustfmt_toolchain = ctx.toolchains["@rules_rust//rust/rustfmt:toolchain_type"]
202*d4726bddSHONG Yifan    prost_toolchain = ctx.toolchains["@rules_rust//proto/prost:toolchain_type"]
203*d4726bddSHONG Yifan    for prost_runtime in [prost_toolchain.prost_runtime, prost_toolchain.tonic_runtime]:
204*d4726bddSHONG Yifan        if not prost_runtime:
205*d4726bddSHONG Yifan            continue
206*d4726bddSHONG Yifan        if rust_common.crate_group_info in prost_runtime:
207*d4726bddSHONG Yifan            crate_group_info = prost_runtime[rust_common.crate_group_info]
208*d4726bddSHONG Yifan            runtime_deps.extend(crate_group_info.dep_variant_infos.to_list())
209*d4726bddSHONG Yifan        else:
210*d4726bddSHONG Yifan            runtime_deps.append(rust_common.dep_variant_info(
211*d4726bddSHONG Yifan                crate_info = prost_runtime[rust_common.crate_info] if rust_common.crate_info in prost_runtime else None,
212*d4726bddSHONG Yifan                dep_info = prost_runtime[rust_common.dep_info] if rust_common.dep_info in prost_runtime else None,
213*d4726bddSHONG Yifan                cc_info = prost_runtime[CcInfo] if CcInfo in prost_runtime else None,
214*d4726bddSHONG Yifan                build_info = None,
215*d4726bddSHONG Yifan            ))
216*d4726bddSHONG Yifan
217*d4726bddSHONG Yifan    proto_deps = getattr(ctx.rule.attr, "deps", [])
218*d4726bddSHONG Yifan
219*d4726bddSHONG Yifan    direct_deps = []
220*d4726bddSHONG Yifan    transitive_deps = [depset(runtime_deps)]
221*d4726bddSHONG Yifan    rust_analyzer_deps = []
222*d4726bddSHONG Yifan    for proto_dep in proto_deps:
223*d4726bddSHONG Yifan        proto_info = proto_dep[ProstProtoInfo]
224*d4726bddSHONG Yifan
225*d4726bddSHONG Yifan        direct_deps.append(proto_info.dep_variant_info)
226*d4726bddSHONG Yifan        transitive_deps.append(depset(
227*d4726bddSHONG Yifan            [proto_info.dep_variant_info],
228*d4726bddSHONG Yifan            transitive = [proto_info.transitive_dep_infos],
229*d4726bddSHONG Yifan        ))
230*d4726bddSHONG Yifan
231*d4726bddSHONG Yifan        if RustAnalyzerInfo in proto_dep:
232*d4726bddSHONG Yifan            rust_analyzer_deps.append(proto_dep[RustAnalyzerInfo])
233*d4726bddSHONG Yifan
234*d4726bddSHONG Yifan    deps = runtime_deps + direct_deps
235*d4726bddSHONG Yifan
236*d4726bddSHONG Yifan    crate_name = ctx.label.name.replace("-", "_").replace("/", "_")
237*d4726bddSHONG Yifan
238*d4726bddSHONG Yifan    proto_info = target[ProtoInfo]
239*d4726bddSHONG Yifan
240*d4726bddSHONG Yifan    lib_rs, package_info_file = _compile_proto(
241*d4726bddSHONG Yifan        ctx = ctx,
242*d4726bddSHONG Yifan        crate_name = crate_name,
243*d4726bddSHONG Yifan        proto_info = proto_info,
244*d4726bddSHONG Yifan        deps = proto_deps,
245*d4726bddSHONG Yifan        prost_toolchain = prost_toolchain,
246*d4726bddSHONG Yifan        rustfmt_toolchain = rustfmt_toolchain,
247*d4726bddSHONG Yifan    )
248*d4726bddSHONG Yifan
249*d4726bddSHONG Yifan    dep_variant_info = _compile_rust(
250*d4726bddSHONG Yifan        ctx = ctx,
251*d4726bddSHONG Yifan        attr = ctx.rule.attr,
252*d4726bddSHONG Yifan        crate_name = crate_name,
253*d4726bddSHONG Yifan        src = lib_rs,
254*d4726bddSHONG Yifan        deps = deps,
255*d4726bddSHONG Yifan        edition = RUST_EDITION,
256*d4726bddSHONG Yifan    )
257*d4726bddSHONG Yifan
258*d4726bddSHONG Yifan    # Always add `test` & `debug_assertions`. See rust-analyzer source code:
259*d4726bddSHONG Yifan    # https://github.com/rust-analyzer/rust-analyzer/blob/2021-11-15/crates/project_model/src/workspace.rs#L529-L531
260*d4726bddSHONG Yifan    cfgs = ["test", "debug_assertions"]
261*d4726bddSHONG Yifan
262*d4726bddSHONG Yifan    rust_analyzer_info = write_rust_analyzer_spec_file(ctx, ctx.rule.attr, ctx.label, RustAnalyzerInfo(
263*d4726bddSHONG Yifan        aliases = {},
264*d4726bddSHONG Yifan        crate = dep_variant_info.crate_info,
265*d4726bddSHONG Yifan        cfgs = cfgs,
266*d4726bddSHONG Yifan        env = dep_variant_info.crate_info.rustc_env,
267*d4726bddSHONG Yifan        deps = rust_analyzer_deps,
268*d4726bddSHONG Yifan        crate_specs = depset(transitive = [dep.crate_specs for dep in rust_analyzer_deps]),
269*d4726bddSHONG Yifan        proc_macro_dylib_path = None,
270*d4726bddSHONG Yifan        build_info = dep_variant_info.build_info,
271*d4726bddSHONG Yifan    ))
272*d4726bddSHONG Yifan
273*d4726bddSHONG Yifan    return [
274*d4726bddSHONG Yifan        ProstProtoInfo(
275*d4726bddSHONG Yifan            dep_variant_info = dep_variant_info,
276*d4726bddSHONG Yifan            transitive_dep_infos = depset(transitive = transitive_deps),
277*d4726bddSHONG Yifan            package_info = package_info_file,
278*d4726bddSHONG Yifan        ),
279*d4726bddSHONG Yifan        rust_analyzer_info,
280*d4726bddSHONG Yifan        OutputGroupInfo(rust_generated_srcs = [lib_rs]),
281*d4726bddSHONG Yifan    ]
282*d4726bddSHONG Yifan
283*d4726bddSHONG Yifanrust_prost_aspect = aspect(
284*d4726bddSHONG Yifan    doc = "An aspect used to generate and compile proto files with Prost.",
285*d4726bddSHONG Yifan    implementation = _rust_prost_aspect_impl,
286*d4726bddSHONG Yifan    attr_aspects = ["deps"],
287*d4726bddSHONG Yifan    attrs = {
288*d4726bddSHONG Yifan        "_collect_cc_coverage": attr.label(
289*d4726bddSHONG Yifan            default = Label("//util:collect_coverage"),
290*d4726bddSHONG Yifan            executable = True,
291*d4726bddSHONG Yifan            cfg = "exec",
292*d4726bddSHONG Yifan        ),
293*d4726bddSHONG Yifan        "_grep_includes": attr.label(
294*d4726bddSHONG Yifan            allow_single_file = True,
295*d4726bddSHONG Yifan            default = Label("@bazel_tools//tools/cpp:grep-includes"),
296*d4726bddSHONG Yifan            cfg = "exec",
297*d4726bddSHONG Yifan        ),
298*d4726bddSHONG Yifan        "_prost_process_wrapper": attr.label(
299*d4726bddSHONG Yifan            doc = "The wrapper script for the Prost protoc plugin.",
300*d4726bddSHONG Yifan            cfg = "exec",
301*d4726bddSHONG Yifan            executable = True,
302*d4726bddSHONG Yifan            default = Label("//proto/prost/private:protoc_wrapper"),
303*d4726bddSHONG Yifan        ),
304*d4726bddSHONG Yifan    } | RUSTC_ATTRS,
305*d4726bddSHONG Yifan    fragments = ["cpp"],
306*d4726bddSHONG Yifan    toolchains = [
307*d4726bddSHONG Yifan        TOOLCHAIN_TYPE,
308*d4726bddSHONG Yifan        "@bazel_tools//tools/cpp:toolchain_type",
309*d4726bddSHONG Yifan        "@rules_rust//rust:toolchain_type",
310*d4726bddSHONG Yifan        "@rules_rust//rust/rustfmt:toolchain_type",
311*d4726bddSHONG Yifan    ],
312*d4726bddSHONG Yifan)
313*d4726bddSHONG Yifan
314*d4726bddSHONG Yifandef _rust_prost_library_impl(ctx):
315*d4726bddSHONG Yifan    proto_dep = ctx.attr.proto
316*d4726bddSHONG Yifan    rust_proto_info = proto_dep[ProstProtoInfo]
317*d4726bddSHONG Yifan    dep_variant_info = rust_proto_info.dep_variant_info
318*d4726bddSHONG Yifan
319*d4726bddSHONG Yifan    return [
320*d4726bddSHONG Yifan        DefaultInfo(files = depset([dep_variant_info.crate_info.output])),
321*d4726bddSHONG Yifan        rust_common.crate_group_info(
322*d4726bddSHONG Yifan            dep_variant_infos = depset(
323*d4726bddSHONG Yifan                [dep_variant_info],
324*d4726bddSHONG Yifan                transitive = [rust_proto_info.transitive_dep_infos],
325*d4726bddSHONG Yifan            ),
326*d4726bddSHONG Yifan        ),
327*d4726bddSHONG Yifan        RustAnalyzerGroupInfo(deps = [proto_dep[RustAnalyzerInfo]]),
328*d4726bddSHONG Yifan    ]
329*d4726bddSHONG Yifan
330*d4726bddSHONG Yifanrust_prost_library = rule(
331*d4726bddSHONG Yifan    doc = "A rule for generating a Rust library using Prost.",
332*d4726bddSHONG Yifan    implementation = _rust_prost_library_impl,
333*d4726bddSHONG Yifan    attrs = {
334*d4726bddSHONG Yifan        "proto": attr.label(
335*d4726bddSHONG Yifan            doc = "A `proto_library` target for which to generate Rust gencode.",
336*d4726bddSHONG Yifan            providers = [ProtoInfo],
337*d4726bddSHONG Yifan            aspects = [rust_prost_aspect],
338*d4726bddSHONG Yifan            mandatory = True,
339*d4726bddSHONG Yifan        ),
340*d4726bddSHONG Yifan        "_collect_cc_coverage": attr.label(
341*d4726bddSHONG Yifan            default = Label("@rules_rust//util:collect_coverage"),
342*d4726bddSHONG Yifan            executable = True,
343*d4726bddSHONG Yifan            cfg = "exec",
344*d4726bddSHONG Yifan        ),
345*d4726bddSHONG Yifan    },
346*d4726bddSHONG Yifan)
347*d4726bddSHONG Yifan
348*d4726bddSHONG Yifandef _rust_prost_toolchain_impl(ctx):
349*d4726bddSHONG Yifan    tonic_attrs = [ctx.attr.tonic_plugin_flag, ctx.attr.tonic_plugin, ctx.attr.tonic_runtime]
350*d4726bddSHONG Yifan    if any(tonic_attrs) and not all(tonic_attrs):
351*d4726bddSHONG Yifan        fail("When one tonic attribute is added, all must be added")
352*d4726bddSHONG Yifan
353*d4726bddSHONG Yifan    if ctx.attr.proto_compiler:
354*d4726bddSHONG Yifan        # buildifier: disable=print
355*d4726bddSHONG Yifan        print("WARN: rust_prost_toolchain's proto_compiler attribute is deprecated. Make sure your rules_proto dependency is at least version 6.0.0 and stop setting proto_compiler")
356*d4726bddSHONG Yifan
357*d4726bddSHONG Yifan    proto_toolchain = proto_toolchains.find_toolchain(
358*d4726bddSHONG Yifan        ctx,
359*d4726bddSHONG Yifan        legacy_attr = "_legacy_proto_toolchain",
360*d4726bddSHONG Yifan        toolchain_type = "@rules_proto//proto:toolchain_type",
361*d4726bddSHONG Yifan    )
362*d4726bddSHONG Yifan
363*d4726bddSHONG Yifan    return [platform_common.ToolchainInfo(
364*d4726bddSHONG Yifan        prost_opts = ctx.attr.prost_opts,
365*d4726bddSHONG Yifan        prost_plugin = ctx.attr.prost_plugin,
366*d4726bddSHONG Yifan        prost_plugin_flag = ctx.attr.prost_plugin_flag,
367*d4726bddSHONG Yifan        prost_runtime = ctx.attr.prost_runtime,
368*d4726bddSHONG Yifan        prost_types = ctx.attr.prost_types,
369*d4726bddSHONG Yifan        proto_compiler = ctx.attr.proto_compiler or proto_toolchain.proto_compiler,
370*d4726bddSHONG Yifan        protoc_opts = ctx.fragments.proto.experimental_protoc_opts,
371*d4726bddSHONG Yifan        tonic_opts = ctx.attr.tonic_opts,
372*d4726bddSHONG Yifan        tonic_plugin = ctx.attr.tonic_plugin,
373*d4726bddSHONG Yifan        tonic_plugin_flag = ctx.attr.tonic_plugin_flag,
374*d4726bddSHONG Yifan        tonic_runtime = ctx.attr.tonic_runtime,
375*d4726bddSHONG Yifan    )]
376*d4726bddSHONG Yifan
377*d4726bddSHONG Yifanrust_prost_toolchain = rule(
378*d4726bddSHONG Yifan    implementation = _rust_prost_toolchain_impl,
379*d4726bddSHONG Yifan    doc = "Rust Prost toolchain rule.",
380*d4726bddSHONG Yifan    fragments = ["proto"],
381*d4726bddSHONG Yifan    attrs = dict({
382*d4726bddSHONG Yifan        "prost_opts": attr.string_list(
383*d4726bddSHONG Yifan            doc = "Additional options to add to Prost.",
384*d4726bddSHONG Yifan        ),
385*d4726bddSHONG Yifan        "prost_plugin": attr.label(
386*d4726bddSHONG Yifan            doc = "Additional plugins to add to Prost.",
387*d4726bddSHONG Yifan            cfg = "exec",
388*d4726bddSHONG Yifan            executable = True,
389*d4726bddSHONG Yifan            mandatory = True,
390*d4726bddSHONG Yifan        ),
391*d4726bddSHONG Yifan        "prost_plugin_flag": attr.string(
392*d4726bddSHONG Yifan            doc = "Prost plugin flag format. (e.g. `--plugin=protoc-gen-prost=%s`)",
393*d4726bddSHONG Yifan            default = "--plugin=protoc-gen-prost=%s",
394*d4726bddSHONG Yifan        ),
395*d4726bddSHONG Yifan        "prost_runtime": attr.label(
396*d4726bddSHONG Yifan            doc = "The Prost runtime crates to use.",
397*d4726bddSHONG Yifan            providers = [[rust_common.crate_info], [rust_common.crate_group_info]],
398*d4726bddSHONG Yifan            mandatory = True,
399*d4726bddSHONG Yifan        ),
400*d4726bddSHONG Yifan        "prost_types": attr.label(
401*d4726bddSHONG Yifan            doc = "The Prost types crates to use.",
402*d4726bddSHONG Yifan            providers = [[rust_common.crate_info], [rust_common.crate_group_info]],
403*d4726bddSHONG Yifan            mandatory = True,
404*d4726bddSHONG Yifan        ),
405*d4726bddSHONG Yifan        "proto_compiler": attr.label(
406*d4726bddSHONG Yifan            doc = "The protoc compiler to use. Note that this attribute is deprecated - prefer to use --incompatible_enable_proto_toolchain_resolution.",
407*d4726bddSHONG Yifan            cfg = "exec",
408*d4726bddSHONG Yifan            executable = True,
409*d4726bddSHONG Yifan        ),
410*d4726bddSHONG Yifan        "tonic_opts": attr.string_list(
411*d4726bddSHONG Yifan            doc = "Additional options to add to Tonic.",
412*d4726bddSHONG Yifan        ),
413*d4726bddSHONG Yifan        "tonic_plugin": attr.label(
414*d4726bddSHONG Yifan            doc = "Additional plugins to add to Tonic.",
415*d4726bddSHONG Yifan            cfg = "exec",
416*d4726bddSHONG Yifan            executable = True,
417*d4726bddSHONG Yifan        ),
418*d4726bddSHONG Yifan        "tonic_plugin_flag": attr.string(
419*d4726bddSHONG Yifan            doc = "Tonic plugin flag format. (e.g. `--plugin=protoc-gen-tonic=%s`))",
420*d4726bddSHONG Yifan            default = "--plugin=protoc-gen-tonic=%s",
421*d4726bddSHONG Yifan        ),
422*d4726bddSHONG Yifan        "tonic_runtime": attr.label(
423*d4726bddSHONG Yifan            doc = "The Tonic runtime crates to use.",
424*d4726bddSHONG Yifan            providers = [[rust_common.crate_info], [rust_common.crate_group_info]],
425*d4726bddSHONG Yifan        ),
426*d4726bddSHONG Yifan    }, **proto_toolchains.if_legacy_toolchain({
427*d4726bddSHONG Yifan        "_legacy_proto_toolchain": attr.label(
428*d4726bddSHONG Yifan            default = "//proto/protobuf:legacy_proto_toolchain",
429*d4726bddSHONG Yifan        ),
430*d4726bddSHONG Yifan    })),
431*d4726bddSHONG Yifan    toolchains = proto_toolchains.use_toolchain("@rules_proto//proto:toolchain_type"),
432*d4726bddSHONG Yifan)
433*d4726bddSHONG Yifan
434*d4726bddSHONG Yifandef _current_prost_runtime_impl(ctx):
435*d4726bddSHONG Yifan    toolchain = ctx.toolchains[TOOLCHAIN_TYPE]
436*d4726bddSHONG Yifan
437*d4726bddSHONG Yifan    runtime_deps = []
438*d4726bddSHONG Yifan
439*d4726bddSHONG Yifan    for target in [toolchain.prost_runtime, toolchain.prost_types]:
440*d4726bddSHONG Yifan        if rust_common.crate_group_info in target:
441*d4726bddSHONG Yifan            crate_group_info = target[rust_common.crate_group_info]
442*d4726bddSHONG Yifan            runtime_deps.extend(crate_group_info.dep_variant_infos.to_list())
443*d4726bddSHONG Yifan        else:
444*d4726bddSHONG Yifan            runtime_deps.append(rust_common.dep_variant_info(
445*d4726bddSHONG Yifan                crate_info = target[rust_common.crate_info] if rust_common.crate_info in target else None,
446*d4726bddSHONG Yifan                dep_info = target[rust_common.dep_info] if rust_common.dep_info in target else None,
447*d4726bddSHONG Yifan                cc_info = target[CcInfo] if CcInfo in target else None,
448*d4726bddSHONG Yifan                build_info = None,
449*d4726bddSHONG Yifan            ))
450*d4726bddSHONG Yifan
451*d4726bddSHONG Yifan    return [rust_common.crate_group_info(
452*d4726bddSHONG Yifan        dep_variant_infos = depset(runtime_deps),
453*d4726bddSHONG Yifan    )]
454*d4726bddSHONG Yifan
455*d4726bddSHONG Yifancurrent_prost_runtime = rule(
456*d4726bddSHONG Yifan    doc = "A rule for accessing the current Prost toolchain components needed by the process wrapper",
457*d4726bddSHONG Yifan    provides = [rust_common.crate_group_info],
458*d4726bddSHONG Yifan    implementation = _current_prost_runtime_impl,
459*d4726bddSHONG Yifan    toolchains = [TOOLCHAIN_TYPE],
460*d4726bddSHONG Yifan)
461