1# Copyright (C) 2021 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15load("//build/bazel/rules:proto_file_utils.bzl", "proto_file_utils")
16load(":library.bzl", "java_library")
17
18def _java_proto_sources_gen_rule_impl(ctx):
19    out_flags = []
20    plugin_executable = None
21    out_arg = None
22    if ctx.attr.plugin:
23        plugin_executable = ctx.executable.plugin
24    else:
25        out_arg = "--java_out"
26        if ctx.attr.out_format:
27            out_flags.append(ctx.attr.out_format)
28
29    srcs = []
30    proto_infos = []
31
32    for dep in ctx.attr.deps:
33        proto_infos.append(dep[ProtoInfo])
34
35    out_jar = _generate_java_proto_action(
36        proto_infos = proto_infos,
37        protoc = ctx.executable._protoc,
38        ctx = ctx,
39        out_flags = out_flags,
40        plugin_executable = plugin_executable,
41        out_arg = out_arg,
42        transitive_proto_infos = [dep[ProtoInfo] for dep in ctx.attr.transitive_deps],
43    )
44    srcs.append(out_jar)
45
46    return [
47        DefaultInfo(files = depset(direct = srcs)),
48    ]
49
50java_proto_sources_gen = rule(
51    implementation = _java_proto_sources_gen_rule_impl,
52    attrs = {
53        "deps": attr.label_list(
54            providers = [ProtoInfo],
55            doc = """
56proto_library or any other target exposing ProtoInfo provider with *.proto files
57""",
58            mandatory = True,
59        ),
60        "transitive_deps": attr.label_list(
61            providers = [ProtoInfo],
62            doc = """
63proto_library that will be added to aprotoc -I when compiling the direct .proto sources.
64WARNING: This is an experimental attribute and is expected to be deprecated in the future.
65""",
66        ),
67        "_protoc": attr.label(
68            default = Label("//external/protobuf:aprotoc"),
69            executable = True,
70            cfg = "exec",
71        ),
72        "plugin": attr.label(
73            executable = True,
74            cfg = "exec",
75        ),
76        "out_format": attr.string(
77            doc = """
78Optional argument specifying the out format, e.g. lite.
79If not provided, defaults to full protos.
80""",
81        ),
82    },
83    toolchains = ["@bazel_tools//tools/jdk:toolchain_type"],
84)
85
86def _generate_java_proto_action(
87        proto_infos,
88        protoc,
89        ctx,
90        plugin_executable,
91        out_arg,
92        out_flags,
93        transitive_proto_infos):
94    return proto_file_utils.generate_jar_proto_action(
95        proto_infos,
96        protoc,
97        ctx,
98        out_flags,
99        plugin_executable = plugin_executable,
100        out_arg = out_arg,
101        mnemonic = "JavaProtoGen",
102        transitive_proto_infos = transitive_proto_infos,
103    )
104
105def _java_proto_library(
106        name,
107        deps = [],
108        transitive_deps = [],
109        plugin = None,
110        out_format = None,
111        proto_dep = None,
112        sdk_version = "core_current",
113        **kwargs):
114    proto_sources_name = name + "_proto_gen"
115
116    java_proto_sources_gen(
117        name = proto_sources_name,
118        deps = deps,
119        transitive_deps = transitive_deps,
120        plugin = plugin,
121        out_format = out_format,
122        tags = ["manual"],
123    )
124
125    deps = kwargs.pop("additional_proto_deps", [])
126    if proto_dep and proto_dep not in deps:
127        deps.append(proto_dep)
128
129    java_library(
130        name = name,
131        srcs = [proto_sources_name],
132        deps = deps,
133        sdk_version = sdk_version,
134        exports = [proto_dep],
135        **kwargs
136    )
137
138def java_nano_proto_library(
139        name,
140        plugin = "//external/protobuf:protoc-gen-javanano",
141        **kwargs):
142    _java_proto_library(
143        name,
144        plugin = plugin,
145        proto_dep = "//external/protobuf:libprotobuf-java-nano",
146        **kwargs
147    )
148
149def java_micro_proto_library(
150        name,
151        plugin = "//external/protobuf:protoc-gen-javamicro",
152        **kwargs):
153    _java_proto_library(
154        name,
155        plugin = plugin,
156        proto_dep = "//external/protobuf:libprotobuf-java-micro",
157        **kwargs
158    )
159
160def java_lite_proto_library(
161        name,
162        plugin = None,
163        **kwargs):
164    _java_proto_library(
165        name,
166        plugin = plugin,
167        out_format = "lite",
168        proto_dep = "//external/protobuf:libprotobuf-java-lite",
169        **kwargs
170    )
171
172def java_stream_proto_library(
173        name,
174        plugin = "//frameworks/base/tools/streaming_proto:protoc-gen-javastream",
175        **kwargs):
176    _java_proto_library(
177        name,
178        plugin = plugin,
179        **kwargs
180    )
181
182def java_proto_library(
183        name,
184        plugin = None,
185        **kwargs):
186    _java_proto_library(
187        name,
188        plugin = plugin,
189        proto_dep = "//external/protobuf:libprotobuf-java-full",
190        **kwargs
191    )
192