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