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