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"""Common attributes for Android rules."""
16
17load(":utils.bzl", "log")
18
19def _add(attrs, *others):
20    new = {}
21    new.update(attrs)
22    for o in others:
23        for name in o.keys():
24            if name in new:
25                log.error("Attr '%s' is defined twice." % name)
26            new[name] = o[name]
27    return new
28
29def _replace(attrs, **kwargs):
30    # Verify that new values are replacing existing ones, not adding.
31    for name in kwargs.keys():
32        if name not in attrs:
33            log.error("Attr '%s' is not defined, replacement failed." % name)
34    new = dict()
35    new.update(attrs)
36    new.update(kwargs)
37    return new
38
39def _make_tristate_attr(default, doc = "", mandatory = False):
40    return attr.int(
41        default = default,
42        doc = doc,
43        mandatory = mandatory,
44        values = [-1, 0, 1],
45    )
46
47def _normalize_tristate(attr_value):
48    """Normalizes the tristate value going into a rule.
49
50    This is required because "tristate" is not officially supported as an
51    attribute type. An equivalent attribute type is an in with a constrained
52    set of values, namely [-1, 0, 1]. Unfortunately, tristate accepts
53    multiple types, integers, booleans and strings ("auto"). As a result, this
54    method normalizes the inputs to an integer.
55
56    This method needs to be applied to attributes that were formally tristate
57    to normalize the inputs.
58    """
59    if type(attr_value) == "int":
60        return attr_value
61
62    if type(attr_value) == "string":
63        if attr_value.lower() == "auto":
64            return -1
65
66    if type(attr_value) == "bool":
67        return int(attr_value)
68
69    return attr_value  # Return unknown type, let the rule fail.
70
71_tristate = struct(
72    create = _make_tristate_attr,
73    normalize = _normalize_tristate,
74    yes = 1,
75    no = 0,
76    auto = -1,
77)
78
79_JAVA_RUNTIME = dict(
80    _host_javabase = attr.label(
81        cfg = "host",
82        default = Label("@rules_android//rules:current_java_runtime"),
83    ),
84)
85
86
87# Android SDK attribute.
88_ANDROID_SDK = dict(
89    _android_sdk = attr.label(
90        allow_rules = ["android_sdk"],
91        default = configuration_field(
92            fragment = "android",
93            name = "android_sdk_label",
94        ),
95        providers = [AndroidSdkInfo],
96    ),
97)
98
99# Compilation attributes for Android rules.
100_COMPILATION = _add(
101    dict(
102        assets = attr.label_list(
103            allow_files = True,
104            cfg = "target",
105        ),
106        assets_dir = attr.string(),
107        custom_package = attr.string(),
108        manifest = attr.label(
109            allow_single_file = [".xml"],
110        ),
111        resource_files = attr.label_list(
112            allow_files = True,
113        ),
114        data = attr.label_list(
115            allow_files = True,
116        ),
117        plugins = attr.label_list(
118            allow_rules = ["java_plugin"],
119            cfg = "host",
120        ),
121        javacopts = attr.string_list(),
122        # TODO: Expose getPlugins() in JavaConfiguration.java
123        #       com/google/devtools/build/lib/rules/java/JavaConfiguration.java
124        #       com/google/devtools/build/lib/rules/java/JavaOptions.java
125        #
126        # _java_plugins = attr.label(
127        #     allow_rules = ["java_plugin"],
128        #     default = configuration_field(
129        #         fragment = "java",
130        #         name = "plugin",
131        #     ),
132        # ),
133    ),
134    _JAVA_RUNTIME,
135)
136
137# Attributes for rules that use the AndroidDataContext android_data.make_context
138_DATA_CONTEXT = _add(
139    dict(
140        # Additional attrs needed for AndroidDataContext
141        _add_g3itr_xslt = attr.label(
142            cfg = "host",
143            default = Label("//tools/android/xslt:add_g3itr.xslt"),
144            allow_single_file = True,
145        ),
146        _android_manifest_merge_tool = attr.label(
147            cfg = "host",
148            default = Label("//tools/android:merge_manifests"),
149            executable = True,
150        ),
151        # TODO(b/145617058) Switching back to head RPBB until the Android rules release process is improved
152        _android_resources_busybox = attr.label(
153            cfg = "host",
154            default = Label("@rules_android//rules:ResourceProcessorBusyBox"),
155            executable = True,
156        ),
157        _xsltproc_tool = attr.label(
158            cfg = "host",
159            default = Label("//tools/android/xslt:xslt"),
160            allow_files = True,
161        ),
162    ),
163    _ANDROID_SDK,
164)
165
166
167
168
169
170
171
172ANDROID_SDK_ATTRS = dict(
173    aapt = attr.label(
174        allow_single_file = True,
175        cfg = "host",
176        executable = True,
177        mandatory = True,
178    ),
179    aapt2 = attr.label(
180        allow_single_file = True,
181        cfg = "host",
182        executable = True,
183    ),
184    aidl = attr.label(
185        allow_files = True,
186        cfg = "host",
187        executable = True,
188        mandatory = True,
189    ),
190    aidl_lib = attr.label(
191        allow_files = [".jar"],
192    ),
193    android_jar = attr.label(
194        allow_single_file = [".jar"],
195        cfg = "host",
196        mandatory = True,
197    ),
198    annotations_jar = attr.label(
199        allow_single_file = [".jar"],
200        cfg = "host",
201    ),
202    apkbuilder = attr.label(
203        allow_files = True,
204        cfg = "host",
205        executable = True,
206    ),
207    apksigner = attr.label(
208        allow_files = True,
209        cfg = "host",
210        executable = True,
211        mandatory = True,
212    ),
213    adb = attr.label(
214        allow_single_file = True,
215        cfg = "host",
216        executable = True,
217        mandatory = True,
218    ),
219    build_tools_version = attr.string(),
220    dx = attr.label(
221        allow_files = True,
222        cfg = "host",
223        executable = True,
224        mandatory = True,
225    ),
226    framework_aidl = attr.label(
227        allow_single_file = True,
228        cfg = "host",
229        mandatory = True,
230    ),
231    main_dex_classes = attr.label(
232        allow_single_file = True,
233        cfg = "host",
234        mandatory = True,
235    ),
236    main_dex_list_creator = attr.label(
237        allow_files = True,
238        cfg = "host",
239        executable = True,
240        mandatory = True,
241    ),
242    proguard = attr.label(
243        allow_files = True,
244        cfg = "host",
245        executable = True,
246        mandatory = True,
247    ),
248    shrinked_android_jar = attr.label(
249        allow_single_file = True,
250        cfg = "host",
251        mandatory = True,
252    ),
253    source_properties = attr.label(
254        allow_single_file = True,
255        cfg = "host",
256    ),
257    zipalign = attr.label(
258        allow_single_file = True,
259        cfg = "host",
260        executable = True,
261        mandatory = True,
262    ),
263    _proguard = attr.label(
264        cfg = "host",
265        default = configuration_field(
266            fragment = "java",
267            name = "proguard_top",
268        ),
269    ),
270    _system = attr.label(
271        default = Label("//tools/android:bootclasspath_android_only"),
272    ),
273)
274
275ANDROID_TOOLS_DEFAULTS_JAR_ATTRS = _add(_ANDROID_SDK)
276
277
278attrs = struct(
279    ANDROID_SDK = _ANDROID_SDK,
280    COMPILATION = _COMPILATION,
281    DATA_CONTEXT = _DATA_CONTEXT,
282    JAVA_RUNTIME = _JAVA_RUNTIME,
283    tristate = _tristate,
284    add = _add,
285    replace = _replace,
286)
287