1"""Generates and compiles C++ grpc stubs from proto_library rules."""
2
3load("@rules_proto//proto:defs.bzl", "proto_library")
4load("//bazel:generate_cc.bzl", "generate_cc")
5load("//bazel:protobuf.bzl", "well_known_proto_libs")
6
7def cc_grpc_library(
8        name,
9        srcs,
10        deps,
11        proto_only = False,
12        well_known_protos = False,
13        generate_mocks = False,
14        use_external = False,
15        grpc_only = False,
16        **kwargs):
17    """Generates C++ grpc classes for services defined in a proto file.
18
19    If grpc_only is True, this rule is compatible with proto_library and
20    cc_proto_library native rules such that it expects proto_library target
21    as srcs argument and generates only grpc library classes, expecting
22    protobuf messages classes library (cc_proto_library target) to be passed in
23    deps argument. By default grpc_only is False which makes this rule to behave
24    in a backwards-compatible mode (trying to generate both proto and grpc
25    classes).
26
27    Assumes the generated classes will be used in cc_api_version = 2.
28
29    Args:
30        name (str): Name of rule.
31        srcs (list): A single .proto file which contains services definitions,
32          or if grpc_only parameter is True, a single proto_library which
33          contains services descriptors.
34        deps (list): A list of C++ proto_library (or cc_proto_library) which
35          provides the compiled code of any message that the services depend on.
36        proto_only (bool): If True, create only C++ proto classes library,
37          avoid creating C++ grpc classes library (expect it in deps).
38          Deprecated, use native cc_proto_library instead. False by default.
39        well_known_protos (bool): Should this library additionally depend on
40          well known protos. Deprecated, the well known protos should be
41          specified as explicit dependencies of the proto_library target
42          (passed in srcs parameter) instead. False by default.
43        generate_mocks (bool): when True, Google Mock code for client stub is
44          generated. False by default.
45        use_external (bool): Not used.
46        grpc_only (bool): if True, generate only grpc library, expecting
47          protobuf messages library (cc_proto_library target) to be passed as
48          deps. False by default (will become True by default eventually).
49        **kwargs: rest of arguments, e.g., compatible_with and visibility
50    """
51    if len(srcs) > 1:
52        fail("Only one srcs value supported", "srcs")
53    if grpc_only and proto_only:
54        fail("A mutualy exclusive configuration is specified: grpc_only = True and proto_only = True")
55
56    extra_deps = []
57    proto_targets = []
58
59    if not grpc_only:
60        proto_target = "_" + name + "_only"
61        cc_proto_target = name if proto_only else "_" + name + "_cc_proto"
62
63        proto_deps = ["_" + dep + "_only" for dep in deps if dep.find(":") == -1]
64        proto_deps += [dep.split(":")[0] + ":" + "_" + dep.split(":")[1] + "_only" for dep in deps if dep.find(":") != -1]
65        if well_known_protos:
66            proto_deps += well_known_proto_libs()
67        proto_library(
68            name = proto_target,
69            srcs = srcs,
70            deps = proto_deps,
71            **kwargs
72        )
73
74        native.cc_proto_library(
75            name = cc_proto_target,
76            deps = [":" + proto_target],
77            **kwargs
78        )
79        extra_deps.append(":" + cc_proto_target)
80        proto_targets.append(proto_target)
81    else:
82        if not srcs:
83            fail("srcs cannot be empty", "srcs")
84        proto_targets += srcs
85
86    if not proto_only:
87        codegen_grpc_target = "_" + name + "_grpc_codegen"
88        generate_cc(
89            name = codegen_grpc_target,
90            srcs = proto_targets,
91            plugin = "@com_github_grpc_grpc//src/compiler:grpc_cpp_plugin",
92            well_known_protos = well_known_protos,
93            generate_mocks = generate_mocks,
94            **kwargs
95        )
96
97        native.cc_library(
98            name = name,
99            srcs = [":" + codegen_grpc_target],
100            hdrs = [":" + codegen_grpc_target],
101            deps = deps +
102                   extra_deps +
103                   ["@com_github_grpc_grpc//:grpc++_codegen_proto"],
104            **kwargs
105        )
106