xref: /aosp_15_r20/external/bazelbuild-rules_android/rules/android_library/rule.bzl (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
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