1*9e965d6fSRomain Jobredeaux# Copyright 2018 The Bazel Authors. All rights reserved. 2*9e965d6fSRomain Jobredeaux# 3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License"); 4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License. 5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at 6*9e965d6fSRomain Jobredeaux# 7*9e965d6fSRomain Jobredeaux# http://www.apache.org/licenses/LICENSE-2.0 8*9e965d6fSRomain Jobredeaux# 9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software 10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS, 11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and 13*9e965d6fSRomain Jobredeaux# limitations under the License. 14*9e965d6fSRomain Jobredeaux 15*9e965d6fSRomain Jobredeaux"""android_library rule.""" 16*9e965d6fSRomain Jobredeaux 17*9e965d6fSRomain Jobredeauxload("//rules:acls.bzl", "acls") 18*9e965d6fSRomain Jobredeauxload(":attrs.bzl", _ATTRS = "ATTRS") 19*9e965d6fSRomain Jobredeauxload(":impl.bzl", _impl = "impl") 20*9e965d6fSRomain Jobredeauxload( 21*9e965d6fSRomain Jobredeaux "//rules:attrs.bzl", 22*9e965d6fSRomain Jobredeaux _attrs = "attrs", 23*9e965d6fSRomain Jobredeaux) 24*9e965d6fSRomain Jobredeaux 25*9e965d6fSRomain Jobredeaux_RULE_DOC = """ 26*9e965d6fSRomain Jobredeaux#### Examples 27*9e965d6fSRomain Jobredeaux 28*9e965d6fSRomain JobredeauxThe following example shows how to use android libraries with resources. 29*9e965d6fSRomain Jobredeaux 30*9e965d6fSRomain Jobredeaux```starlark 31*9e965d6fSRomain Jobredeauxandroid_library( 32*9e965d6fSRomain Jobredeaux name = "hellobazellib", 33*9e965d6fSRomain Jobredeaux srcs = glob(["*.java"]), 34*9e965d6fSRomain Jobredeaux resource_files = glob(["res/**/*"]), 35*9e965d6fSRomain Jobredeaux manifest = "AndroidManifest.xml", 36*9e965d6fSRomain Jobredeaux deps = [ 37*9e965d6fSRomain Jobredeaux "//java/bazel/hellobazellib/activities", 38*9e965d6fSRomain Jobredeaux "//java/bazel/hellobazellib/common", 39*9e965d6fSRomain Jobredeaux "//java/bazel/hellobazellib/math", 40*9e965d6fSRomain Jobredeaux "//java/bazel/hellobazellib/service", 41*9e965d6fSRomain Jobredeaux ], 42*9e965d6fSRomain Jobredeaux) 43*9e965d6fSRomain Jobredeaux``` 44*9e965d6fSRomain Jobredeaux 45*9e965d6fSRomain JobredeauxThe following example shows how to set `idl_import_root`. Let `//java/bazel/helloandroid/BUILD` contain: 46*9e965d6fSRomain Jobredeaux 47*9e965d6fSRomain Jobredeaux```starlark 48*9e965d6fSRomain Jobredeauxandroid_library( 49*9e965d6fSRomain Jobredeaux name = "parcelable", 50*9e965d6fSRomain Jobredeaux srcs = ["MyParcelable.java"], # bazel.helloandroid.MyParcelable 51*9e965d6fSRomain Jobredeaux # MyParcelable.aidl will be used as import for other .aidl 52*9e965d6fSRomain Jobredeaux # files that depend on it, but will not be compiled. 53*9e965d6fSRomain Jobredeaux idl_parcelables = ["MyParcelable.aidl"] # bazel.helloandroid.MyParcelable 54*9e965d6fSRomain Jobredeaux # We don't need to specify idl_import_root since the aidl file 55*9e965d6fSRomain Jobredeaux # which declares bazel.helloandroid.MyParcelable 56*9e965d6fSRomain Jobredeaux # is present at java/bazel/helloandroid/MyParcelable.aidl 57*9e965d6fSRomain Jobredeaux # underneath a java root (java/). 58*9e965d6fSRomain Jobredeaux) 59*9e965d6fSRomain Jobredeaux 60*9e965d6fSRomain Jobredeauxandroid_library( 61*9e965d6fSRomain Jobredeaux name = "foreign_parcelable", 62*9e965d6fSRomain Jobredeaux srcs = ["src/android/helloandroid/OtherParcelable.java"], # android.helloandroid.OtherParcelable 63*9e965d6fSRomain Jobredeaux idl_parcelables = [ 64*9e965d6fSRomain Jobredeaux "src/android/helloandroid/OtherParcelable.aidl" # android.helloandroid.OtherParcelable 65*9e965d6fSRomain Jobredeaux ], 66*9e965d6fSRomain Jobredeaux # We need to specify idl_import_root because the aidl file which 67*9e965d6fSRomain Jobredeaux # declares android.helloandroid.OtherParcelable is not positioned 68*9e965d6fSRomain Jobredeaux # at android/helloandroid/OtherParcelable.aidl under a normal java root. 69*9e965d6fSRomain Jobredeaux # Setting idl_import_root to "src" in //java/bazel/helloandroid 70*9e965d6fSRomain Jobredeaux # adds java/bazel/helloandroid/src to the list of roots 71*9e965d6fSRomain Jobredeaux # the aidl compiler will search for imported types. 72*9e965d6fSRomain Jobredeaux idl_import_root = "src", 73*9e965d6fSRomain Jobredeaux) 74*9e965d6fSRomain Jobredeaux 75*9e965d6fSRomain Jobredeaux# Here, OtherInterface.aidl has an "import android.helloandroid.CallbackInterface;" statement. 76*9e965d6fSRomain Jobredeauxandroid_library( 77*9e965d6fSRomain Jobredeaux name = "foreign_interface", 78*9e965d6fSRomain Jobredeaux idl_srcs = [ 79*9e965d6fSRomain Jobredeaux "src/android/helloandroid/OtherInterface.aidl" # android.helloandroid.OtherInterface 80*9e965d6fSRomain Jobredeaux "src/android/helloandroid/CallbackInterface.aidl" # android.helloandroid.CallbackInterface 81*9e965d6fSRomain Jobredeaux ], 82*9e965d6fSRomain Jobredeaux # As above, idl_srcs which are not correctly positioned under a java root 83*9e965d6fSRomain Jobredeaux # must have idl_import_root set. Otherwise, OtherInterface (or any other 84*9e965d6fSRomain Jobredeaux # interface in a library which depends on this one) will not be able 85*9e965d6fSRomain Jobredeaux # to find CallbackInterface when it is imported. 86*9e965d6fSRomain Jobredeaux idl_import_root = "src", 87*9e965d6fSRomain Jobredeaux) 88*9e965d6fSRomain Jobredeaux 89*9e965d6fSRomain Jobredeaux# MyParcelable.aidl is imported by MyInterface.aidl, so the generated 90*9e965d6fSRomain Jobredeaux# MyInterface.java requires MyParcelable.class at compile time. 91*9e965d6fSRomain Jobredeaux# Depending on :parcelable ensures that aidl compilation of MyInterface.aidl 92*9e965d6fSRomain Jobredeaux# specifies the correct import roots and can access MyParcelable.aidl, and 93*9e965d6fSRomain Jobredeaux# makes MyParcelable.class available to Java compilation of MyInterface.java 94*9e965d6fSRomain Jobredeaux# as usual. 95*9e965d6fSRomain Jobredeauxandroid_library( 96*9e965d6fSRomain Jobredeaux name = "idl", 97*9e965d6fSRomain Jobredeaux idl_srcs = ["MyInterface.aidl"], 98*9e965d6fSRomain Jobredeaux deps = [":parcelable"], 99*9e965d6fSRomain Jobredeaux) 100*9e965d6fSRomain Jobredeaux 101*9e965d6fSRomain Jobredeaux# Here, ServiceParcelable uses and thus depends on ParcelableService, 102*9e965d6fSRomain Jobredeaux# when it's compiled, but ParcelableService also uses ServiceParcelable, 103*9e965d6fSRomain Jobredeaux# which creates a circular dependency. 104*9e965d6fSRomain Jobredeaux# As a result, these files must be compiled together, in the same android_library. 105*9e965d6fSRomain Jobredeauxandroid_library( 106*9e965d6fSRomain Jobredeaux name = "circular_dependencies", 107*9e965d6fSRomain Jobredeaux srcs = ["ServiceParcelable.java"], 108*9e965d6fSRomain Jobredeaux idl_srcs = ["ParcelableService.aidl"], 109*9e965d6fSRomain Jobredeaux idl_parcelables = ["ServiceParcelable.aidl"], 110*9e965d6fSRomain Jobredeaux) 111*9e965d6fSRomain Jobredeaux``` 112*9e965d6fSRomain Jobredeaux""" 113*9e965d6fSRomain Jobredeaux 114*9e965d6fSRomain Jobredeauxdef _outputs(name, _package_name, _defined_local_resources): 115*9e965d6fSRomain Jobredeaux outputs = dict( 116*9e965d6fSRomain Jobredeaux lib_jar = "lib%{name}.jar", 117*9e965d6fSRomain Jobredeaux lib_src_jar = "lib%{name}-src.jar", 118*9e965d6fSRomain Jobredeaux aar = "%{name}.aar", 119*9e965d6fSRomain Jobredeaux ) 120*9e965d6fSRomain Jobredeaux 121*9e965d6fSRomain Jobredeaux if _defined_local_resources: 122*9e965d6fSRomain Jobredeaux # TODO(b/177261846): resource-related predeclared outputs need to be re-pointed at the 123*9e965d6fSRomain Jobredeaux # corresponding artifacts in the Starlark pipeline. 124*9e965d6fSRomain Jobredeaux label = "//" + _package_name + ":" + name 125*9e965d6fSRomain Jobredeaux if acls.in_android_library_starlark_resource_outputs_rollout(label): 126*9e965d6fSRomain Jobredeaux path_prefix = "_migrated/" 127*9e965d6fSRomain Jobredeaux else: 128*9e965d6fSRomain Jobredeaux path_prefix = "" 129*9e965d6fSRomain Jobredeaux outputs.update( 130*9e965d6fSRomain Jobredeaux dict( 131*9e965d6fSRomain Jobredeaux resources_src_jar = path_prefix + "%{name}.srcjar", 132*9e965d6fSRomain Jobredeaux resources_txt = path_prefix + "%{name}_symbols/R.txt", 133*9e965d6fSRomain Jobredeaux resources_jar = path_prefix + "%{name}_resources.jar", 134*9e965d6fSRomain Jobredeaux ), 135*9e965d6fSRomain Jobredeaux ) 136*9e965d6fSRomain Jobredeaux 137*9e965d6fSRomain Jobredeaux return outputs 138*9e965d6fSRomain Jobredeaux 139*9e965d6fSRomain Jobredeauxdef make_rule( 140*9e965d6fSRomain Jobredeaux attrs = _ATTRS, 141*9e965d6fSRomain Jobredeaux implementation = _impl, 142*9e965d6fSRomain Jobredeaux outputs = _outputs, 143*9e965d6fSRomain Jobredeaux additional_toolchains = [], 144*9e965d6fSRomain Jobredeaux additional_providers = []): 145*9e965d6fSRomain Jobredeaux """Makes the rule. 146*9e965d6fSRomain Jobredeaux 147*9e965d6fSRomain Jobredeaux Args: 148*9e965d6fSRomain Jobredeaux attrs: A dict. The attributes for the rule. 149*9e965d6fSRomain Jobredeaux implementation: A function. The rule's implementation method. 150*9e965d6fSRomain Jobredeaux outputs: A dict, function, or None. The rule's outputs. 151*9e965d6fSRomain Jobredeaux additional_toolchains: A list. Additional toolchains passed to pass to rule(toolchains). 152*9e965d6fSRomain Jobredeaux additional_providers: A list. Additional providers passed to pass to rule(providers). 153*9e965d6fSRomain Jobredeaux 154*9e965d6fSRomain Jobredeaux Returns: 155*9e965d6fSRomain Jobredeaux A rule. 156*9e965d6fSRomain Jobredeaux """ 157*9e965d6fSRomain Jobredeaux return rule( 158*9e965d6fSRomain Jobredeaux attrs = attrs, 159*9e965d6fSRomain Jobredeaux fragments = [ 160*9e965d6fSRomain Jobredeaux "android", 161*9e965d6fSRomain Jobredeaux "java", 162*9e965d6fSRomain Jobredeaux ], 163*9e965d6fSRomain Jobredeaux implementation = implementation, 164*9e965d6fSRomain Jobredeaux doc = _RULE_DOC, 165*9e965d6fSRomain Jobredeaux provides = [ 166*9e965d6fSRomain Jobredeaux AndroidCcLinkParamsInfo, 167*9e965d6fSRomain Jobredeaux AndroidIdeInfo, 168*9e965d6fSRomain Jobredeaux AndroidIdlInfo, 169*9e965d6fSRomain Jobredeaux AndroidLibraryResourceClassJarProvider, 170*9e965d6fSRomain Jobredeaux AndroidNativeLibsInfo, 171*9e965d6fSRomain Jobredeaux JavaInfo, 172*9e965d6fSRomain Jobredeaux ] + additional_providers, 173*9e965d6fSRomain Jobredeaux outputs = outputs, 174*9e965d6fSRomain Jobredeaux toolchains = [ 175*9e965d6fSRomain Jobredeaux "//toolchains/android:toolchain_type", 176*9e965d6fSRomain Jobredeaux "//toolchains/android_sdk:toolchain_type", 177*9e965d6fSRomain Jobredeaux "@bazel_tools//tools/jdk:toolchain_type", 178*9e965d6fSRomain Jobredeaux ] + additional_toolchains, 179*9e965d6fSRomain Jobredeaux _skylark_testable = True, 180*9e965d6fSRomain Jobredeaux ) 181*9e965d6fSRomain Jobredeaux 182*9e965d6fSRomain Jobredeauxandroid_library = make_rule() 183*9e965d6fSRomain Jobredeaux 184*9e965d6fSRomain Jobredeauxdef _is_defined(name, attrs): 185*9e965d6fSRomain Jobredeaux return name in attrs and attrs[name] != None 186*9e965d6fSRomain Jobredeaux 187*9e965d6fSRomain Jobredeauxdef attrs_metadata(attrs): 188*9e965d6fSRomain Jobredeaux """Adds additional metadata for specific android_library attrs. 189*9e965d6fSRomain Jobredeaux 190*9e965d6fSRomain Jobredeaux Bazel native rules have additional capabilities when inspecting attrs that 191*9e965d6fSRomain Jobredeaux are not available in Starlark. For example, native rules are able to 192*9e965d6fSRomain Jobredeaux determine if an attribute was set by a user and make decisions based on this 193*9e965d6fSRomain Jobredeaux knowledge - sometimes the behavior may differ if the user specifies the 194*9e965d6fSRomain Jobredeaux default value of the attribute. As such the Starlark android_library uses 195*9e965d6fSRomain Jobredeaux this shim to provide similar capabilities. 196*9e965d6fSRomain Jobredeaux 197*9e965d6fSRomain Jobredeaux Args: 198*9e965d6fSRomain Jobredeaux attrs: The attributes passed to the android_library rule. 199*9e965d6fSRomain Jobredeaux 200*9e965d6fSRomain Jobredeaux Returns: 201*9e965d6fSRomain Jobredeaux A dictionary containing attr values with additional metadata. 202*9e965d6fSRomain Jobredeaux """ 203*9e965d6fSRomain Jobredeaux 204*9e965d6fSRomain Jobredeaux # Required for the outputs. 205*9e965d6fSRomain Jobredeaux attrs["$defined_local_resources"] = bool( 206*9e965d6fSRomain Jobredeaux attrs.get("assets") or 207*9e965d6fSRomain Jobredeaux attrs.get("assets_dir") or 208*9e965d6fSRomain Jobredeaux attrs.get("assets_dir") == "" or 209*9e965d6fSRomain Jobredeaux attrs.get("export_manifest") or 210*9e965d6fSRomain Jobredeaux attrs.get("manifest") or 211*9e965d6fSRomain Jobredeaux attrs.get("resource_files"), 212*9e965d6fSRomain Jobredeaux ) 213*9e965d6fSRomain Jobredeaux 214*9e965d6fSRomain Jobredeaux # TODO(b/116691720): Remove normalization when bug is fixed. 215*9e965d6fSRomain Jobredeaux if _is_defined("exports_manifest", attrs): 216*9e965d6fSRomain Jobredeaux attrs["exports_manifest"] = _attrs.tristate.normalize( 217*9e965d6fSRomain Jobredeaux attrs.get("exports_manifest"), 218*9e965d6fSRomain Jobredeaux ) 219*9e965d6fSRomain Jobredeaux 220*9e965d6fSRomain Jobredeaux # TODO(b/127517031): Remove these entries once fixed. 221*9e965d6fSRomain Jobredeaux attrs["$defined_assets"] = _is_defined("assets", attrs) 222*9e965d6fSRomain Jobredeaux attrs["$defined_assets_dir"] = _is_defined("assets_dir", attrs) 223*9e965d6fSRomain Jobredeaux attrs["$defined_idl_import_root"] = _is_defined("idl_import_root", attrs) 224*9e965d6fSRomain Jobredeaux attrs["$defined_idl_parcelables"] = _is_defined("idl_parcelables", attrs) 225*9e965d6fSRomain Jobredeaux attrs["$defined_idl_srcs"] = _is_defined("idl_srcs", attrs) 226*9e965d6fSRomain Jobredeaux 227*9e965d6fSRomain Jobredeaux # Required for ACLs check in _outputs(), since the callback can't access 228*9e965d6fSRomain Jobredeaux # the native module. 229*9e965d6fSRomain Jobredeaux attrs["$package_name"] = native.package_name() 230*9e965d6fSRomain Jobredeaux 231*9e965d6fSRomain Jobredeaux return attrs 232*9e965d6fSRomain Jobredeaux 233*9e965d6fSRomain Jobredeauxdef android_library_macro(**attrs): 234*9e965d6fSRomain Jobredeaux """Bazel android_library rule. 235*9e965d6fSRomain Jobredeaux 236*9e965d6fSRomain Jobredeaux https://docs.bazel.build/versions/master/be/android.html#android_library 237*9e965d6fSRomain Jobredeaux 238*9e965d6fSRomain Jobredeaux Args: 239*9e965d6fSRomain Jobredeaux **attrs: Rule attributes 240*9e965d6fSRomain Jobredeaux """ 241*9e965d6fSRomain Jobredeaux android_library(**attrs_metadata(attrs)) 242