xref: /aosp_15_r20/external/dagger2/tools/maven.bzl (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1*f585d8a3SJacky Wang# Copyright (C) 2018 The Dagger Authors.
2*f585d8a3SJacky Wang#
3*f585d8a3SJacky Wang# Licensed under the Apache License, Version 2.0 (the "License");
4*f585d8a3SJacky Wang# you may not use this file except in compliance with the License.
5*f585d8a3SJacky Wang# You may obtain a copy of the License at
6*f585d8a3SJacky Wang#
7*f585d8a3SJacky Wang# http://www.apache.org/licenses/LICENSE-2.0
8*f585d8a3SJacky Wang#
9*f585d8a3SJacky Wang# Unless required by applicable law or agreed to in writing, software
10*f585d8a3SJacky Wang# distributed under the License is distributed on an "AS IS" BASIS,
11*f585d8a3SJacky Wang# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*f585d8a3SJacky Wang# See the License for the specific language governing permissions and
13*f585d8a3SJacky Wang# limitations under the License.
14*f585d8a3SJacky Wang
15*f585d8a3SJacky Wang"""Macros to simplify generating maven files.
16*f585d8a3SJacky Wang"""
17*f585d8a3SJacky Wang
18*f585d8a3SJacky Wangload("@google_bazel_common//tools/jarjar:jarjar.bzl", "jarjar_library")
19*f585d8a3SJacky Wangload("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
20*f585d8a3SJacky Wangload("@google_bazel_common//tools/maven:pom_file.bzl", default_pom_file = "pom_file")
21*f585d8a3SJacky Wangload(":maven_info.bzl", "MavenInfo", "collect_maven_info")
22*f585d8a3SJacky Wang
23*f585d8a3SJacky WangSHADED_MAVEN_DEPS = [
24*f585d8a3SJacky Wang    "com.google.auto:auto-common",
25*f585d8a3SJacky Wang    "org.jetbrains.kotlinx:kotlinx-metadata-jvm",
26*f585d8a3SJacky Wang]
27*f585d8a3SJacky Wang
28*f585d8a3SJacky Wangdef pom_file(name, targets, artifact_name, artifact_id, packaging = None, **kwargs):
29*f585d8a3SJacky Wang    default_pom_file(
30*f585d8a3SJacky Wang        name = name,
31*f585d8a3SJacky Wang        targets = targets,
32*f585d8a3SJacky Wang        preferred_group_ids = [
33*f585d8a3SJacky Wang            "com.google.dagger",
34*f585d8a3SJacky Wang            "com.google",
35*f585d8a3SJacky Wang        ],
36*f585d8a3SJacky Wang        template_file = "//tools:pom-template.xml",
37*f585d8a3SJacky Wang        substitutions = {
38*f585d8a3SJacky Wang            "{artifact_name}": artifact_name,
39*f585d8a3SJacky Wang            "{artifact_id}": artifact_id,
40*f585d8a3SJacky Wang            "{packaging}": packaging or "jar",
41*f585d8a3SJacky Wang        },
42*f585d8a3SJacky Wang        # NOTE: The shaded maven dependencies are excluded from every Dagger pom file.
43*f585d8a3SJacky Wang        # Thus, if a Dagger artifact needs the dependencies it must jarjar the dependency
44*f585d8a3SJacky Wang        # into the artifact itself using the gen_maven_artifact.shaded_deps or get it from
45*f585d8a3SJacky Wang        # a transitive Dagger artifact as a dependency. In addition, the artifact must add
46*f585d8a3SJacky Wang        # the shade rules in the deploy scripts, e.g. deploy-dagger.sh.
47*f585d8a3SJacky Wang        excluded_artifacts = SHADED_MAVEN_DEPS,
48*f585d8a3SJacky Wang        **kwargs
49*f585d8a3SJacky Wang    )
50*f585d8a3SJacky Wang
51*f585d8a3SJacky Wangdef gen_maven_artifact(
52*f585d8a3SJacky Wang        name,
53*f585d8a3SJacky Wang        artifact_name,
54*f585d8a3SJacky Wang        artifact_coordinates,
55*f585d8a3SJacky Wang        artifact_target,
56*f585d8a3SJacky Wang        artifact_target_libs = None,
57*f585d8a3SJacky Wang        artifact_target_maven_deps = None,
58*f585d8a3SJacky Wang        artifact_target_maven_deps_banned = None,
59*f585d8a3SJacky Wang        testonly = 0,
60*f585d8a3SJacky Wang        pom_name = "pom",
61*f585d8a3SJacky Wang        packaging = None,
62*f585d8a3SJacky Wang        javadoc_srcs = None,
63*f585d8a3SJacky Wang        javadoc_root_packages = None,
64*f585d8a3SJacky Wang        javadoc_exclude_packages = None,
65*f585d8a3SJacky Wang        javadoc_android_api_level = None,
66*f585d8a3SJacky Wang        shaded_deps = None,
67*f585d8a3SJacky Wang        manifest = None,
68*f585d8a3SJacky Wang        lint_deps = None,
69*f585d8a3SJacky Wang        proguard_and_r8_specs = None,
70*f585d8a3SJacky Wang        r8_specs = None,
71*f585d8a3SJacky Wang        proguard_specs = None):
72*f585d8a3SJacky Wang    _gen_maven_artifact(
73*f585d8a3SJacky Wang        name,
74*f585d8a3SJacky Wang        artifact_name,
75*f585d8a3SJacky Wang        artifact_coordinates,
76*f585d8a3SJacky Wang        artifact_target,
77*f585d8a3SJacky Wang        artifact_target_libs,
78*f585d8a3SJacky Wang        artifact_target_maven_deps,
79*f585d8a3SJacky Wang        artifact_target_maven_deps_banned,
80*f585d8a3SJacky Wang        testonly,
81*f585d8a3SJacky Wang        pom_name,
82*f585d8a3SJacky Wang        packaging,
83*f585d8a3SJacky Wang        javadoc_srcs,
84*f585d8a3SJacky Wang        javadoc_root_packages,
85*f585d8a3SJacky Wang        javadoc_exclude_packages,
86*f585d8a3SJacky Wang        javadoc_android_api_level,
87*f585d8a3SJacky Wang        shaded_deps,
88*f585d8a3SJacky Wang        manifest,
89*f585d8a3SJacky Wang        lint_deps,
90*f585d8a3SJacky Wang        proguard_and_r8_specs,
91*f585d8a3SJacky Wang        r8_specs,
92*f585d8a3SJacky Wang        proguard_specs
93*f585d8a3SJacky Wang    )
94*f585d8a3SJacky Wang
95*f585d8a3SJacky Wangdef _gen_maven_artifact(
96*f585d8a3SJacky Wang        name,
97*f585d8a3SJacky Wang        artifact_name,
98*f585d8a3SJacky Wang        artifact_coordinates,
99*f585d8a3SJacky Wang        artifact_target,
100*f585d8a3SJacky Wang        artifact_target_libs,
101*f585d8a3SJacky Wang        artifact_target_maven_deps,
102*f585d8a3SJacky Wang        artifact_target_maven_deps_banned,
103*f585d8a3SJacky Wang        testonly,
104*f585d8a3SJacky Wang        pom_name,
105*f585d8a3SJacky Wang        packaging,
106*f585d8a3SJacky Wang        javadoc_srcs,
107*f585d8a3SJacky Wang        javadoc_root_packages,
108*f585d8a3SJacky Wang        javadoc_exclude_packages,
109*f585d8a3SJacky Wang        javadoc_android_api_level,
110*f585d8a3SJacky Wang        shaded_deps,
111*f585d8a3SJacky Wang        manifest,
112*f585d8a3SJacky Wang        lint_deps,
113*f585d8a3SJacky Wang        proguard_and_r8_specs,
114*f585d8a3SJacky Wang        r8_specs,
115*f585d8a3SJacky Wang        proguard_specs):
116*f585d8a3SJacky Wang    """Generates the files required for a maven artifact.
117*f585d8a3SJacky Wang
118*f585d8a3SJacky Wang    This macro generates the following targets:
119*f585d8a3SJacky Wang        * ":pom": The pom file for the given target and deps
120*f585d8a3SJacky Wang        * ":<NAME>": The artifact file for the given target and deps
121*f585d8a3SJacky Wang        * ":<NAME>-src": The sources jar file for the given target and deps
122*f585d8a3SJacky Wang        * ":<NAME>-javadoc": The javadocs jar file for the given target and deps
123*f585d8a3SJacky Wang
124*f585d8a3SJacky Wang    This macro also validates a few things. First, it validates that the
125*f585d8a3SJacky Wang    given "target" is a maven artifact (i.e. the "tags" attribute contains
126*f585d8a3SJacky Wang    "maven_coordinates=..."). Second, it calculates the list of transitive
127*f585d8a3SJacky Wang    dependencies of the target that are not owned by another maven artifact,
128*f585d8a3SJacky Wang    and validates that the given "deps" matches exactly.
129*f585d8a3SJacky Wang
130*f585d8a3SJacky Wang    Args:
131*f585d8a3SJacky Wang      name: The name associated with the various output targets.
132*f585d8a3SJacky Wang      artifact_target: The target containing the maven_coordinates.
133*f585d8a3SJacky Wang      artifact_name: The name of the maven artifact.
134*f585d8a3SJacky Wang      artifact_coordinates: The coordinates of the maven artifact in the
135*f585d8a3SJacky Wang                            form: "<group_id>:<artifact_id>:<version>"
136*f585d8a3SJacky Wang      artifact_target_libs: The set of transitive libraries of the target.
137*f585d8a3SJacky Wang      artifact_target_maven_deps: The required maven deps of the target.
138*f585d8a3SJacky Wang      artifact_target_maven_deps_banned: The banned maven deps of the target.
139*f585d8a3SJacky Wang      testonly: True if the jar should be testonly.
140*f585d8a3SJacky Wang      packaging: The packaging of the maven artifact. E.g. "aar"
141*f585d8a3SJacky Wang      pom_name: The name of the pom file (or "pom" if absent).
142*f585d8a3SJacky Wang      javadoc_srcs: The srcs for the javadocs.
143*f585d8a3SJacky Wang      javadoc_root_packages: The root packages for the javadocs.
144*f585d8a3SJacky Wang      javadoc_exclude_packages: The packages to exclude from the javadocs.
145*f585d8a3SJacky Wang      javadoc_android_api_level: The android api level for the javadocs.
146*f585d8a3SJacky Wang      shaded_deps: The shaded deps for the jarjar.
147*f585d8a3SJacky Wang      manifest: The AndroidManifest.xml to bundle in when packaing an 'aar'.
148*f585d8a3SJacky Wang      lint_deps: The lint targets to be bundled in when packaging an 'aar'.
149*f585d8a3SJacky Wang      proguard_and_r8_specs: The proguard spec files to be bundled in when
150*f585d8a3SJacky Wang                             packaging an 'aar', which will be applied in
151*f585d8a3SJacky Wang                             both r8 and proguard.
152*f585d8a3SJacky Wang      r8_specs: The proguard spec files to be used only for r8 when packaging an 'jar'.
153*f585d8a3SJacky Wang      proguard_specs: The proguard spec files to be used only for proguard not r8 when
154*f585d8a3SJacky Wang                           packaging an 'jar'.
155*f585d8a3SJacky Wang    """
156*f585d8a3SJacky Wang
157*f585d8a3SJacky Wang    _validate_maven_deps(
158*f585d8a3SJacky Wang        name = name + "-validation",
159*f585d8a3SJacky Wang        testonly = 1,
160*f585d8a3SJacky Wang        target = artifact_target,
161*f585d8a3SJacky Wang        expected_artifact = artifact_coordinates,
162*f585d8a3SJacky Wang        expected_libs = artifact_target_libs,
163*f585d8a3SJacky Wang        expected_maven_deps = artifact_target_maven_deps,
164*f585d8a3SJacky Wang        banned_maven_deps = artifact_target_maven_deps_banned,
165*f585d8a3SJacky Wang    )
166*f585d8a3SJacky Wang
167*f585d8a3SJacky Wang    shaded_deps = shaded_deps or []
168*f585d8a3SJacky Wang    artifact_targets = [artifact_target] + (artifact_target_libs or [])
169*f585d8a3SJacky Wang    lint_deps = lint_deps or []
170*f585d8a3SJacky Wang
171*f585d8a3SJacky Wang    # META-INF resources files that can be combined by appending lines.
172*f585d8a3SJacky Wang    merge_meta_inf_files = [
173*f585d8a3SJacky Wang        "gradle/incremental.annotation.processors",
174*f585d8a3SJacky Wang    ]
175*f585d8a3SJacky Wang
176*f585d8a3SJacky Wang    artifact_id = artifact_coordinates.split(":")[1]
177*f585d8a3SJacky Wang    pom_file(
178*f585d8a3SJacky Wang        name = pom_name,
179*f585d8a3SJacky Wang        testonly = testonly,
180*f585d8a3SJacky Wang        artifact_id = artifact_id,
181*f585d8a3SJacky Wang        artifact_name = artifact_name,
182*f585d8a3SJacky Wang        packaging = packaging,
183*f585d8a3SJacky Wang        targets = artifact_targets,
184*f585d8a3SJacky Wang    )
185*f585d8a3SJacky Wang
186*f585d8a3SJacky Wang    if (packaging == "aar"):
187*f585d8a3SJacky Wang        jarjar_library(
188*f585d8a3SJacky Wang            name = name + "-classes",
189*f585d8a3SJacky Wang            testonly = testonly,
190*f585d8a3SJacky Wang            jars = artifact_targets + shaded_deps,
191*f585d8a3SJacky Wang            merge_meta_inf_files = merge_meta_inf_files,
192*f585d8a3SJacky Wang        )
193*f585d8a3SJacky Wang        if lint_deps:
194*f585d8a3SJacky Wang            # jarjar all lint artifacts since an aar only contains a single lint.jar.
195*f585d8a3SJacky Wang            jarjar_library(
196*f585d8a3SJacky Wang                name = name + "-lint",
197*f585d8a3SJacky Wang                jars = lint_deps,
198*f585d8a3SJacky Wang            )
199*f585d8a3SJacky Wang            lint_jar_name = name + "-lint.jar"
200*f585d8a3SJacky Wang        else:
201*f585d8a3SJacky Wang            lint_jar_name = None
202*f585d8a3SJacky Wang
203*f585d8a3SJacky Wang        if proguard_and_r8_specs:
204*f585d8a3SJacky Wang            # Concatenate all proguard rules since an aar only contains a single proguard.txt
205*f585d8a3SJacky Wang            native.genrule(
206*f585d8a3SJacky Wang                name = name + "-proguard",
207*f585d8a3SJacky Wang                srcs = proguard_and_r8_specs,
208*f585d8a3SJacky Wang                outs = [name + "-proguard.txt"],
209*f585d8a3SJacky Wang                cmd = "cat $(SRCS) > $@",
210*f585d8a3SJacky Wang            )
211*f585d8a3SJacky Wang            proguard_file = name + "-proguard.txt"
212*f585d8a3SJacky Wang        else:
213*f585d8a3SJacky Wang            proguard_file = None
214*f585d8a3SJacky Wang
215*f585d8a3SJacky Wang        _package_android_library(
216*f585d8a3SJacky Wang            name = name + "-android-lib",
217*f585d8a3SJacky Wang            manifest = manifest,
218*f585d8a3SJacky Wang            classesJar = name + "-classes.jar",
219*f585d8a3SJacky Wang            lintJar = lint_jar_name,
220*f585d8a3SJacky Wang            proguardSpec = proguard_file,
221*f585d8a3SJacky Wang        )
222*f585d8a3SJacky Wang
223*f585d8a3SJacky Wang        # Copy intermediate outputs to final one.
224*f585d8a3SJacky Wang        native.genrule(
225*f585d8a3SJacky Wang            name = name,
226*f585d8a3SJacky Wang            srcs = [name + "-android-lib"],
227*f585d8a3SJacky Wang            outs = [name + ".aar"],
228*f585d8a3SJacky Wang            cmd = "cp $< $@",
229*f585d8a3SJacky Wang        )
230*f585d8a3SJacky Wang    else:
231*f585d8a3SJacky Wang        # (TODO/322873492) add support for passing in general proguard rule.
232*f585d8a3SJacky Wang        if r8_specs:
233*f585d8a3SJacky Wang            # Concatenate all r8 rules.
234*f585d8a3SJacky Wang            native.genrule(
235*f585d8a3SJacky Wang                name = name + "-r8",
236*f585d8a3SJacky Wang                srcs = r8_specs,
237*f585d8a3SJacky Wang                outs = [name + "-r8.txt"],
238*f585d8a3SJacky Wang                cmd = "cat $(SRCS) > $@",
239*f585d8a3SJacky Wang            )
240*f585d8a3SJacky Wang            r8_file = name + "-r8.txt"
241*f585d8a3SJacky Wang        else:
242*f585d8a3SJacky Wang            r8_file = None
243*f585d8a3SJacky Wang
244*f585d8a3SJacky Wang        if proguard_specs:
245*f585d8a3SJacky Wang            # Concatenate all proguard only rules.
246*f585d8a3SJacky Wang            native.genrule(
247*f585d8a3SJacky Wang                name = name + "-proguard-only",
248*f585d8a3SJacky Wang                srcs = proguard_specs,
249*f585d8a3SJacky Wang                outs = [name + "-proguard-only.txt"],
250*f585d8a3SJacky Wang                cmd = "cat $(SRCS) > $@",
251*f585d8a3SJacky Wang            )
252*f585d8a3SJacky Wang            proguard_only_file = name + "-proguard-only.txt"
253*f585d8a3SJacky Wang        else:
254*f585d8a3SJacky Wang            proguard_only_file = None
255*f585d8a3SJacky Wang
256*f585d8a3SJacky Wang        jarjar_library(
257*f585d8a3SJacky Wang            name = name + "-classes",
258*f585d8a3SJacky Wang            testonly = testonly,
259*f585d8a3SJacky Wang            jars = artifact_targets + shaded_deps,
260*f585d8a3SJacky Wang            merge_meta_inf_files = merge_meta_inf_files,
261*f585d8a3SJacky Wang        )
262*f585d8a3SJacky Wang        jar_name = name + "-classes.jar"
263*f585d8a3SJacky Wang
264*f585d8a3SJacky Wang        # Include r8 and proguard rules to dagger jar if there is one.
265*f585d8a3SJacky Wang        _package_r8_and_proguard_rule(
266*f585d8a3SJacky Wang            name = name,
267*f585d8a3SJacky Wang            artifactJar = jar_name,
268*f585d8a3SJacky Wang            r8Spec = r8_file,
269*f585d8a3SJacky Wang            proguardSpec = proguard_only_file,
270*f585d8a3SJacky Wang        )
271*f585d8a3SJacky Wang
272*f585d8a3SJacky Wang    jarjar_library(
273*f585d8a3SJacky Wang        name = name + "-src",
274*f585d8a3SJacky Wang        testonly = testonly,
275*f585d8a3SJacky Wang        jars = [_src_jar(dep) for dep in artifact_targets],
276*f585d8a3SJacky Wang        merge_meta_inf_files = merge_meta_inf_files,
277*f585d8a3SJacky Wang    )
278*f585d8a3SJacky Wang
279*f585d8a3SJacky Wang    if javadoc_srcs != None:
280*f585d8a3SJacky Wang        javadoc_library(
281*f585d8a3SJacky Wang            name = name + "-javadoc",
282*f585d8a3SJacky Wang            srcs = javadoc_srcs,
283*f585d8a3SJacky Wang            testonly = testonly,
284*f585d8a3SJacky Wang            root_packages = javadoc_root_packages,
285*f585d8a3SJacky Wang            exclude_packages = javadoc_exclude_packages,
286*f585d8a3SJacky Wang            android_api_level = javadoc_android_api_level,
287*f585d8a3SJacky Wang            deps = artifact_targets,
288*f585d8a3SJacky Wang        )
289*f585d8a3SJacky Wang    else:
290*f585d8a3SJacky Wang        # Build an empty javadoc because Sonatype requires javadocs
291*f585d8a3SJacky Wang        # even if the jar is empty.
292*f585d8a3SJacky Wang        # https://central.sonatype.org/pages/requirements.html#supply-javadoc-and-sources
293*f585d8a3SJacky Wang        native.java_binary(
294*f585d8a3SJacky Wang            name = name + "-javadoc",
295*f585d8a3SJacky Wang        )
296*f585d8a3SJacky Wang
297*f585d8a3SJacky Wangdef _src_jar(target):
298*f585d8a3SJacky Wang    if target.startswith(":"):
299*f585d8a3SJacky Wang        target = Label("//" + native.package_name() + target)
300*f585d8a3SJacky Wang    else:
301*f585d8a3SJacky Wang        target = Label(target)
302*f585d8a3SJacky Wang    return "//%s:lib%s-src.jar" % (target.package, target.name)
303*f585d8a3SJacky Wang
304*f585d8a3SJacky Wangdef _validate_maven_deps_impl(ctx):
305*f585d8a3SJacky Wang    """Validates the given Maven target and deps
306*f585d8a3SJacky Wang
307*f585d8a3SJacky Wang    Validates that the given "target" is a maven artifact (i.e. the "tags"
308*f585d8a3SJacky Wang    attribute contains "maven_coordinates=..."). Second, it calculates the
309*f585d8a3SJacky Wang    list of transitive dependencies of the target that are not owned by
310*f585d8a3SJacky Wang    another maven artifact, and validates that the given "deps" matches
311*f585d8a3SJacky Wang    exactly.
312*f585d8a3SJacky Wang    """
313*f585d8a3SJacky Wang    target = ctx.attr.target
314*f585d8a3SJacky Wang    artifact = target[MavenInfo].artifact
315*f585d8a3SJacky Wang    if not artifact:
316*f585d8a3SJacky Wang        fail("\t[Error]: %s is not a maven artifact" % target.label)
317*f585d8a3SJacky Wang
318*f585d8a3SJacky Wang    if artifact != ctx.attr.expected_artifact:
319*f585d8a3SJacky Wang        fail(
320*f585d8a3SJacky Wang            "\t[Error]: %s expected artifact, %s, but was: %s" % (
321*f585d8a3SJacky Wang                target.label,
322*f585d8a3SJacky Wang                ctx.attr.expected_artifact,
323*f585d8a3SJacky Wang                artifact,
324*f585d8a3SJacky Wang            ),
325*f585d8a3SJacky Wang        )
326*f585d8a3SJacky Wang
327*f585d8a3SJacky Wang    all_transitive_deps = target[MavenInfo].all_transitive_deps.to_list()
328*f585d8a3SJacky Wang    maven_nearest_artifacts = target[MavenInfo].maven_nearest_artifacts.to_list()
329*f585d8a3SJacky Wang    maven_transitive_deps = target[MavenInfo].maven_transitive_deps.to_list()
330*f585d8a3SJacky Wang
331*f585d8a3SJacky Wang    expected_libs = [dep.label for dep in getattr(ctx.attr, "expected_libs", [])]
332*f585d8a3SJacky Wang    actual_libs = [dep for dep in all_transitive_deps if dep not in maven_transitive_deps]
333*f585d8a3SJacky Wang    _validate_list("artifact_target_libs", actual_libs, expected_libs)
334*f585d8a3SJacky Wang
335*f585d8a3SJacky Wang    expected_maven_deps = [dep for dep in getattr(ctx.attr, "expected_maven_deps", [])]
336*f585d8a3SJacky Wang    actual_maven_deps = [_strip_artifact_version(artifact) for artifact in maven_nearest_artifacts]
337*f585d8a3SJacky Wang    _validate_list(
338*f585d8a3SJacky Wang        "artifact_target_maven_deps",
339*f585d8a3SJacky Wang        # Exclude shaded maven deps from this list since they're not actual dependencies.
340*f585d8a3SJacky Wang        [dep for dep in actual_maven_deps if dep not in SHADED_MAVEN_DEPS],
341*f585d8a3SJacky Wang        expected_maven_deps,
342*f585d8a3SJacky Wang        ctx.attr.banned_maven_deps,
343*f585d8a3SJacky Wang    )
344*f585d8a3SJacky Wang
345*f585d8a3SJacky Wangdef _validate_list(name, actual_list, expected_list, banned_list = []):
346*f585d8a3SJacky Wang    missing = sorted(['"{}",'.format(x) for x in actual_list if x not in expected_list])
347*f585d8a3SJacky Wang    if missing:
348*f585d8a3SJacky Wang        fail("\t[Error]: Found missing {}: \n\t\t".format(name) + "\n\t\t".join(missing))
349*f585d8a3SJacky Wang
350*f585d8a3SJacky Wang    extra = sorted(['"{}",'.format(x) for x in expected_list if x not in actual_list])
351*f585d8a3SJacky Wang    if extra:
352*f585d8a3SJacky Wang        fail("\t[Error]: Found extra {}: \n\t\t".format(name) + "\n\t\t".join(extra))
353*f585d8a3SJacky Wang
354*f585d8a3SJacky Wang    banned = sorted(['"{}",'.format(x) for x in actual_list if x in banned_list])
355*f585d8a3SJacky Wang    if banned:
356*f585d8a3SJacky Wang        fail("\t[Error]: Found banned {}: \n\t\t".format(name) + "\n\t\t".join(banned))
357*f585d8a3SJacky Wang
358*f585d8a3SJacky Wangdef _strip_artifact_version(artifact):
359*f585d8a3SJacky Wang    return artifact.rsplit(":", 1)[0]
360*f585d8a3SJacky Wang
361*f585d8a3SJacky Wang_validate_maven_deps = rule(
362*f585d8a3SJacky Wang    implementation = _validate_maven_deps_impl,
363*f585d8a3SJacky Wang    attrs = {
364*f585d8a3SJacky Wang        "target": attr.label(
365*f585d8a3SJacky Wang            doc = "The target to generate a maven artifact for.",
366*f585d8a3SJacky Wang            aspects = [collect_maven_info],
367*f585d8a3SJacky Wang            mandatory = True,
368*f585d8a3SJacky Wang        ),
369*f585d8a3SJacky Wang        "expected_artifact": attr.string(
370*f585d8a3SJacky Wang            doc = "The artifact name of the target.",
371*f585d8a3SJacky Wang            mandatory = True,
372*f585d8a3SJacky Wang        ),
373*f585d8a3SJacky Wang        "expected_libs": attr.label_list(
374*f585d8a3SJacky Wang            doc = "The set of transitive libraries of the target, if any.",
375*f585d8a3SJacky Wang        ),
376*f585d8a3SJacky Wang        "expected_maven_deps": attr.string_list(
377*f585d8a3SJacky Wang            doc = "The required maven dependencies of the target, if any.",
378*f585d8a3SJacky Wang        ),
379*f585d8a3SJacky Wang        "banned_maven_deps": attr.string_list(
380*f585d8a3SJacky Wang            doc = "The required maven dependencies of the target, if any.",
381*f585d8a3SJacky Wang        ),
382*f585d8a3SJacky Wang    },
383*f585d8a3SJacky Wang)
384*f585d8a3SJacky Wang
385*f585d8a3SJacky Wangdef _package_android_library_impl(ctx):
386*f585d8a3SJacky Wang    """A very, very simple Android Library (aar) packaging rule.
387*f585d8a3SJacky Wang
388*f585d8a3SJacky Wang    This rule only support packaging simple android libraries. No resources
389*f585d8a3SJacky Wang    support, assets, extra libs, nor jni. This rule is needed because
390*f585d8a3SJacky Wang    there is no 'JarJar equivalent' for AARs and some of our artifacts are
391*f585d8a3SJacky Wang    composed of sources spread across multiple android_library targets.
392*f585d8a3SJacky Wang
393*f585d8a3SJacky Wang    See: https://developer.android.com/studio/projects/android-library.html#aar-contents
394*f585d8a3SJacky Wang    """
395*f585d8a3SJacky Wang    inputs = [ctx.file.manifest, ctx.file.classesJar]
396*f585d8a3SJacky Wang    if ctx.file.lintJar:
397*f585d8a3SJacky Wang        inputs.append(ctx.file.lintJar)
398*f585d8a3SJacky Wang    if ctx.file.proguardSpec:
399*f585d8a3SJacky Wang        inputs.append(ctx.file.proguardSpec)
400*f585d8a3SJacky Wang
401*f585d8a3SJacky Wang    ctx.actions.run_shell(
402*f585d8a3SJacky Wang        inputs = inputs,
403*f585d8a3SJacky Wang        outputs = [ctx.outputs.aar],
404*f585d8a3SJacky Wang        command = """
405*f585d8a3SJacky Wang            TMPDIR="$(mktemp -d)"
406*f585d8a3SJacky Wang            cp {manifest} $TMPDIR/AndroidManifest.xml
407*f585d8a3SJacky Wang            cp {classesJar} $TMPDIR/classes.jar
408*f585d8a3SJacky Wang            if [[ -a {lintJar} ]]; then
409*f585d8a3SJacky Wang                cp {lintJar} $TMPDIR/lint.jar
410*f585d8a3SJacky Wang            fi
411*f585d8a3SJacky Wang            if [[ -a {proguardSpec} ]]; then
412*f585d8a3SJacky Wang                cp {proguardSpec} $TMPDIR/proguard.txt
413*f585d8a3SJacky Wang            fi
414*f585d8a3SJacky Wang            touch $TMPDIR/R.txt
415*f585d8a3SJacky Wang            zip -j {outputFile} $TMPDIR/*
416*f585d8a3SJacky Wang            """.format(
417*f585d8a3SJacky Wang            manifest = ctx.file.manifest.path,
418*f585d8a3SJacky Wang            classesJar = ctx.file.classesJar.path,
419*f585d8a3SJacky Wang            lintJar = ctx.file.lintJar.path if ctx.file.lintJar else "none",
420*f585d8a3SJacky Wang            proguardSpec = ctx.file.proguardSpec.path if ctx.file.proguardSpec else "none",
421*f585d8a3SJacky Wang            outputFile = ctx.outputs.aar.path,
422*f585d8a3SJacky Wang        ),
423*f585d8a3SJacky Wang    )
424*f585d8a3SJacky Wang
425*f585d8a3SJacky Wang_package_android_library = rule(
426*f585d8a3SJacky Wang    implementation = _package_android_library_impl,
427*f585d8a3SJacky Wang    attrs = {
428*f585d8a3SJacky Wang        "manifest": attr.label(
429*f585d8a3SJacky Wang            doc = "The AndroidManifest.xml file.",
430*f585d8a3SJacky Wang            allow_single_file = True,
431*f585d8a3SJacky Wang            mandatory = True,
432*f585d8a3SJacky Wang        ),
433*f585d8a3SJacky Wang        "classesJar": attr.label(
434*f585d8a3SJacky Wang            doc = "The classes.jar file.",
435*f585d8a3SJacky Wang            allow_single_file = True,
436*f585d8a3SJacky Wang            mandatory = True,
437*f585d8a3SJacky Wang        ),
438*f585d8a3SJacky Wang        "lintJar": attr.label(
439*f585d8a3SJacky Wang            doc = "The lint.jar file.",
440*f585d8a3SJacky Wang            allow_single_file = True,
441*f585d8a3SJacky Wang            mandatory = False,
442*f585d8a3SJacky Wang        ),
443*f585d8a3SJacky Wang        "proguardSpec": attr.label(
444*f585d8a3SJacky Wang            doc = "The proguard.txt file.",
445*f585d8a3SJacky Wang            allow_single_file = True,
446*f585d8a3SJacky Wang            mandatory = False,
447*f585d8a3SJacky Wang        ),
448*f585d8a3SJacky Wang    },
449*f585d8a3SJacky Wang    outputs = {
450*f585d8a3SJacky Wang        "aar": "%{name}.aar",
451*f585d8a3SJacky Wang    },
452*f585d8a3SJacky Wang)
453*f585d8a3SJacky Wang
454*f585d8a3SJacky Wangdef _package_r8_and_proguard_rule_impl(ctx):
455*f585d8a3SJacky Wang    inputs = [ctx.file.artifactJar]
456*f585d8a3SJacky Wang    if ctx.file.r8Spec:
457*f585d8a3SJacky Wang        inputs.append(ctx.file.r8Spec)
458*f585d8a3SJacky Wang    if ctx.file.proguardSpec:
459*f585d8a3SJacky Wang        inputs.append(ctx.file.proguardSpec)
460*f585d8a3SJacky Wang    ctx.actions.run_shell(
461*f585d8a3SJacky Wang        inputs = inputs,
462*f585d8a3SJacky Wang        outputs = [ctx.outputs.jar],
463*f585d8a3SJacky Wang        command = """
464*f585d8a3SJacky Wang            TMPDIR="$(mktemp -d)"
465*f585d8a3SJacky Wang            cp {artifactJar} $TMPDIR/artifact.jar
466*f585d8a3SJacky Wang            if [[ -a {r8Spec} ]]; then
467*f585d8a3SJacky Wang                mkdir -p META-INF/com.android.tools/r8
468*f585d8a3SJacky Wang                cp {r8Spec} META-INF/com.android.tools/r8/r8.pro
469*f585d8a3SJacky Wang                jar uf $TMPDIR/artifact.jar META-INF/
470*f585d8a3SJacky Wang            fi
471*f585d8a3SJacky Wang            if [[ -a {proguardSpec} ]]; then
472*f585d8a3SJacky Wang                mkdir -p META-INF/com.android.tools/proguard
473*f585d8a3SJacky Wang                cp {proguardSpec} META-INF/com.android.tools/proguard/proguard.pro
474*f585d8a3SJacky Wang                jar uf $TMPDIR/artifact.jar META-INF/
475*f585d8a3SJacky Wang            fi
476*f585d8a3SJacky Wang            cp $TMPDIR/artifact.jar {outputFile}
477*f585d8a3SJacky Wang            """.format(
478*f585d8a3SJacky Wang            artifactJar = ctx.file.artifactJar.path,
479*f585d8a3SJacky Wang            r8Spec = ctx.file.r8Spec.path if ctx.file.r8Spec else "none",
480*f585d8a3SJacky Wang            proguardSpec = ctx.file.proguardSpec.path if ctx.file.proguardSpec else "none",
481*f585d8a3SJacky Wang            outputFile = ctx.outputs.jar.path,
482*f585d8a3SJacky Wang        ),
483*f585d8a3SJacky Wang    )
484*f585d8a3SJacky Wang
485*f585d8a3SJacky Wang_package_r8_and_proguard_rule = rule(
486*f585d8a3SJacky Wang    implementation = _package_r8_and_proguard_rule_impl,
487*f585d8a3SJacky Wang    attrs = {
488*f585d8a3SJacky Wang        "artifactJar": attr.label(
489*f585d8a3SJacky Wang            doc = "The library artifact jar to be updated.",
490*f585d8a3SJacky Wang            allow_single_file = True,
491*f585d8a3SJacky Wang            mandatory = True,
492*f585d8a3SJacky Wang        ),
493*f585d8a3SJacky Wang        "r8Spec": attr.label(
494*f585d8a3SJacky Wang            doc = "The r8.txt file to be merged with the artifact jar",
495*f585d8a3SJacky Wang            allow_single_file = True,
496*f585d8a3SJacky Wang            mandatory = False,
497*f585d8a3SJacky Wang        ),
498*f585d8a3SJacky Wang        "proguardSpec": attr.label(
499*f585d8a3SJacky Wang            doc = "The proguard-only.txt file to be merged with the artifact jar",
500*f585d8a3SJacky Wang            allow_single_file = True,
501*f585d8a3SJacky Wang            mandatory = False,
502*f585d8a3SJacky Wang        ),
503*f585d8a3SJacky Wang    },
504*f585d8a3SJacky Wang    outputs = {
505*f585d8a3SJacky Wang        "jar": "%{name}.jar",
506*f585d8a3SJacky Wang    },
507*f585d8a3SJacky Wang)
508