xref: /aosp_15_r20/external/grpc-grpc-java/java_grpc_library.bzl (revision e07d83d3ffcef9ecfc9f7f475418ec639ff0e5fe)
1"""Build rule for java_grpc_library."""
2
3_JavaRpcToolchainInfo = provider(
4    fields = [
5        "java_toolchain",
6        "plugin",
7        "plugin_arg",
8        "protoc",
9        "runtime",
10    ],
11)
12
13def _java_rpc_toolchain_impl(ctx):
14    return [
15        _JavaRpcToolchainInfo(
16            java_toolchain = ctx.attr._java_toolchain,
17            plugin = ctx.executable.plugin,
18            plugin_arg = ctx.attr.plugin_arg,
19            protoc = ctx.executable._protoc,
20            runtime = ctx.attr.runtime,
21        ),
22        platform_common.ToolchainInfo(),  # Magic for b/78647825
23    ]
24
25java_rpc_toolchain = rule(
26    attrs = {
27        # This attribute has a "magic" name recognized by the native DexArchiveAspect (b/78647825).
28        "runtime": attr.label_list(
29            cfg = "target",
30            providers = [JavaInfo],
31        ),
32        "plugin": attr.label(
33            cfg = "exec",
34            executable = True,
35        ),
36        "plugin_arg": attr.string(),
37        "_protoc": attr.label(
38            cfg = "exec",
39            default = Label("@com_google_protobuf//:protoc"),
40            executable = True,
41        ),
42        "_java_toolchain": attr.label(
43            default = Label("@bazel_tools//tools/jdk:current_java_toolchain"),
44        ),
45    },
46    provides = [
47        _JavaRpcToolchainInfo,
48        platform_common.ToolchainInfo,
49    ],
50    implementation = _java_rpc_toolchain_impl,
51)
52
53# "repository" here is for Bazel builds that span multiple WORKSPACES.
54def _path_ignoring_repository(f):
55    # Bazel creates a _virtual_imports directory in case the .proto source files
56    # need to be accessed at a path that's different from their source path:
57    # https://github.com/bazelbuild/bazel/blob/0.27.1/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCommon.java#L289
58    #
59    # In that case, the import path of the .proto file is the path relative to
60    # the virtual imports directory of the rule in question.
61    virtual_imports = "/_virtual_imports/"
62    if virtual_imports in f.path:
63        return f.path.split(virtual_imports)[1].split("/", 1)[1]
64    elif len(f.owner.workspace_root) == 0:
65        # |f| is in the main repository
66        return f.short_path
67    else:
68        # If |f| is a generated file, it will have "bazel-out/*/genfiles" prefix
69        # before "external/workspace", so we need to add the starting index of "external/workspace"
70        return f.path[f.path.find(f.owner.workspace_root) + len(f.owner.workspace_root) + 1:]
71
72def _java_rpc_library_impl(ctx):
73    if len(ctx.attr.srcs) != 1:
74        fail("Exactly one src value supported", "srcs")
75    if ctx.attr.srcs[0].label.package != ctx.label.package:
76        print(("in srcs attribute of {0}: Proto source with label {1} should be in " +
77               "same package as consuming rule").format(ctx.label, ctx.attr.srcs[0].label))
78
79    toolchain = ctx.attr._toolchain[_JavaRpcToolchainInfo]
80    srcs = ctx.attr.srcs[0][ProtoInfo].direct_sources
81    descriptor_set_in = ctx.attr.srcs[0][ProtoInfo].transitive_descriptor_sets
82
83    srcjar = ctx.actions.declare_file("%s-proto-gensrc.jar" % ctx.label.name)
84
85    args = ctx.actions.args()
86    args.add(toolchain.plugin, format = "--plugin=protoc-gen-rpc-plugin=%s")
87    args.add("--rpc-plugin_out={0}:{1}".format(toolchain.plugin_arg, srcjar.path))
88    args.add_joined("--descriptor_set_in", descriptor_set_in, join_with = ctx.configuration.host_path_separator)
89    args.add_all(srcs, map_each = _path_ignoring_repository)
90
91    ctx.actions.run(
92        inputs = depset([toolchain.plugin] + srcs, transitive = [descriptor_set_in]),
93        outputs = [srcjar],
94        executable = toolchain.protoc,
95        arguments = [args],
96        use_default_shell_env = True,
97    )
98
99    deps_java_info = java_common.merge([dep[JavaInfo] for dep in ctx.attr.deps])
100
101    java_info = java_common.compile(
102        ctx,
103        java_toolchain = toolchain.java_toolchain[java_common.JavaToolchainInfo],
104        source_jars = [srcjar],
105        output = ctx.outputs.jar,
106        output_source_jar = ctx.outputs.srcjar,
107        deps = [
108            java_common.make_non_strict(deps_java_info),
109        ] + [dep[JavaInfo] for dep in toolchain.runtime],
110    )
111
112    return [java_info]
113
114_java_grpc_library = rule(
115    attrs = {
116        "srcs": attr.label_list(
117            mandatory = True,
118            allow_empty = False,
119            providers = [ProtoInfo],
120        ),
121        "deps": attr.label_list(
122            mandatory = True,
123            allow_empty = False,
124            providers = [JavaInfo],
125        ),
126        "_toolchain": attr.label(
127            default = Label("//compiler:java_grpc_library_toolchain"),
128        ),
129    },
130    toolchains = ["@bazel_tools//tools/jdk:toolchain_type"],
131    fragments = ["java"],
132    outputs = {
133        "jar": "lib%{name}.jar",
134        "srcjar": "lib%{name}-src.jar",
135    },
136    provides = [JavaInfo],
137    implementation = _java_rpc_library_impl,
138)
139
140_java_lite_grpc_library = rule(
141    attrs = {
142        "srcs": attr.label_list(
143            mandatory = True,
144            allow_empty = False,
145            providers = [ProtoInfo],
146        ),
147        "deps": attr.label_list(
148            mandatory = True,
149            allow_empty = False,
150            providers = [JavaInfo],
151        ),
152        # This attribute has a "magic" name recognized by the native DexArchiveAspect (b/78647825).
153        "_toolchain": attr.label(
154            default = Label("//compiler:java_lite_grpc_library_toolchain"),
155        ),
156    },
157    toolchains = ["@bazel_tools//tools/jdk:toolchain_type"],
158    fragments = ["java"],
159    outputs = {
160        "jar": "lib%{name}.jar",
161        "srcjar": "lib%{name}-src.jar",
162    },
163    provides = [JavaInfo],
164    implementation = _java_rpc_library_impl,
165)
166
167def java_grpc_library(
168        name,
169        srcs,
170        deps,
171        flavor = None,
172        **kwargs):
173    """Generates gRPC Java code for services in a `proto_library`.
174
175    This rule only generates code for services; it does not generate code for
176    messages. You will need a separate java_proto_library or
177    java_lite_proto_library rule.
178
179    Args:
180      name: A unique name for this rule.
181      srcs: (List of `labels`) a single proto_library target that contains the
182        schema of the service.
183      deps: (List of `labels`) a single java_proto_library or
184        java_lite_proto_library target for the proto_library in srcs.
185      flavor: (str) "normal" (default) for normal proto runtime. "lite"
186        for the lite runtime.
187      **kwargs: Other common attributes
188    """
189
190    if len(deps) > 1:
191        print("Multiple values in 'deps' is deprecated in " + name)
192
193    if flavor == None or flavor == "normal":
194        _java_grpc_library(
195            name = name,
196            srcs = srcs,
197            deps = deps,
198            **kwargs
199        )
200    elif flavor == "lite":
201        _java_lite_grpc_library(
202            name = name,
203            srcs = srcs,
204            deps = deps,
205            **kwargs
206        )
207    else:
208        fail("Flavor must be normal or lite")
209