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