xref: /aosp_15_r20/external/bazelbuild-rules_android/rules/busybox.bzl (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1*9e965d6fSRomain Jobredeaux# Copyright 2019 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"""Bazel ResourcesBusyBox Commands."""
16*9e965d6fSRomain Jobredeaux
17*9e965d6fSRomain Jobredeauxload(":java.bzl", _java = "java")
18*9e965d6fSRomain Jobredeaux
19*9e965d6fSRomain Jobredeaux_ANDROID_RESOURCES_STRICT_DEPS = "android_resources_strict_deps"
20*9e965d6fSRomain Jobredeaux
21*9e965d6fSRomain Jobredeauxdef _sanitize_assets_dir(assets_dir):
22*9e965d6fSRomain Jobredeaux    sanitized_assets_dir = "/".join(
23*9e965d6fSRomain Jobredeaux        [
24*9e965d6fSRomain Jobredeaux            part
25*9e965d6fSRomain Jobredeaux            for part in assets_dir.split("/")
26*9e965d6fSRomain Jobredeaux            if part != "" and part != "."
27*9e965d6fSRomain Jobredeaux        ],
28*9e965d6fSRomain Jobredeaux    )
29*9e965d6fSRomain Jobredeaux
30*9e965d6fSRomain Jobredeaux    return "/" + sanitized_assets_dir if assets_dir.startswith("/") else sanitized_assets_dir
31*9e965d6fSRomain Jobredeaux
32*9e965d6fSRomain Jobredeauxdef _get_unique_assets_dirs(assets, assets_dir):
33*9e965d6fSRomain Jobredeaux    """Find the unique assets directories, partitioned by assets_dir.
34*9e965d6fSRomain Jobredeaux
35*9e965d6fSRomain Jobredeaux    Args:
36*9e965d6fSRomain Jobredeaux      assets: A list of Files. List of asset files to process.
37*9e965d6fSRomain Jobredeaux      assets_dir: String. String giving the path to the files in assets.
38*9e965d6fSRomain Jobredeaux
39*9e965d6fSRomain Jobredeaux    Returns:
40*9e965d6fSRomain Jobredeaux      A list of short_paths representing unique asset dirs.
41*9e965d6fSRomain Jobredeaux    """
42*9e965d6fSRomain Jobredeaux    if not assets:
43*9e965d6fSRomain Jobredeaux        return []
44*9e965d6fSRomain Jobredeaux
45*9e965d6fSRomain Jobredeaux    dirs = dict()
46*9e965d6fSRomain Jobredeaux
47*9e965d6fSRomain Jobredeaux    assets_dir = _sanitize_assets_dir(assets_dir)
48*9e965d6fSRomain Jobredeaux    if assets_dir:
49*9e965d6fSRomain Jobredeaux        partition_by = "/%s/" % assets_dir.strip("/")
50*9e965d6fSRomain Jobredeaux        for f in assets:
51*9e965d6fSRomain Jobredeaux            if f.is_directory and f.path.endswith(partition_by[:-1]):
52*9e965d6fSRomain Jobredeaux                # If f is a directory, check if its path ends with the assets_dir.
53*9e965d6fSRomain Jobredeaux                dirs[f.path] = True
54*9e965d6fSRomain Jobredeaux            elif f.is_directory and "_aar/unzipped" in f.path:
55*9e965d6fSRomain Jobredeaux                # Assets from an aar_import rule are extracted in a
56*9e965d6fSRomain Jobredeaux                # "assets" subdirectory of the given path
57*9e965d6fSRomain Jobredeaux                dirs["%s/assets" % f.path] = True
58*9e965d6fSRomain Jobredeaux            else:
59*9e965d6fSRomain Jobredeaux                # Partition to remove subdirectories beneath assets_dir
60*9e965d6fSRomain Jobredeaux                # Also removes the trailing /
61*9e965d6fSRomain Jobredeaux                dirs["".join(f.path.rpartition(partition_by)[:2])[:-1]] = True
62*9e965d6fSRomain Jobredeaux    else:
63*9e965d6fSRomain Jobredeaux        # Use the dirname of the generating target if no assets_dir.
64*9e965d6fSRomain Jobredeaux        for f in assets:
65*9e965d6fSRomain Jobredeaux            if f.is_source:
66*9e965d6fSRomain Jobredeaux                dirs[f.owner.package] = True
67*9e965d6fSRomain Jobredeaux            else:
68*9e965d6fSRomain Jobredeaux                # Prepend the root path for generated files.
69*9e965d6fSRomain Jobredeaux                dirs[f.root.path + "/" + f.owner.package] = True
70*9e965d6fSRomain Jobredeaux    return dirs.keys()
71*9e965d6fSRomain Jobredeaux
72*9e965d6fSRomain Jobredeauxdef _get_unique_res_dirs(resource_files):
73*9e965d6fSRomain Jobredeaux    """Find the unique res dirs.
74*9e965d6fSRomain Jobredeaux
75*9e965d6fSRomain Jobredeaux    Args:
76*9e965d6fSRomain Jobredeaux      resource_files: A list of Files. A list of resource_files.
77*9e965d6fSRomain Jobredeaux
78*9e965d6fSRomain Jobredeaux    Returns:
79*9e965d6fSRomain Jobredeaux      A list of short_paths representing unique res dirs from the given resource files.
80*9e965d6fSRomain Jobredeaux    """
81*9e965d6fSRomain Jobredeaux    dirs = dict()
82*9e965d6fSRomain Jobredeaux    for f in resource_files:
83*9e965d6fSRomain Jobredeaux        if f.is_directory:
84*9e965d6fSRomain Jobredeaux            dirs[f.path] = True
85*9e965d6fSRomain Jobredeaux        else:
86*9e965d6fSRomain Jobredeaux            dirs[f.dirname.rpartition("/" + f.dirname.split("/")[-1])[0]] = True
87*9e965d6fSRomain Jobredeaux    return dirs.keys()
88*9e965d6fSRomain Jobredeaux
89*9e965d6fSRomain Jobredeauxdef _make_serialized_resources_flag(
90*9e965d6fSRomain Jobredeaux        assets = [],
91*9e965d6fSRomain Jobredeaux        assets_dir = None,
92*9e965d6fSRomain Jobredeaux        resource_files = [],
93*9e965d6fSRomain Jobredeaux        label = "",
94*9e965d6fSRomain Jobredeaux        symbols = None):
95*9e965d6fSRomain Jobredeaux    return ";".join(
96*9e965d6fSRomain Jobredeaux        [
97*9e965d6fSRomain Jobredeaux            "#".join(_get_unique_res_dirs(resource_files)),
98*9e965d6fSRomain Jobredeaux            "#".join(_get_unique_assets_dirs(assets, assets_dir)),
99*9e965d6fSRomain Jobredeaux            label,
100*9e965d6fSRomain Jobredeaux            symbols.path if symbols else "",
101*9e965d6fSRomain Jobredeaux        ],
102*9e965d6fSRomain Jobredeaux    ).rstrip(":")
103*9e965d6fSRomain Jobredeaux
104*9e965d6fSRomain Jobredeauxdef _make_resources_flag(
105*9e965d6fSRomain Jobredeaux        assets = [],
106*9e965d6fSRomain Jobredeaux        assets_dir = None,
107*9e965d6fSRomain Jobredeaux        resource_files = [],
108*9e965d6fSRomain Jobredeaux        manifest = None,
109*9e965d6fSRomain Jobredeaux        r_txt = None,
110*9e965d6fSRomain Jobredeaux        symbols = None):
111*9e965d6fSRomain Jobredeaux    return ":".join(
112*9e965d6fSRomain Jobredeaux        [
113*9e965d6fSRomain Jobredeaux            "#".join(_get_unique_res_dirs(resource_files)),
114*9e965d6fSRomain Jobredeaux            "#".join(_get_unique_assets_dirs(assets, assets_dir)),
115*9e965d6fSRomain Jobredeaux            manifest.path if manifest else "",
116*9e965d6fSRomain Jobredeaux            r_txt.path if r_txt else "",
117*9e965d6fSRomain Jobredeaux            symbols.path if symbols else "",
118*9e965d6fSRomain Jobredeaux        ],
119*9e965d6fSRomain Jobredeaux    )
120*9e965d6fSRomain Jobredeaux
121*9e965d6fSRomain Jobredeauxdef _path(f):
122*9e965d6fSRomain Jobredeaux    return f.path
123*9e965d6fSRomain Jobredeaux
124*9e965d6fSRomain Jobredeauxdef _make_package_resources_flags(resources_node):
125*9e965d6fSRomain Jobredeaux    if not (resources_node.manifest and resources_node.r_txt and resources_node.compiled_resources):
126*9e965d6fSRomain Jobredeaux        return None
127*9e965d6fSRomain Jobredeaux    flag = _make_resources_flag(
128*9e965d6fSRomain Jobredeaux        resource_files = resources_node.resource_files.to_list(),
129*9e965d6fSRomain Jobredeaux        assets = resources_node.assets.to_list(),
130*9e965d6fSRomain Jobredeaux        assets_dir = resources_node.assets_dir,
131*9e965d6fSRomain Jobredeaux        manifest = resources_node.manifest,
132*9e965d6fSRomain Jobredeaux        r_txt = resources_node.r_txt,
133*9e965d6fSRomain Jobredeaux        symbols = resources_node.compiled_resources,
134*9e965d6fSRomain Jobredeaux    )
135*9e965d6fSRomain Jobredeaux    return flag
136*9e965d6fSRomain Jobredeaux
137*9e965d6fSRomain Jobredeauxdef _make_package_assets_flags(resources_node):
138*9e965d6fSRomain Jobredeaux    assets = resources_node.assets.to_list()
139*9e965d6fSRomain Jobredeaux    if not assets:
140*9e965d6fSRomain Jobredeaux        return None
141*9e965d6fSRomain Jobredeaux    return _make_serialized_resources_flag(
142*9e965d6fSRomain Jobredeaux        assets = assets,
143*9e965d6fSRomain Jobredeaux        assets_dir = resources_node.assets_dir,
144*9e965d6fSRomain Jobredeaux        label = str(resources_node.label),
145*9e965d6fSRomain Jobredeaux        symbols = resources_node.compiled_assets,
146*9e965d6fSRomain Jobredeaux    )
147*9e965d6fSRomain Jobredeaux
148*9e965d6fSRomain Jobredeauxdef _extract_filters(
149*9e965d6fSRomain Jobredeaux        raw_list):
150*9e965d6fSRomain Jobredeaux    """Extract densities and resource_configuration filters from raw string lists.
151*9e965d6fSRomain Jobredeaux
152*9e965d6fSRomain Jobredeaux    In BUILD files, string lists can be represented as a list of strings, a single comma-separated
153*9e965d6fSRomain Jobredeaux    string, or a combination of both. This method outputs a single list of individual string values,
154*9e965d6fSRomain Jobredeaux    which can then be passed directly to resource processing actions. Empty strings are removed and
155*9e965d6fSRomain Jobredeaux    the final list is sorted.
156*9e965d6fSRomain Jobredeaux
157*9e965d6fSRomain Jobredeaux    Args:
158*9e965d6fSRomain Jobredeaux      raw_list: List of strings. The raw densities or resource configuration filters.
159*9e965d6fSRomain Jobredeaux
160*9e965d6fSRomain Jobredeaux    Returns:
161*9e965d6fSRomain Jobredeaux      List of strings extracted from the raw list.
162*9e965d6fSRomain Jobredeaux    """
163*9e965d6fSRomain Jobredeaux    out_filters = []
164*9e965d6fSRomain Jobredeaux    for item in raw_list:
165*9e965d6fSRomain Jobredeaux        if "," in item:
166*9e965d6fSRomain Jobredeaux            item_list = item.split(",")
167*9e965d6fSRomain Jobredeaux            for entry in item_list:
168*9e965d6fSRomain Jobredeaux                stripped_entry = entry.strip()
169*9e965d6fSRomain Jobredeaux                if stripped_entry:
170*9e965d6fSRomain Jobredeaux                    out_filters.append(stripped_entry)
171*9e965d6fSRomain Jobredeaux        elif item:
172*9e965d6fSRomain Jobredeaux            out_filters.append(item)
173*9e965d6fSRomain Jobredeaux    return sorted(out_filters)
174*9e965d6fSRomain Jobredeaux
175*9e965d6fSRomain Jobredeauxdef _package(
176*9e965d6fSRomain Jobredeaux        ctx,
177*9e965d6fSRomain Jobredeaux        out_r_src_jar = None,
178*9e965d6fSRomain Jobredeaux        out_r_txt = None,
179*9e965d6fSRomain Jobredeaux        out_symbols = None,
180*9e965d6fSRomain Jobredeaux        out_manifest = None,
181*9e965d6fSRomain Jobredeaux        out_proguard_cfg = None,
182*9e965d6fSRomain Jobredeaux        out_main_dex_proguard_cfg = None,
183*9e965d6fSRomain Jobredeaux        out_resource_files_zip = None,
184*9e965d6fSRomain Jobredeaux        out_file = None,
185*9e965d6fSRomain Jobredeaux        package_type = None,
186*9e965d6fSRomain Jobredeaux        java_package = None,
187*9e965d6fSRomain Jobredeaux        manifest = None,
188*9e965d6fSRomain Jobredeaux        assets = [],
189*9e965d6fSRomain Jobredeaux        assets_dir = None,
190*9e965d6fSRomain Jobredeaux        resource_files = [],
191*9e965d6fSRomain Jobredeaux        resource_configs = None,
192*9e965d6fSRomain Jobredeaux        densities = [],
193*9e965d6fSRomain Jobredeaux        application_id = None,
194*9e965d6fSRomain Jobredeaux        package_id = None,
195*9e965d6fSRomain Jobredeaux        direct_resources_nodes = [],
196*9e965d6fSRomain Jobredeaux        transitive_resources_nodes = [],
197*9e965d6fSRomain Jobredeaux        transitive_manifests = [],
198*9e965d6fSRomain Jobredeaux        transitive_assets = [],
199*9e965d6fSRomain Jobredeaux        transitive_compiled_assets = [],
200*9e965d6fSRomain Jobredeaux        transitive_resource_files = [],
201*9e965d6fSRomain Jobredeaux        transitive_compiled_resources = [],
202*9e965d6fSRomain Jobredeaux        transitive_r_txts = [],
203*9e965d6fSRomain Jobredeaux        additional_apks_to_link_against = [],
204*9e965d6fSRomain Jobredeaux        resource_apks = depset(),
205*9e965d6fSRomain Jobredeaux        nocompress_extensions = [],
206*9e965d6fSRomain Jobredeaux        proto_format = False,
207*9e965d6fSRomain Jobredeaux        shrink_resource_cycles = False,
208*9e965d6fSRomain Jobredeaux        version_name = None,
209*9e965d6fSRomain Jobredeaux        version_code = None,
210*9e965d6fSRomain Jobredeaux        android_jar = None,
211*9e965d6fSRomain Jobredeaux        aapt = None,
212*9e965d6fSRomain Jobredeaux        busybox = None,
213*9e965d6fSRomain Jobredeaux        host_javabase = None,
214*9e965d6fSRomain Jobredeaux        should_throw_on_conflict = True,  # TODO: read this from allowlist at caller
215*9e965d6fSRomain Jobredeaux        debug = True):  # TODO: we will set this to false in prod builds
216*9e965d6fSRomain Jobredeaux    """Packages the compiled Android Resources with AAPT.
217*9e965d6fSRomain Jobredeaux
218*9e965d6fSRomain Jobredeaux    Args:
219*9e965d6fSRomain Jobredeaux      ctx: The context.
220*9e965d6fSRomain Jobredeaux      out_r_src_jar: A File. The R.java outputted by linking resources in a srcjar.
221*9e965d6fSRomain Jobredeaux      out_r_txt: A File. The resource IDs outputted by linking resources in text.
222*9e965d6fSRomain Jobredeaux      out_symbols: A File. The output zip containing compiled resources.
223*9e965d6fSRomain Jobredeaux      out_manifest: A File. The output processed manifest.
224*9e965d6fSRomain Jobredeaux      out_proguard_cfg: A File. The proguard config to be generated.
225*9e965d6fSRomain Jobredeaux      out_main_dex_proguard_cfg: A File. The main dex proguard config to be generated.
226*9e965d6fSRomain Jobredeaux      out_resource_files_zip: A File. The resource files zipped by linking resources.
227*9e965d6fSRomain Jobredeaux      out_file: A File. The Resource APK outputted by linking resources.
228*9e965d6fSRomain Jobredeaux      package_type: A string. The configuration type to use when packaging.
229*9e965d6fSRomain Jobredeaux      java_package: A string. The Java package for the generated R.java.
230*9e965d6fSRomain Jobredeaux      manifest: A File. The AndroidManifest.xml.
231*9e965d6fSRomain Jobredeaux      assets: sequence of Files. A list of Android assets files to be processed.
232*9e965d6fSRomain Jobredeaux      assets_dir: String. The name of the assets directory.
233*9e965d6fSRomain Jobredeaux      resource_files: A list of Files. The resource files.
234*9e965d6fSRomain Jobredeaux      resource_configs: A list of strings. The list of resource configuration
235*9e965d6fSRomain Jobredeaux        filters.
236*9e965d6fSRomain Jobredeaux      densities: A list of strings. The list of screen densities to filter for when
237*9e965d6fSRomain Jobredeaux        building the apk.
238*9e965d6fSRomain Jobredeaux      application_id: An optional string. The applicationId set in manifest values.
239*9e965d6fSRomain Jobredeaux      package_id: An optional integer in [2,255]. This is the prefix byte for
240*9e965d6fSRomain Jobredeaux        all generated resource IDs, defaults to 0x7F (127). 1 is reserved by the
241*9e965d6fSRomain Jobredeaux        framework, and some builds are known to crash when given IDs > 127.
242*9e965d6fSRomain Jobredeaux        Shared libraries are also assigned monotonically increasing IDs in
243*9e965d6fSRomain Jobredeaux        [2,126], so care should be taken that there is room at the lower end.
244*9e965d6fSRomain Jobredeaux      direct_resources_nodes: Depset of ResourcesNodeInfo providers. The set of
245*9e965d6fSRomain Jobredeaux        ResourcesNodeInfo from direct dependencies.
246*9e965d6fSRomain Jobredeaux      transitive_resources_nodes: Depset of ResourcesNodeInfo providers. The set
247*9e965d6fSRomain Jobredeaux        of ResourcesNodeInfo from transitive dependencies (not including directs).
248*9e965d6fSRomain Jobredeaux      transitive_manifests: List of Depsets. Depsets contain all transitive manifests.
249*9e965d6fSRomain Jobredeaux      transitive_assets: List of Depsets. Depsets contain all transitive assets.
250*9e965d6fSRomain Jobredeaux      transitive_compiled_assets: List of Depsets. Depsets contain all transitive
251*9e965d6fSRomain Jobredeaux        compiled_assets.
252*9e965d6fSRomain Jobredeaux      transitive_resource_files: List of Depsets. Depsets contain all transitive
253*9e965d6fSRomain Jobredeaux        resource files.
254*9e965d6fSRomain Jobredeaux      transitive_compiled_resources: List of Depsets. Depsets contain all transitive
255*9e965d6fSRomain Jobredeaux        compiled_resources.
256*9e965d6fSRomain Jobredeaux      transitive_r_txts: List of Depsets. Depsets contain all transitive R txt files.
257*9e965d6fSRomain Jobredeaux      additional_apks_to_link_against: A list of Files. Additional APKs to link
258*9e965d6fSRomain Jobredeaux        against. Optional.
259*9e965d6fSRomain Jobredeaux      resource_apks: Depset of resource only apk files to link against.
260*9e965d6fSRomain Jobredeaux      nocompress_extensions: A list of strings. File extension to leave uncompressed
261*9e965d6fSRomain Jobredeaux        in the apk.
262*9e965d6fSRomain Jobredeaux      proto_format: Boolean, whether to generate the resource table in proto format.
263*9e965d6fSRomain Jobredeaux      shrink_resource_cycles: Boolean, flag that enables more shrinking of
264*9e965d6fSRomain Jobredeaux        code and resources by instructing AAPT2 to emit conditional Proguard keep rules.
265*9e965d6fSRomain Jobredeaux      version_name: A string. The version name to stamp the generated manifest with. Optional.
266*9e965d6fSRomain Jobredeaux      version_code: A string. The version code to stamp the generated manifest with. Optional.
267*9e965d6fSRomain Jobredeaux      android_jar: A File. The Android Jar.
268*9e965d6fSRomain Jobredeaux      aapt: A FilesToRunProvider. The AAPT executable.
269*9e965d6fSRomain Jobredeaux      busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable.
270*9e965d6fSRomain Jobredeaux      host_javabase: Target. The host javabase.
271*9e965d6fSRomain Jobredeaux      should_throw_on_conflict: A boolean. Determines whether an error should be thrown
272*9e965d6fSRomain Jobredeaux        when a resource conflict occurs.
273*9e965d6fSRomain Jobredeaux      debug: A boolean. Determines whether to enable debugging.
274*9e965d6fSRomain Jobredeaux    """
275*9e965d6fSRomain Jobredeaux    if not manifest:
276*9e965d6fSRomain Jobredeaux        fail("No manifest given, the manifest is mandatory.")
277*9e965d6fSRomain Jobredeaux
278*9e965d6fSRomain Jobredeaux    direct_data_flag = []
279*9e965d6fSRomain Jobredeaux    direct_compiled_resources = []
280*9e965d6fSRomain Jobredeaux
281*9e965d6fSRomain Jobredeaux    output_files = []
282*9e965d6fSRomain Jobredeaux    input_files = []
283*9e965d6fSRomain Jobredeaux    transitive_input_files = []
284*9e965d6fSRomain Jobredeaux
285*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
286*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s")
287*9e965d6fSRomain Jobredeaux    args.add("--tool", "AAPT2_PACKAGE")
288*9e965d6fSRomain Jobredeaux    args.add("--")
289*9e965d6fSRomain Jobredeaux    args.add("--aapt2", aapt.executable)
290*9e965d6fSRomain Jobredeaux    args.add_joined(
291*9e965d6fSRomain Jobredeaux        "--data",
292*9e965d6fSRomain Jobredeaux        transitive_resources_nodes,
293*9e965d6fSRomain Jobredeaux        map_each = _make_package_resources_flags,
294*9e965d6fSRomain Jobredeaux        join_with = ",",
295*9e965d6fSRomain Jobredeaux    )
296*9e965d6fSRomain Jobredeaux    args.add_joined(
297*9e965d6fSRomain Jobredeaux        "--directData",
298*9e965d6fSRomain Jobredeaux        direct_resources_nodes,
299*9e965d6fSRomain Jobredeaux        map_each = _make_package_resources_flags,
300*9e965d6fSRomain Jobredeaux        join_with = ",",
301*9e965d6fSRomain Jobredeaux    )
302*9e965d6fSRomain Jobredeaux    args.add_joined(
303*9e965d6fSRomain Jobredeaux        "--directAssets",
304*9e965d6fSRomain Jobredeaux        direct_resources_nodes,
305*9e965d6fSRomain Jobredeaux        map_each = _make_package_assets_flags,
306*9e965d6fSRomain Jobredeaux        join_with = "&",
307*9e965d6fSRomain Jobredeaux        omit_if_empty = True,
308*9e965d6fSRomain Jobredeaux    )
309*9e965d6fSRomain Jobredeaux    args.add_joined(
310*9e965d6fSRomain Jobredeaux        "--assets",
311*9e965d6fSRomain Jobredeaux        transitive_resources_nodes,
312*9e965d6fSRomain Jobredeaux        map_each = _make_package_assets_flags,
313*9e965d6fSRomain Jobredeaux        join_with = "&",
314*9e965d6fSRomain Jobredeaux        omit_if_empty = True,
315*9e965d6fSRomain Jobredeaux    )
316*9e965d6fSRomain Jobredeaux    transitive_input_files.extend(transitive_resource_files)
317*9e965d6fSRomain Jobredeaux    transitive_input_files.extend(transitive_assets)
318*9e965d6fSRomain Jobredeaux    transitive_input_files.extend(transitive_compiled_assets)
319*9e965d6fSRomain Jobredeaux    transitive_input_files.extend(transitive_compiled_resources)
320*9e965d6fSRomain Jobredeaux    transitive_input_files.extend(transitive_manifests)
321*9e965d6fSRomain Jobredeaux    transitive_input_files.extend(transitive_r_txts)
322*9e965d6fSRomain Jobredeaux    args.add(
323*9e965d6fSRomain Jobredeaux        "--primaryData",
324*9e965d6fSRomain Jobredeaux        _make_resources_flag(
325*9e965d6fSRomain Jobredeaux            manifest = manifest,
326*9e965d6fSRomain Jobredeaux            assets = assets,
327*9e965d6fSRomain Jobredeaux            assets_dir = assets_dir,
328*9e965d6fSRomain Jobredeaux            resource_files = resource_files,
329*9e965d6fSRomain Jobredeaux        ),
330*9e965d6fSRomain Jobredeaux    )
331*9e965d6fSRomain Jobredeaux    input_files.append(manifest)
332*9e965d6fSRomain Jobredeaux    input_files.extend(resource_files)
333*9e965d6fSRomain Jobredeaux    input_files.extend(assets)
334*9e965d6fSRomain Jobredeaux    args.add("--androidJar", android_jar)
335*9e965d6fSRomain Jobredeaux    input_files.append(android_jar)
336*9e965d6fSRomain Jobredeaux    args.add("--rOutput", out_r_txt)
337*9e965d6fSRomain Jobredeaux    output_files.append(out_r_txt)
338*9e965d6fSRomain Jobredeaux    if out_symbols:
339*9e965d6fSRomain Jobredeaux        args.add("--symbolsOut", out_symbols)
340*9e965d6fSRomain Jobredeaux        output_files.append(out_symbols)
341*9e965d6fSRomain Jobredeaux    args.add("--srcJarOutput", out_r_src_jar)
342*9e965d6fSRomain Jobredeaux    output_files.append(out_r_src_jar)
343*9e965d6fSRomain Jobredeaux    if out_proguard_cfg:
344*9e965d6fSRomain Jobredeaux        args.add("--proguardOutput", out_proguard_cfg)
345*9e965d6fSRomain Jobredeaux        output_files.append(out_proguard_cfg)
346*9e965d6fSRomain Jobredeaux    if out_main_dex_proguard_cfg:
347*9e965d6fSRomain Jobredeaux        args.add("--mainDexProguardOutput", out_main_dex_proguard_cfg)
348*9e965d6fSRomain Jobredeaux        output_files.append(out_main_dex_proguard_cfg)
349*9e965d6fSRomain Jobredeaux    args.add("--manifestOutput", out_manifest)
350*9e965d6fSRomain Jobredeaux    output_files.append(out_manifest)
351*9e965d6fSRomain Jobredeaux    if out_resource_files_zip:
352*9e965d6fSRomain Jobredeaux        args.add("--resourcesOutput", out_resource_files_zip)
353*9e965d6fSRomain Jobredeaux        output_files.append(out_resource_files_zip)
354*9e965d6fSRomain Jobredeaux    if out_file:
355*9e965d6fSRomain Jobredeaux        args.add("--packagePath", out_file)
356*9e965d6fSRomain Jobredeaux        output_files.append(out_file)
357*9e965d6fSRomain Jobredeaux    args.add("--useAaptCruncher=no")  # Unnecessary, used for AAPT1 only but added here to minimize diffs.
358*9e965d6fSRomain Jobredeaux    if package_type:
359*9e965d6fSRomain Jobredeaux        args.add("--packageType", package_type)
360*9e965d6fSRomain Jobredeaux    if debug:
361*9e965d6fSRomain Jobredeaux        args.add("--debug")
362*9e965d6fSRomain Jobredeaux    if should_throw_on_conflict:
363*9e965d6fSRomain Jobredeaux        args.add("--throwOnResourceConflict")
364*9e965d6fSRomain Jobredeaux    if resource_configs:
365*9e965d6fSRomain Jobredeaux        args.add_joined("--resourceConfigs", _extract_filters(resource_configs), join_with = ",")
366*9e965d6fSRomain Jobredeaux    if densities:
367*9e965d6fSRomain Jobredeaux        args.add_joined("--densities", _extract_filters(densities), join_with = ",")
368*9e965d6fSRomain Jobredeaux    if application_id:
369*9e965d6fSRomain Jobredeaux        args.add("--applicationId", application_id)
370*9e965d6fSRomain Jobredeaux    if package_id:
371*9e965d6fSRomain Jobredeaux        args.add("--packageId", package_id)
372*9e965d6fSRomain Jobredeaux    if additional_apks_to_link_against:
373*9e965d6fSRomain Jobredeaux        args.add_joined(
374*9e965d6fSRomain Jobredeaux            "--additionalApksToLinkAgainst",
375*9e965d6fSRomain Jobredeaux            additional_apks_to_link_against,
376*9e965d6fSRomain Jobredeaux            join_with = ":",
377*9e965d6fSRomain Jobredeaux            map_each = _path,
378*9e965d6fSRomain Jobredeaux        )
379*9e965d6fSRomain Jobredeaux        input_files.extend(additional_apks_to_link_against)
380*9e965d6fSRomain Jobredeaux    if nocompress_extensions:
381*9e965d6fSRomain Jobredeaux        args.add_joined("--uncompressedExtensions", nocompress_extensions, join_with = ",")
382*9e965d6fSRomain Jobredeaux    if proto_format:
383*9e965d6fSRomain Jobredeaux        args.add("--resourceTableAsProto")
384*9e965d6fSRomain Jobredeaux    if shrink_resource_cycles:
385*9e965d6fSRomain Jobredeaux        args.add("--conditionalKeepRules=yes")
386*9e965d6fSRomain Jobredeaux    if version_name:
387*9e965d6fSRomain Jobredeaux        args.add("--versionName", version_name)
388*9e965d6fSRomain Jobredeaux    if version_code:
389*9e965d6fSRomain Jobredeaux        args.add("--versionCode", version_code)
390*9e965d6fSRomain Jobredeaux    if java_package:
391*9e965d6fSRomain Jobredeaux        args.add("--packageForR", java_package)
392*9e965d6fSRomain Jobredeaux
393*9e965d6fSRomain Jobredeaux    args.add_joined(
394*9e965d6fSRomain Jobredeaux        "--resourceApks",
395*9e965d6fSRomain Jobredeaux        resource_apks,
396*9e965d6fSRomain Jobredeaux        join_with = ":",
397*9e965d6fSRomain Jobredeaux    )
398*9e965d6fSRomain Jobredeaux    transitive_input_files.append(resource_apks)
399*9e965d6fSRomain Jobredeaux
400*9e965d6fSRomain Jobredeaux    _java.run(
401*9e965d6fSRomain Jobredeaux        ctx = ctx,
402*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
403*9e965d6fSRomain Jobredeaux        executable = busybox,
404*9e965d6fSRomain Jobredeaux        tools = [aapt],
405*9e965d6fSRomain Jobredeaux        arguments = [args],
406*9e965d6fSRomain Jobredeaux        inputs = depset(input_files, transitive = transitive_input_files),
407*9e965d6fSRomain Jobredeaux        outputs = output_files,
408*9e965d6fSRomain Jobredeaux        mnemonic = "PackageAndroidResources",
409*9e965d6fSRomain Jobredeaux        progress_message = "Packaging Android Resources in %s" % ctx.label,
410*9e965d6fSRomain Jobredeaux    )
411*9e965d6fSRomain Jobredeaux
412*9e965d6fSRomain Jobredeauxdef _parse(
413*9e965d6fSRomain Jobredeaux        ctx,
414*9e965d6fSRomain Jobredeaux        out_symbols = None,
415*9e965d6fSRomain Jobredeaux        assets = [],
416*9e965d6fSRomain Jobredeaux        assets_dir = None,
417*9e965d6fSRomain Jobredeaux        busybox = None,
418*9e965d6fSRomain Jobredeaux        host_javabase = None):
419*9e965d6fSRomain Jobredeaux    """Parses Android assets.
420*9e965d6fSRomain Jobredeaux
421*9e965d6fSRomain Jobredeaux    Args:
422*9e965d6fSRomain Jobredeaux      ctx: The context.
423*9e965d6fSRomain Jobredeaux      out_symbols: A File. The output bin containing parsed assets.
424*9e965d6fSRomain Jobredeaux      assets: sequence of Files. A list of Android assets files to be processed.
425*9e965d6fSRomain Jobredeaux      assets_dir: String. The name of the assets directory.
426*9e965d6fSRomain Jobredeaux      busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable.
427*9e965d6fSRomain Jobredeaux      host_javabase: Target. The host javabase.
428*9e965d6fSRomain Jobredeaux    """
429*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
430*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s")
431*9e965d6fSRomain Jobredeaux    args.add("--tool", "PARSE")
432*9e965d6fSRomain Jobredeaux    args.add("--")
433*9e965d6fSRomain Jobredeaux    args.add(
434*9e965d6fSRomain Jobredeaux        "--primaryData",
435*9e965d6fSRomain Jobredeaux        _make_resources_flag(
436*9e965d6fSRomain Jobredeaux            assets = assets,
437*9e965d6fSRomain Jobredeaux            assets_dir = assets_dir,
438*9e965d6fSRomain Jobredeaux        ),
439*9e965d6fSRomain Jobredeaux    )
440*9e965d6fSRomain Jobredeaux    args.add("--output", out_symbols)
441*9e965d6fSRomain Jobredeaux
442*9e965d6fSRomain Jobredeaux    _java.run(
443*9e965d6fSRomain Jobredeaux        ctx = ctx,
444*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
445*9e965d6fSRomain Jobredeaux        executable = busybox,
446*9e965d6fSRomain Jobredeaux        arguments = [args],
447*9e965d6fSRomain Jobredeaux        inputs = assets,
448*9e965d6fSRomain Jobredeaux        outputs = [out_symbols],
449*9e965d6fSRomain Jobredeaux        mnemonic = "ParseAndroidResources",
450*9e965d6fSRomain Jobredeaux        progress_message = "Parsing Android Resources in %s" % out_symbols.short_path,
451*9e965d6fSRomain Jobredeaux    )
452*9e965d6fSRomain Jobredeaux
453*9e965d6fSRomain Jobredeauxdef _make_merge_assets_flags(resources_node):
454*9e965d6fSRomain Jobredeaux    assets = resources_node.assets.to_list()
455*9e965d6fSRomain Jobredeaux    if not (assets or resources_node.assets_dir):
456*9e965d6fSRomain Jobredeaux        return None
457*9e965d6fSRomain Jobredeaux    return _make_serialized_resources_flag(
458*9e965d6fSRomain Jobredeaux        assets = assets,
459*9e965d6fSRomain Jobredeaux        assets_dir = resources_node.assets_dir,
460*9e965d6fSRomain Jobredeaux        label = str(resources_node.label),
461*9e965d6fSRomain Jobredeaux        symbols = resources_node.assets_symbols,
462*9e965d6fSRomain Jobredeaux    )
463*9e965d6fSRomain Jobredeaux
464*9e965d6fSRomain Jobredeauxdef _merge_assets(
465*9e965d6fSRomain Jobredeaux        ctx,
466*9e965d6fSRomain Jobredeaux        out_assets_zip = None,
467*9e965d6fSRomain Jobredeaux        assets = [],
468*9e965d6fSRomain Jobredeaux        assets_dir = None,
469*9e965d6fSRomain Jobredeaux        symbols = None,
470*9e965d6fSRomain Jobredeaux        transitive_assets = [],
471*9e965d6fSRomain Jobredeaux        transitive_assets_symbols = [],
472*9e965d6fSRomain Jobredeaux        direct_resources_nodes = [],
473*9e965d6fSRomain Jobredeaux        transitive_resources_nodes = [],
474*9e965d6fSRomain Jobredeaux        busybox = None,
475*9e965d6fSRomain Jobredeaux        host_javabase = None):
476*9e965d6fSRomain Jobredeaux    """Merges Android assets.
477*9e965d6fSRomain Jobredeaux
478*9e965d6fSRomain Jobredeaux    Args:
479*9e965d6fSRomain Jobredeaux      ctx: The context.
480*9e965d6fSRomain Jobredeaux      out_assets_zip: A File.
481*9e965d6fSRomain Jobredeaux      assets: sequence of Files. A list of Android assets files to be processed.
482*9e965d6fSRomain Jobredeaux      assets_dir: String. The name of the assets directory.
483*9e965d6fSRomain Jobredeaux      symbols: A File. The parsed assets.
484*9e965d6fSRomain Jobredeaux      transitive_assets: Sequence of Depsets. The list of transitive
485*9e965d6fSRomain Jobredeaux        assets from deps.
486*9e965d6fSRomain Jobredeaux      transitive_assets_symbols: Sequence of Depsets. The list of
487*9e965d6fSRomain Jobredeaux        transitive assets_symbols files from deps.
488*9e965d6fSRomain Jobredeaux      direct_resources_nodes: Sequence of ResourcesNodeInfo providers. The list
489*9e965d6fSRomain Jobredeaux        of ResourcesNodeInfo providers that are direct depencies.
490*9e965d6fSRomain Jobredeaux      transitive_resources_nodes: Sequence of ResourcesNodeInfo providers. The
491*9e965d6fSRomain Jobredeaux        list of ResourcesNodeInfo providers that are transitive depencies.
492*9e965d6fSRomain Jobredeaux      busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable.
493*9e965d6fSRomain Jobredeaux      host_javabase: Target. The host javabase.
494*9e965d6fSRomain Jobredeaux    """
495*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
496*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s")
497*9e965d6fSRomain Jobredeaux    args.add("--tool", "MERGE_ASSETS")
498*9e965d6fSRomain Jobredeaux    args.add("--")
499*9e965d6fSRomain Jobredeaux    args.add("--assetsOutput", out_assets_zip)
500*9e965d6fSRomain Jobredeaux    args.add(
501*9e965d6fSRomain Jobredeaux        "--primaryData",
502*9e965d6fSRomain Jobredeaux        _make_serialized_resources_flag(
503*9e965d6fSRomain Jobredeaux            assets = assets,
504*9e965d6fSRomain Jobredeaux            assets_dir = assets_dir,
505*9e965d6fSRomain Jobredeaux            label = str(ctx.label),
506*9e965d6fSRomain Jobredeaux            symbols = symbols,
507*9e965d6fSRomain Jobredeaux        ),
508*9e965d6fSRomain Jobredeaux    )
509*9e965d6fSRomain Jobredeaux    args.add_joined(
510*9e965d6fSRomain Jobredeaux        "--directData",
511*9e965d6fSRomain Jobredeaux        direct_resources_nodes,
512*9e965d6fSRomain Jobredeaux        map_each = _make_merge_assets_flags,
513*9e965d6fSRomain Jobredeaux        join_with = "&",
514*9e965d6fSRomain Jobredeaux    )
515*9e965d6fSRomain Jobredeaux    args.add_joined(
516*9e965d6fSRomain Jobredeaux        "--data",
517*9e965d6fSRomain Jobredeaux        transitive_resources_nodes,
518*9e965d6fSRomain Jobredeaux        map_each = _make_merge_assets_flags,
519*9e965d6fSRomain Jobredeaux        join_with = "&",
520*9e965d6fSRomain Jobredeaux    )
521*9e965d6fSRomain Jobredeaux
522*9e965d6fSRomain Jobredeaux    _java.run(
523*9e965d6fSRomain Jobredeaux        ctx = ctx,
524*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
525*9e965d6fSRomain Jobredeaux        executable = busybox,
526*9e965d6fSRomain Jobredeaux        arguments = [args],
527*9e965d6fSRomain Jobredeaux        inputs = depset(
528*9e965d6fSRomain Jobredeaux            assets + [symbols],
529*9e965d6fSRomain Jobredeaux            transitive = transitive_assets + transitive_assets_symbols,
530*9e965d6fSRomain Jobredeaux        ),
531*9e965d6fSRomain Jobredeaux        outputs = [out_assets_zip],
532*9e965d6fSRomain Jobredeaux        mnemonic = "MergeAndroidAssets",
533*9e965d6fSRomain Jobredeaux        progress_message =
534*9e965d6fSRomain Jobredeaux            "Merging Android Assets in %s" % out_assets_zip.short_path,
535*9e965d6fSRomain Jobredeaux    )
536*9e965d6fSRomain Jobredeaux
537*9e965d6fSRomain Jobredeauxdef _validate_and_link(
538*9e965d6fSRomain Jobredeaux        ctx,
539*9e965d6fSRomain Jobredeaux        out_r_src_jar = None,
540*9e965d6fSRomain Jobredeaux        out_r_txt = None,
541*9e965d6fSRomain Jobredeaux        out_file = None,
542*9e965d6fSRomain Jobredeaux        compiled_resources = None,
543*9e965d6fSRomain Jobredeaux        transitive_compiled_resources = depset(),
544*9e965d6fSRomain Jobredeaux        java_package = None,
545*9e965d6fSRomain Jobredeaux        manifest = None,
546*9e965d6fSRomain Jobredeaux        resource_apks = [],
547*9e965d6fSRomain Jobredeaux        android_jar = None,
548*9e965d6fSRomain Jobredeaux        busybox = None,
549*9e965d6fSRomain Jobredeaux        host_javabase = None,
550*9e965d6fSRomain Jobredeaux        aapt = None):
551*9e965d6fSRomain Jobredeaux    """Links compiled Android Resources with AAPT.
552*9e965d6fSRomain Jobredeaux
553*9e965d6fSRomain Jobredeaux    Args:
554*9e965d6fSRomain Jobredeaux      ctx: The context.
555*9e965d6fSRomain Jobredeaux      out_r_src_jar: A File. The R.java outputted by linking resources in a srcjar.
556*9e965d6fSRomain Jobredeaux      out_r_txt: A File. The resource IDs outputted by linking resources in text.
557*9e965d6fSRomain Jobredeaux      out_file: A File. The Resource APK outputted by linking resources.
558*9e965d6fSRomain Jobredeaux      compiled_resources: A File. The symbols.zip of compiled resources for
559*9e965d6fSRomain Jobredeaux        this target.
560*9e965d6fSRomain Jobredeaux      transitive_compiled_resources: Depset of Files. The symbols.zip of the
561*9e965d6fSRomain Jobredeaux        compiled resources from the transitive dependencies of this target.
562*9e965d6fSRomain Jobredeaux      java_package: A string. The Java package for the generated R.java.
563*9e965d6fSRomain Jobredeaux      manifest: A File. The AndroidManifest.xml.
564*9e965d6fSRomain Jobredeaux      resource_apks: List of direct resource only apk files.
565*9e965d6fSRomain Jobredeaux      android_jar: A File. The Android Jar.
566*9e965d6fSRomain Jobredeaux      busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable.
567*9e965d6fSRomain Jobredeaux      host_javabase: Target. The host javabase.
568*9e965d6fSRomain Jobredeaux      aapt: A FilesToRunProvider. The AAPT executable.
569*9e965d6fSRomain Jobredeaux    """
570*9e965d6fSRomain Jobredeaux    output_files = []
571*9e965d6fSRomain Jobredeaux    input_files = [android_jar]
572*9e965d6fSRomain Jobredeaux    transitive_input_files = []
573*9e965d6fSRomain Jobredeaux
574*9e965d6fSRomain Jobredeaux    # Retrieves the list of files at runtime when a directory is passed.
575*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
576*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s")
577*9e965d6fSRomain Jobredeaux    args.add("--tool", "LINK_STATIC_LIBRARY")
578*9e965d6fSRomain Jobredeaux    args.add("--")
579*9e965d6fSRomain Jobredeaux    args.add("--aapt2", aapt.executable)
580*9e965d6fSRomain Jobredeaux    args.add("--libraries", android_jar)
581*9e965d6fSRomain Jobredeaux    if compiled_resources:
582*9e965d6fSRomain Jobredeaux        args.add("--compiled", compiled_resources)
583*9e965d6fSRomain Jobredeaux        input_files.append(compiled_resources)
584*9e965d6fSRomain Jobredeaux    args.add_joined(
585*9e965d6fSRomain Jobredeaux        "--compiledDep",
586*9e965d6fSRomain Jobredeaux        transitive_compiled_resources,
587*9e965d6fSRomain Jobredeaux        join_with = ":",
588*9e965d6fSRomain Jobredeaux    )
589*9e965d6fSRomain Jobredeaux    transitive_input_files.append(transitive_compiled_resources)
590*9e965d6fSRomain Jobredeaux    args.add("--manifest", manifest)
591*9e965d6fSRomain Jobredeaux    input_files.append(manifest)
592*9e965d6fSRomain Jobredeaux    if java_package:
593*9e965d6fSRomain Jobredeaux        args.add("--packageForR", java_package)
594*9e965d6fSRomain Jobredeaux    args.add("--sourceJarOut", out_r_src_jar)
595*9e965d6fSRomain Jobredeaux    output_files.append(out_r_src_jar)
596*9e965d6fSRomain Jobredeaux    args.add("--rTxtOut", out_r_txt)
597*9e965d6fSRomain Jobredeaux    output_files.append(out_r_txt)
598*9e965d6fSRomain Jobredeaux    args.add("--staticLibraryOut", out_file)
599*9e965d6fSRomain Jobredeaux    output_files.append(out_file)
600*9e965d6fSRomain Jobredeaux    args.add_joined(
601*9e965d6fSRomain Jobredeaux        "--resourceApks",
602*9e965d6fSRomain Jobredeaux        resource_apks,
603*9e965d6fSRomain Jobredeaux        join_with = ":",
604*9e965d6fSRomain Jobredeaux    )
605*9e965d6fSRomain Jobredeaux    input_files.extend(resource_apks)
606*9e965d6fSRomain Jobredeaux
607*9e965d6fSRomain Jobredeaux    _java.run(
608*9e965d6fSRomain Jobredeaux        ctx = ctx,
609*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
610*9e965d6fSRomain Jobredeaux        executable = busybox,
611*9e965d6fSRomain Jobredeaux        tools = [aapt],
612*9e965d6fSRomain Jobredeaux        arguments = [args],
613*9e965d6fSRomain Jobredeaux        inputs = depset(input_files, transitive = transitive_input_files),
614*9e965d6fSRomain Jobredeaux        outputs = output_files,
615*9e965d6fSRomain Jobredeaux        mnemonic = "LinkAndroidResources",
616*9e965d6fSRomain Jobredeaux        progress_message =
617*9e965d6fSRomain Jobredeaux            "Linking Android Resources in " + out_file.short_path,
618*9e965d6fSRomain Jobredeaux    )
619*9e965d6fSRomain Jobredeaux
620*9e965d6fSRomain Jobredeauxdef _compile(
621*9e965d6fSRomain Jobredeaux        ctx,
622*9e965d6fSRomain Jobredeaux        out_file = None,
623*9e965d6fSRomain Jobredeaux        assets = [],
624*9e965d6fSRomain Jobredeaux        assets_dir = None,
625*9e965d6fSRomain Jobredeaux        resource_files = [],
626*9e965d6fSRomain Jobredeaux        busybox = None,
627*9e965d6fSRomain Jobredeaux        aapt = None,
628*9e965d6fSRomain Jobredeaux        host_javabase = None):
629*9e965d6fSRomain Jobredeaux    """Compile and store resources in a single archive.
630*9e965d6fSRomain Jobredeaux
631*9e965d6fSRomain Jobredeaux    Args:
632*9e965d6fSRomain Jobredeaux      ctx: The context.
633*9e965d6fSRomain Jobredeaux      out_file: File. The output zip containing compiled resources.
634*9e965d6fSRomain Jobredeaux      resource_files: A list of Files. The list of resource files or directories
635*9e965d6fSRomain Jobredeaux      assets: A list of Files. The list of assets files or directories
636*9e965d6fSRomain Jobredeaux        to process.
637*9e965d6fSRomain Jobredeaux      assets_dir: String. The name of the assets directory.
638*9e965d6fSRomain Jobredeaux      busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable.
639*9e965d6fSRomain Jobredeaux      aapt: AAPT. Tool for compiling resources.
640*9e965d6fSRomain Jobredeaux      host_javabase: Target. The host javabase.
641*9e965d6fSRomain Jobredeaux    """
642*9e965d6fSRomain Jobredeaux    if not out_file:
643*9e965d6fSRomain Jobredeaux        fail("No output directory specified.")
644*9e965d6fSRomain Jobredeaux
645*9e965d6fSRomain Jobredeaux    # Retrieves the list of files at runtime when a directory is passed.
646*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
647*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s")
648*9e965d6fSRomain Jobredeaux    args.add("--tool", "COMPILE_LIBRARY_RESOURCES")
649*9e965d6fSRomain Jobredeaux    args.add("--")
650*9e965d6fSRomain Jobredeaux    args.add("--aapt2", aapt.executable)
651*9e965d6fSRomain Jobredeaux    args.add(
652*9e965d6fSRomain Jobredeaux        "--resources",
653*9e965d6fSRomain Jobredeaux        _make_resources_flag(
654*9e965d6fSRomain Jobredeaux            resource_files = resource_files,
655*9e965d6fSRomain Jobredeaux            assets = assets,
656*9e965d6fSRomain Jobredeaux            assets_dir = assets_dir,
657*9e965d6fSRomain Jobredeaux        ),
658*9e965d6fSRomain Jobredeaux    )
659*9e965d6fSRomain Jobredeaux    args.add("--output", out_file)
660*9e965d6fSRomain Jobredeaux
661*9e965d6fSRomain Jobredeaux    _java.run(
662*9e965d6fSRomain Jobredeaux        ctx = ctx,
663*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
664*9e965d6fSRomain Jobredeaux        executable = busybox,
665*9e965d6fSRomain Jobredeaux        tools = [aapt],
666*9e965d6fSRomain Jobredeaux        arguments = [args],
667*9e965d6fSRomain Jobredeaux        inputs = resource_files + assets,
668*9e965d6fSRomain Jobredeaux        outputs = [out_file],
669*9e965d6fSRomain Jobredeaux        mnemonic = "CompileAndroidResources",
670*9e965d6fSRomain Jobredeaux        progress_message = "Compiling Android Resources in %s" % out_file.short_path,
671*9e965d6fSRomain Jobredeaux    )
672*9e965d6fSRomain Jobredeaux
673*9e965d6fSRomain Jobredeauxdef _make_merge_compiled_flags(resources_node_info):
674*9e965d6fSRomain Jobredeaux    if not resources_node_info.compiled_resources:
675*9e965d6fSRomain Jobredeaux        return None
676*9e965d6fSRomain Jobredeaux    return _make_serialized_resources_flag(
677*9e965d6fSRomain Jobredeaux        label = str(resources_node_info.label),
678*9e965d6fSRomain Jobredeaux        symbols = resources_node_info.compiled_resources,
679*9e965d6fSRomain Jobredeaux    )
680*9e965d6fSRomain Jobredeaux
681*9e965d6fSRomain Jobredeauxdef _merge_compiled(
682*9e965d6fSRomain Jobredeaux        ctx,
683*9e965d6fSRomain Jobredeaux        out_class_jar = None,
684*9e965d6fSRomain Jobredeaux        out_manifest = None,
685*9e965d6fSRomain Jobredeaux        out_aapt2_r_txt = None,
686*9e965d6fSRomain Jobredeaux        java_package = None,
687*9e965d6fSRomain Jobredeaux        manifest = None,
688*9e965d6fSRomain Jobredeaux        compiled_resources = None,
689*9e965d6fSRomain Jobredeaux        direct_resources_nodes = [],
690*9e965d6fSRomain Jobredeaux        transitive_resources_nodes = [],
691*9e965d6fSRomain Jobredeaux        direct_compiled_resources = depset(),
692*9e965d6fSRomain Jobredeaux        transitive_compiled_resources = depset(),
693*9e965d6fSRomain Jobredeaux        android_jar = None,
694*9e965d6fSRomain Jobredeaux        busybox = None,
695*9e965d6fSRomain Jobredeaux        host_javabase = None):
696*9e965d6fSRomain Jobredeaux    """Merges the compile resources.
697*9e965d6fSRomain Jobredeaux
698*9e965d6fSRomain Jobredeaux    Args:
699*9e965d6fSRomain Jobredeaux      ctx: The context.
700*9e965d6fSRomain Jobredeaux      out_class_jar: A File. The compiled R.java outputted by linking resources.
701*9e965d6fSRomain Jobredeaux      out_manifest: A File. The list of resource files or directories
702*9e965d6fSRomain Jobredeaux      out_aapt2_r_txt: A File. The resource IDs outputted by linking resources in text.
703*9e965d6fSRomain Jobredeaux      java_package: A string. The Java package for the generated R.java.
704*9e965d6fSRomain Jobredeaux      manifest: A File. The AndroidManifest.xml.
705*9e965d6fSRomain Jobredeaux      compiled_resources: A File. The symbols.zip of compiled resources for this target.
706*9e965d6fSRomain Jobredeaux      direct_resources_nodes: Sequence of ResourcesNodeInfo providers. The list
707*9e965d6fSRomain Jobredeaux        of ResourcesNodeInfo providers that are direct depencies.
708*9e965d6fSRomain Jobredeaux      transitive_resources_nodes: Sequence of ResourcesNodeInfo providers. The
709*9e965d6fSRomain Jobredeaux        list of ResourcesNodeInfo providers that are transitive depencies.
710*9e965d6fSRomain Jobredeaux      direct_compiled_resources: Depset of Files. A depset of symbols.zip of
711*9e965d6fSRomain Jobredeaux        compiled resources from direct dependencies.
712*9e965d6fSRomain Jobredeaux      transitive_compiled_resources: Depset of Files. A depset of symbols.zip of
713*9e965d6fSRomain Jobredeaux        compiled resources from transitive dependencies.
714*9e965d6fSRomain Jobredeaux      android_jar: A File. The Android Jar.
715*9e965d6fSRomain Jobredeaux      busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable.
716*9e965d6fSRomain Jobredeaux      host_javabase: Target. The host javabase.
717*9e965d6fSRomain Jobredeaux    """
718*9e965d6fSRomain Jobredeaux    output_files = []
719*9e965d6fSRomain Jobredeaux    input_files = [android_jar]
720*9e965d6fSRomain Jobredeaux    transitive_input_files = []
721*9e965d6fSRomain Jobredeaux
722*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
723*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s")
724*9e965d6fSRomain Jobredeaux    args.add("--tool", "MERGE_COMPILED")
725*9e965d6fSRomain Jobredeaux    args.add("--")
726*9e965d6fSRomain Jobredeaux    args.add("--classJarOutput", out_class_jar)
727*9e965d6fSRomain Jobredeaux    output_files.append(out_class_jar)
728*9e965d6fSRomain Jobredeaux    args.add("--targetLabel", ctx.label)
729*9e965d6fSRomain Jobredeaux    args.add("--manifestOutput", out_manifest)
730*9e965d6fSRomain Jobredeaux    output_files.append(out_manifest)
731*9e965d6fSRomain Jobredeaux    args.add("--rTxtOut", out_aapt2_r_txt)
732*9e965d6fSRomain Jobredeaux    output_files.append(out_aapt2_r_txt)
733*9e965d6fSRomain Jobredeaux    args.add("--androidJar", android_jar)
734*9e965d6fSRomain Jobredeaux    args.add("--primaryManifest", manifest)
735*9e965d6fSRomain Jobredeaux    input_files.append(manifest)
736*9e965d6fSRomain Jobredeaux    if java_package:
737*9e965d6fSRomain Jobredeaux        args.add("--packageForR", java_package)
738*9e965d6fSRomain Jobredeaux    args.add(
739*9e965d6fSRomain Jobredeaux        "--primaryData",
740*9e965d6fSRomain Jobredeaux        _make_serialized_resources_flag(
741*9e965d6fSRomain Jobredeaux            label = str(ctx.label),
742*9e965d6fSRomain Jobredeaux            symbols = compiled_resources,
743*9e965d6fSRomain Jobredeaux        ),
744*9e965d6fSRomain Jobredeaux    )
745*9e965d6fSRomain Jobredeaux    input_files.append(compiled_resources)
746*9e965d6fSRomain Jobredeaux    args.add_joined(
747*9e965d6fSRomain Jobredeaux        "--directData",
748*9e965d6fSRomain Jobredeaux        direct_resources_nodes,
749*9e965d6fSRomain Jobredeaux        map_each = _make_merge_compiled_flags,
750*9e965d6fSRomain Jobredeaux        join_with = "&",
751*9e965d6fSRomain Jobredeaux    )
752*9e965d6fSRomain Jobredeaux    transitive_input_files.append(direct_compiled_resources)
753*9e965d6fSRomain Jobredeaux    if _ANDROID_RESOURCES_STRICT_DEPS in ctx.disabled_features:
754*9e965d6fSRomain Jobredeaux        args.add_joined(
755*9e965d6fSRomain Jobredeaux            "--data",
756*9e965d6fSRomain Jobredeaux            transitive_resources_nodes,
757*9e965d6fSRomain Jobredeaux            map_each = _make_merge_compiled_flags,
758*9e965d6fSRomain Jobredeaux            join_with = "&",
759*9e965d6fSRomain Jobredeaux        )
760*9e965d6fSRomain Jobredeaux        transitive_input_files.append(transitive_compiled_resources)
761*9e965d6fSRomain Jobredeaux
762*9e965d6fSRomain Jobredeaux    _java.run(
763*9e965d6fSRomain Jobredeaux        ctx = ctx,
764*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
765*9e965d6fSRomain Jobredeaux        executable = busybox,
766*9e965d6fSRomain Jobredeaux        arguments = [args],
767*9e965d6fSRomain Jobredeaux        inputs = depset(input_files, transitive = transitive_input_files),
768*9e965d6fSRomain Jobredeaux        outputs = output_files,
769*9e965d6fSRomain Jobredeaux        mnemonic = "StarlarkMergeCompiledAndroidResources",
770*9e965d6fSRomain Jobredeaux        progress_message =
771*9e965d6fSRomain Jobredeaux            "Merging compiled Android Resources in " + out_class_jar.short_path,
772*9e965d6fSRomain Jobredeaux    )
773*9e965d6fSRomain Jobredeaux
774*9e965d6fSRomain Jobredeauxdef _escape_mv(s):
775*9e965d6fSRomain Jobredeaux    """Escapes `:` and `,` in manifest values so they can be used as a busybox flag."""
776*9e965d6fSRomain Jobredeaux    return s.replace(":", "\\:").replace(",", "\\,")
777*9e965d6fSRomain Jobredeaux
778*9e965d6fSRomain Jobredeauxdef _owner_label(file):
779*9e965d6fSRomain Jobredeaux    return "//" + file.owner.package + ":" + file.owner.name
780*9e965d6fSRomain Jobredeaux
781*9e965d6fSRomain Jobredeaux# We need to remove the "/_migrated/" path segment from file paths in order for sorting to
782*9e965d6fSRomain Jobredeaux# match the order of the native manifest merging action.
783*9e965d6fSRomain Jobredeauxdef _manifest_short_path(manifest):
784*9e965d6fSRomain Jobredeaux    return manifest.short_path.replace("/_migrated/", "/")
785*9e965d6fSRomain Jobredeaux
786*9e965d6fSRomain Jobredeauxdef _mergee_manifests_flag(manifests):
787*9e965d6fSRomain Jobredeaux    ordered_manifests = sorted(manifests.to_list(), key = _manifest_short_path)
788*9e965d6fSRomain Jobredeaux    entries = []
789*9e965d6fSRomain Jobredeaux    for manifest in ordered_manifests:
790*9e965d6fSRomain Jobredeaux        label = _owner_label(manifest).replace(":", "\\:")
791*9e965d6fSRomain Jobredeaux        entries.append((manifest.path + ":" + label).replace(",", "\\,"))
792*9e965d6fSRomain Jobredeaux    flag_entry = ",".join(entries)
793*9e965d6fSRomain Jobredeaux    if not flag_entry:
794*9e965d6fSRomain Jobredeaux        return None
795*9e965d6fSRomain Jobredeaux    return flag_entry
796*9e965d6fSRomain Jobredeaux
797*9e965d6fSRomain Jobredeauxdef _merge_manifests(
798*9e965d6fSRomain Jobredeaux        ctx,
799*9e965d6fSRomain Jobredeaux        out_file = None,
800*9e965d6fSRomain Jobredeaux        out_log_file = None,
801*9e965d6fSRomain Jobredeaux        merge_type = "APPLICATION",
802*9e965d6fSRomain Jobredeaux        manifest = None,
803*9e965d6fSRomain Jobredeaux        mergee_manifests = depset(),
804*9e965d6fSRomain Jobredeaux        manifest_values = None,
805*9e965d6fSRomain Jobredeaux        java_package = None,
806*9e965d6fSRomain Jobredeaux        busybox = None,
807*9e965d6fSRomain Jobredeaux        host_javabase = None):
808*9e965d6fSRomain Jobredeaux    """Merge multiple AndroidManifest.xml files into a single one.
809*9e965d6fSRomain Jobredeaux
810*9e965d6fSRomain Jobredeaux    Args:
811*9e965d6fSRomain Jobredeaux      ctx: The context.
812*9e965d6fSRomain Jobredeaux      out_file: A File. The output merged manifest.
813*9e965d6fSRomain Jobredeaux      out_log_file: A File. The output log from the merge tool.
814*9e965d6fSRomain Jobredeaux      merge_type: A string, either APPLICATION or LIBRARY. Type of merging.
815*9e965d6fSRomain Jobredeaux      manifest: A File. The primary AndroidManifest.xml.
816*9e965d6fSRomain Jobredeaux      mergee_manifests: A depset of Files. All transitive manifests to be merged.
817*9e965d6fSRomain Jobredeaux      manifest_values: A dictionary. Manifest values to substitute.
818*9e965d6fSRomain Jobredeaux      java_package: A string. Custom java package to insert in manifest package attribute.
819*9e965d6fSRomain Jobredeaux      busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable.
820*9e965d6fSRomain Jobredeaux      host_javabase: Target. The host javabase.
821*9e965d6fSRomain Jobredeaux    """
822*9e965d6fSRomain Jobredeaux    if merge_type not in ["APPLICATION", "LIBRARY"]:
823*9e965d6fSRomain Jobredeaux        fail("Unexpected manifest merge type: " + merge_type)
824*9e965d6fSRomain Jobredeaux
825*9e965d6fSRomain Jobredeaux    outputs = [out_file]
826*9e965d6fSRomain Jobredeaux    directs = [manifest] if manifest else []
827*9e965d6fSRomain Jobredeaux    transitives = [mergee_manifests]
828*9e965d6fSRomain Jobredeaux
829*9e965d6fSRomain Jobredeaux    # Args for busybox
830*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
831*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s", use_always = True)
832*9e965d6fSRomain Jobredeaux    args.add("--tool", "MERGE_MANIFEST")
833*9e965d6fSRomain Jobredeaux    args.add("--")
834*9e965d6fSRomain Jobredeaux    if manifest:
835*9e965d6fSRomain Jobredeaux        args.add("--manifest", manifest)
836*9e965d6fSRomain Jobredeaux    args.add_all(
837*9e965d6fSRomain Jobredeaux        "--mergeeManifests",
838*9e965d6fSRomain Jobredeaux        [mergee_manifests],
839*9e965d6fSRomain Jobredeaux        map_each = _mergee_manifests_flag,
840*9e965d6fSRomain Jobredeaux    )
841*9e965d6fSRomain Jobredeaux    if manifest_values:
842*9e965d6fSRomain Jobredeaux        args.add(
843*9e965d6fSRomain Jobredeaux            "--manifestValues",
844*9e965d6fSRomain Jobredeaux            ",".join(["%s:%s" % (_escape_mv(k), _escape_mv(v)) for k, v in manifest_values.items()]),
845*9e965d6fSRomain Jobredeaux        )
846*9e965d6fSRomain Jobredeaux    args.add("--mergeType", merge_type)
847*9e965d6fSRomain Jobredeaux    if java_package:
848*9e965d6fSRomain Jobredeaux        args.add("--customPackage", java_package)
849*9e965d6fSRomain Jobredeaux    args.add("--manifestOutput", out_file)
850*9e965d6fSRomain Jobredeaux    if out_log_file:
851*9e965d6fSRomain Jobredeaux        args.add("--log", out_log_file)
852*9e965d6fSRomain Jobredeaux        outputs.append(out_log_file)
853*9e965d6fSRomain Jobredeaux
854*9e965d6fSRomain Jobredeaux    _java.run(
855*9e965d6fSRomain Jobredeaux        ctx = ctx,
856*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
857*9e965d6fSRomain Jobredeaux        executable = busybox,
858*9e965d6fSRomain Jobredeaux        arguments = [args],
859*9e965d6fSRomain Jobredeaux        inputs = depset(directs, transitive = transitives),
860*9e965d6fSRomain Jobredeaux        outputs = outputs,
861*9e965d6fSRomain Jobredeaux        mnemonic = "MergeManifests",
862*9e965d6fSRomain Jobredeaux        progress_message = "Merging Android Manifests in %s" % out_file.short_path,
863*9e965d6fSRomain Jobredeaux    )
864*9e965d6fSRomain Jobredeaux
865*9e965d6fSRomain Jobredeauxdef _process_databinding(
866*9e965d6fSRomain Jobredeaux        ctx,
867*9e965d6fSRomain Jobredeaux        out_databinding_info = None,
868*9e965d6fSRomain Jobredeaux        out_databinding_processed_resources = None,
869*9e965d6fSRomain Jobredeaux        databinding_resources_dirname = None,
870*9e965d6fSRomain Jobredeaux        resource_files = None,
871*9e965d6fSRomain Jobredeaux        java_package = None,
872*9e965d6fSRomain Jobredeaux        busybox = None,
873*9e965d6fSRomain Jobredeaux        host_javabase = None):
874*9e965d6fSRomain Jobredeaux    """Processes databinding for android_binary.
875*9e965d6fSRomain Jobredeaux
876*9e965d6fSRomain Jobredeaux    Processes databinding declarations over resources, populates the databinding layout
877*9e965d6fSRomain Jobredeaux    info file, and generates new resources with databinding expressions stripped out.
878*9e965d6fSRomain Jobredeaux
879*9e965d6fSRomain Jobredeaux    Args:
880*9e965d6fSRomain Jobredeaux      ctx: The context.
881*9e965d6fSRomain Jobredeaux      out_databinding_info: File. The output databinding layout info zip file.
882*9e965d6fSRomain Jobredeaux      out_databinding_processed_resources: List of Files. The generated databinding
883*9e965d6fSRomain Jobredeaux        processed resource files.
884*9e965d6fSRomain Jobredeaux      databinding_resources_dirname: String. The execution path to the directory where
885*9e965d6fSRomain Jobredeaux      the out_databinding_processed_resources are generated.
886*9e965d6fSRomain Jobredeaux      resource_files: List of Files. The resource files to be processed.
887*9e965d6fSRomain Jobredeaux      java_package: String. Java package for which java sources will be
888*9e965d6fSRomain Jobredeaux        generated. By default the package is inferred from the directory where
889*9e965d6fSRomain Jobredeaux        the BUILD file containing the rule is.
890*9e965d6fSRomain Jobredeaux      busybox: FilesToRunProvider. The ResourceBusyBox executable or
891*9e965d6fSRomain Jobredeaux        FilesToRunprovider
892*9e965d6fSRomain Jobredeaux      host_javabase: A Target. The host javabase.
893*9e965d6fSRomain Jobredeaux    """
894*9e965d6fSRomain Jobredeaux    res_dirs = _get_unique_res_dirs(resource_files)
895*9e965d6fSRomain Jobredeaux
896*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
897*9e965d6fSRomain Jobredeaux    args.add("--tool", "PROCESS_DATABINDING")
898*9e965d6fSRomain Jobredeaux    args.add("--")
899*9e965d6fSRomain Jobredeaux    args.add("--output_resource_directory", databinding_resources_dirname)
900*9e965d6fSRomain Jobredeaux    args.add_all(res_dirs, before_each = "--resource_root")
901*9e965d6fSRomain Jobredeaux    args.add("--dataBindingInfoOut", out_databinding_info)
902*9e965d6fSRomain Jobredeaux    args.add("--appId", java_package)
903*9e965d6fSRomain Jobredeaux
904*9e965d6fSRomain Jobredeaux    _java.run(
905*9e965d6fSRomain Jobredeaux        ctx = ctx,
906*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
907*9e965d6fSRomain Jobredeaux        executable = busybox,
908*9e965d6fSRomain Jobredeaux        arguments = [args],
909*9e965d6fSRomain Jobredeaux        inputs = resource_files,
910*9e965d6fSRomain Jobredeaux        outputs = [out_databinding_info] + out_databinding_processed_resources,
911*9e965d6fSRomain Jobredeaux        mnemonic = "StarlarkProcessDatabinding",
912*9e965d6fSRomain Jobredeaux        progress_message = "Processing data binding",
913*9e965d6fSRomain Jobredeaux    )
914*9e965d6fSRomain Jobredeaux
915*9e965d6fSRomain Jobredeauxdef _make_generate_binay_r_flags(resources_node):
916*9e965d6fSRomain Jobredeaux    if not (resources_node.r_txt or resources_node.manifest):
917*9e965d6fSRomain Jobredeaux        return None
918*9e965d6fSRomain Jobredeaux    return ",".join(
919*9e965d6fSRomain Jobredeaux        [
920*9e965d6fSRomain Jobredeaux            resources_node.r_txt.path if resources_node.r_txt else "",
921*9e965d6fSRomain Jobredeaux            resources_node.manifest.path if resources_node.manifest else "",
922*9e965d6fSRomain Jobredeaux        ],
923*9e965d6fSRomain Jobredeaux    )
924*9e965d6fSRomain Jobredeaux
925*9e965d6fSRomain Jobredeauxdef _generate_binary_r(
926*9e965d6fSRomain Jobredeaux        ctx,
927*9e965d6fSRomain Jobredeaux        out_class_jar = None,
928*9e965d6fSRomain Jobredeaux        r_txt = None,
929*9e965d6fSRomain Jobredeaux        manifest = None,
930*9e965d6fSRomain Jobredeaux        package_for_r = None,
931*9e965d6fSRomain Jobredeaux        final_fields = None,
932*9e965d6fSRomain Jobredeaux        resources_nodes = depset(),
933*9e965d6fSRomain Jobredeaux        transitive_r_txts = [],
934*9e965d6fSRomain Jobredeaux        transitive_manifests = [],
935*9e965d6fSRomain Jobredeaux        busybox = None,
936*9e965d6fSRomain Jobredeaux        host_javabase = None):
937*9e965d6fSRomain Jobredeaux    """Generate compiled resources class jar.
938*9e965d6fSRomain Jobredeaux
939*9e965d6fSRomain Jobredeaux    Args:
940*9e965d6fSRomain Jobredeaux      ctx: The context.
941*9e965d6fSRomain Jobredeaux      out_class_jar: File. The output class jar file.
942*9e965d6fSRomain Jobredeaux      r_txt: File. The resource IDs outputted by linking resources in text.
943*9e965d6fSRomain Jobredeaux      manifest: File. The primary AndroidManifest.xml.
944*9e965d6fSRomain Jobredeaux      package_for_r: String. The Java package for the generated R class files.
945*9e965d6fSRomain Jobredeaux      final_fields: Bool. Whether fields get declared as final.
946*9e965d6fSRomain Jobredeaux      busybox: FilesToRunProvider. The ResourceBusyBox executable or
947*9e965d6fSRomain Jobredeaux        FilesToRunprovider
948*9e965d6fSRomain Jobredeaux      host_javabase: A Target. The host javabase.
949*9e965d6fSRomain Jobredeaux    """
950*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
951*9e965d6fSRomain Jobredeaux    args.add("--tool", "GENERATE_BINARY_R")
952*9e965d6fSRomain Jobredeaux    args.add("--")
953*9e965d6fSRomain Jobredeaux    args.add("--primaryRTxt", r_txt)
954*9e965d6fSRomain Jobredeaux    args.add("--primaryManifest", manifest)
955*9e965d6fSRomain Jobredeaux    if package_for_r:
956*9e965d6fSRomain Jobredeaux        args.add("--packageForR", package_for_r)
957*9e965d6fSRomain Jobredeaux    args.add_all(
958*9e965d6fSRomain Jobredeaux        resources_nodes,
959*9e965d6fSRomain Jobredeaux        map_each = _make_generate_binay_r_flags,
960*9e965d6fSRomain Jobredeaux        before_each = "--library",
961*9e965d6fSRomain Jobredeaux    )
962*9e965d6fSRomain Jobredeaux    if final_fields:
963*9e965d6fSRomain Jobredeaux        args.add("--finalFields")
964*9e965d6fSRomain Jobredeaux    else:
965*9e965d6fSRomain Jobredeaux        args.add("--nofinalFields")
966*9e965d6fSRomain Jobredeaux
967*9e965d6fSRomain Jobredeaux    # TODO(b/154003916): support transitive "--library transitive_r_txt_path,transitive_manifest_path" flags
968*9e965d6fSRomain Jobredeaux    args.add("--classJarOutput", out_class_jar)
969*9e965d6fSRomain Jobredeaux    args.add("--targetLabel", str(ctx.label))
970*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s")
971*9e965d6fSRomain Jobredeaux
972*9e965d6fSRomain Jobredeaux    _java.run(
973*9e965d6fSRomain Jobredeaux        ctx = ctx,
974*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
975*9e965d6fSRomain Jobredeaux        executable = busybox,
976*9e965d6fSRomain Jobredeaux        arguments = [args],
977*9e965d6fSRomain Jobredeaux        inputs = depset([r_txt, manifest], transitive = transitive_r_txts + transitive_manifests),
978*9e965d6fSRomain Jobredeaux        outputs = [out_class_jar],
979*9e965d6fSRomain Jobredeaux        mnemonic = "StarlarkRClassGenerator",
980*9e965d6fSRomain Jobredeaux        progress_message = "Generating R classes",
981*9e965d6fSRomain Jobredeaux    )
982*9e965d6fSRomain Jobredeaux
983*9e965d6fSRomain Jobredeauxdef _make_aar(
984*9e965d6fSRomain Jobredeaux        ctx,
985*9e965d6fSRomain Jobredeaux        out_aar = None,
986*9e965d6fSRomain Jobredeaux        assets = [],
987*9e965d6fSRomain Jobredeaux        assets_dir = None,
988*9e965d6fSRomain Jobredeaux        resource_files = [],
989*9e965d6fSRomain Jobredeaux        class_jar = None,
990*9e965d6fSRomain Jobredeaux        r_txt = None,
991*9e965d6fSRomain Jobredeaux        manifest = None,
992*9e965d6fSRomain Jobredeaux        proguard_specs = [],
993*9e965d6fSRomain Jobredeaux        should_throw_on_conflict = False,
994*9e965d6fSRomain Jobredeaux        busybox = None,
995*9e965d6fSRomain Jobredeaux        host_javabase = None):
996*9e965d6fSRomain Jobredeaux    """Generate an android archive file.
997*9e965d6fSRomain Jobredeaux
998*9e965d6fSRomain Jobredeaux    Args:
999*9e965d6fSRomain Jobredeaux      ctx: The context.
1000*9e965d6fSRomain Jobredeaux      out_aar: File. The output AAR file.
1001*9e965d6fSRomain Jobredeaux      assets: sequence of Files. A list of Android assets files to be processed.
1002*9e965d6fSRomain Jobredeaux      assets_dir: String. The name of the assets directory.
1003*9e965d6fSRomain Jobredeaux      resource_files: A list of Files. The resource files.
1004*9e965d6fSRomain Jobredeaux      class_jar: File. The class jar file.
1005*9e965d6fSRomain Jobredeaux      r_txt: File. The resource IDs outputted by linking resources in text.
1006*9e965d6fSRomain Jobredeaux      manifest: File. The primary AndroidManifest.xml.
1007*9e965d6fSRomain Jobredeaux      proguard_specs: List of File. The proguard spec files.
1008*9e965d6fSRomain Jobredeaux      busybox: FilesToRunProvider. The ResourceBusyBox executable or
1009*9e965d6fSRomain Jobredeaux        FilesToRunprovider
1010*9e965d6fSRomain Jobredeaux      host_javabase: A Target. The host javabase.
1011*9e965d6fSRomain Jobredeaux      should_throw_on_conflict: A boolean. Determines whether an error should be thrown
1012*9e965d6fSRomain Jobredeaux        when a resource conflict occurs.
1013*9e965d6fSRomain Jobredeaux    """
1014*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
1015*9e965d6fSRomain Jobredeaux    args.add("--tool", "GENERATE_AAR")
1016*9e965d6fSRomain Jobredeaux    args.add("--")
1017*9e965d6fSRomain Jobredeaux    args.add(
1018*9e965d6fSRomain Jobredeaux        "--mainData",
1019*9e965d6fSRomain Jobredeaux        _make_resources_flag(
1020*9e965d6fSRomain Jobredeaux            manifest = manifest,
1021*9e965d6fSRomain Jobredeaux            assets = assets,
1022*9e965d6fSRomain Jobredeaux            assets_dir = assets_dir,
1023*9e965d6fSRomain Jobredeaux            resource_files = resource_files,
1024*9e965d6fSRomain Jobredeaux        ),
1025*9e965d6fSRomain Jobredeaux    )
1026*9e965d6fSRomain Jobredeaux    args.add("--manifest", manifest)
1027*9e965d6fSRomain Jobredeaux    args.add("--rtxt", r_txt)
1028*9e965d6fSRomain Jobredeaux    args.add("--classes", class_jar)
1029*9e965d6fSRomain Jobredeaux    args.add("--aarOutput", out_aar)
1030*9e965d6fSRomain Jobredeaux    args.add_all(proguard_specs, before_each = "--proguardSpec")
1031*9e965d6fSRomain Jobredeaux    if should_throw_on_conflict:
1032*9e965d6fSRomain Jobredeaux        args.add("--throwOnResourceConflict")
1033*9e965d6fSRomain Jobredeaux
1034*9e965d6fSRomain Jobredeaux    _java.run(
1035*9e965d6fSRomain Jobredeaux        ctx = ctx,
1036*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
1037*9e965d6fSRomain Jobredeaux        executable = busybox,
1038*9e965d6fSRomain Jobredeaux        arguments = [args],
1039*9e965d6fSRomain Jobredeaux        inputs = (
1040*9e965d6fSRomain Jobredeaux            resource_files +
1041*9e965d6fSRomain Jobredeaux            assets +
1042*9e965d6fSRomain Jobredeaux            proguard_specs +
1043*9e965d6fSRomain Jobredeaux            [r_txt, manifest, class_jar]
1044*9e965d6fSRomain Jobredeaux        ),
1045*9e965d6fSRomain Jobredeaux        outputs = [out_aar],
1046*9e965d6fSRomain Jobredeaux        mnemonic = "StarlarkAARGenerator",
1047*9e965d6fSRomain Jobredeaux        progress_message = "Generating AAR package for %s" % ctx.label,
1048*9e965d6fSRomain Jobredeaux    )
1049*9e965d6fSRomain Jobredeaux
1050*9e965d6fSRomain Jobredeauxdef _shrink(
1051*9e965d6fSRomain Jobredeaux        ctx,
1052*9e965d6fSRomain Jobredeaux        out_apk,
1053*9e965d6fSRomain Jobredeaux        out_zip,
1054*9e965d6fSRomain Jobredeaux        out_log,
1055*9e965d6fSRomain Jobredeaux        out_config = None,
1056*9e965d6fSRomain Jobredeaux        resources_zip = None,
1057*9e965d6fSRomain Jobredeaux        aapt = None,
1058*9e965d6fSRomain Jobredeaux        android_jar = None,
1059*9e965d6fSRomain Jobredeaux        r_txt = None,
1060*9e965d6fSRomain Jobredeaux        shrunk_jar = None,
1061*9e965d6fSRomain Jobredeaux        proguard_mapping = None,
1062*9e965d6fSRomain Jobredeaux        debug = True,
1063*9e965d6fSRomain Jobredeaux        busybox = None,
1064*9e965d6fSRomain Jobredeaux        host_javabase = None):
1065*9e965d6fSRomain Jobredeaux    """Shrinks the resource apk by removing the resources unused from the packaged app.
1066*9e965d6fSRomain Jobredeaux
1067*9e965d6fSRomain Jobredeaux    Args:
1068*9e965d6fSRomain Jobredeaux        ctx: The context.
1069*9e965d6fSRomain Jobredeaux        out_apk: File. The output shrunk resource ap_ package.
1070*9e965d6fSRomain Jobredeaux        out_zip: File. The output shrunk resources file zip.
1071*9e965d6fSRomain Jobredeaux        out_log: File. The output shrinker log.
1072*9e965d6fSRomain Jobredeaux        out_config: File. The output config for the optimizer.
1073*9e965d6fSRomain Jobredeaux        resources_zip: File. The input resources file zip.
1074*9e965d6fSRomain Jobredeaux        aapt: FilesToRunProvider. The AAPT executable.
1075*9e965d6fSRomain Jobredeaux        android_jar: File. The Android Jar.
1076*9e965d6fSRomain Jobredeaux        r_txt: File. The resource IDs outputted by linking resources in text.
1077*9e965d6fSRomain Jobredeaux        shrunk_jar: File. The proguarded jar.
1078*9e965d6fSRomain Jobredeaux        proguard_mapping: File. The Proguard Mapping file.
1079*9e965d6fSRomain Jobredeaux        debug: Boolean. Whether to enable debug mode.
1080*9e965d6fSRomain Jobredeaux        busybox: FilesToRunProvider. The ResourceBusyBox executable.
1081*9e965d6fSRomain Jobredeaux        host_javabase: Target. The host javabase.
1082*9e965d6fSRomain Jobredeaux    """
1083*9e965d6fSRomain Jobredeaux
1084*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
1085*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s")
1086*9e965d6fSRomain Jobredeaux    args.add("--tool", "SHRINK_AAPT2")
1087*9e965d6fSRomain Jobredeaux    args.add("--")
1088*9e965d6fSRomain Jobredeaux    args.add("--aapt2", aapt.executable)
1089*9e965d6fSRomain Jobredeaux    args.add("--androidJar", android_jar)
1090*9e965d6fSRomain Jobredeaux    args.add("--resources", resources_zip)
1091*9e965d6fSRomain Jobredeaux    args.add("--shrunkJar", shrunk_jar)
1092*9e965d6fSRomain Jobredeaux    args.add("--proguardMapping", proguard_mapping)
1093*9e965d6fSRomain Jobredeaux    args.add("--rTxt", r_txt)
1094*9e965d6fSRomain Jobredeaux    args.add("--shrunkResourceApk", out_apk)
1095*9e965d6fSRomain Jobredeaux    args.add("--shrunkResources", out_zip)
1096*9e965d6fSRomain Jobredeaux    args.add("--log", out_log)
1097*9e965d6fSRomain Jobredeaux    args.add("--useDataBindingAndroidX")
1098*9e965d6fSRomain Jobredeaux    if debug:
1099*9e965d6fSRomain Jobredeaux        args.add("--debug")
1100*9e965d6fSRomain Jobredeaux
1101*9e965d6fSRomain Jobredeaux    input_files = [
1102*9e965d6fSRomain Jobredeaux        android_jar,
1103*9e965d6fSRomain Jobredeaux        resources_zip,
1104*9e965d6fSRomain Jobredeaux        shrunk_jar,
1105*9e965d6fSRomain Jobredeaux        proguard_mapping,
1106*9e965d6fSRomain Jobredeaux        r_txt,
1107*9e965d6fSRomain Jobredeaux    ]
1108*9e965d6fSRomain Jobredeaux    output_files = [
1109*9e965d6fSRomain Jobredeaux        out_apk,
1110*9e965d6fSRomain Jobredeaux        out_zip,
1111*9e965d6fSRomain Jobredeaux        out_log,
1112*9e965d6fSRomain Jobredeaux    ]
1113*9e965d6fSRomain Jobredeaux    if out_config:
1114*9e965d6fSRomain Jobredeaux        args.add("--resourcesConfigOutput", out_config)
1115*9e965d6fSRomain Jobredeaux        output_files.append(out_config)
1116*9e965d6fSRomain Jobredeaux
1117*9e965d6fSRomain Jobredeaux    _java.run(
1118*9e965d6fSRomain Jobredeaux        ctx = ctx,
1119*9e965d6fSRomain Jobredeaux        executable = busybox,
1120*9e965d6fSRomain Jobredeaux        tools = [aapt],
1121*9e965d6fSRomain Jobredeaux        outputs = output_files,
1122*9e965d6fSRomain Jobredeaux        inputs = input_files,
1123*9e965d6fSRomain Jobredeaux        arguments = [args],
1124*9e965d6fSRomain Jobredeaux        mnemonic = "ResourceShrinker",
1125*9e965d6fSRomain Jobredeaux        progress_message =
1126*9e965d6fSRomain Jobredeaux            "Shrinking resources for " + str(ctx.label),
1127*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
1128*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
1129*9e965d6fSRomain Jobredeaux    )
1130*9e965d6fSRomain Jobredeaux
1131*9e965d6fSRomain Jobredeauxdef _optimize(
1132*9e965d6fSRomain Jobredeaux        ctx,
1133*9e965d6fSRomain Jobredeaux        out_apk,
1134*9e965d6fSRomain Jobredeaux        in_apk,
1135*9e965d6fSRomain Jobredeaux        resource_path_shortening_map = None,
1136*9e965d6fSRomain Jobredeaux        resource_optimization_config = None,
1137*9e965d6fSRomain Jobredeaux        aapt = None,
1138*9e965d6fSRomain Jobredeaux        busybox = None,
1139*9e965d6fSRomain Jobredeaux        host_javabase = None):
1140*9e965d6fSRomain Jobredeaux    """Optimizes the resource apk including resource obfuscation, sparse encoding and path shortening.
1141*9e965d6fSRomain Jobredeaux
1142*9e965d6fSRomain Jobredeaux    Args:
1143*9e965d6fSRomain Jobredeaux        ctx: The context.
1144*9e965d6fSRomain Jobredeaux        out_apk: File. The output optimized resource ap_ package.
1145*9e965d6fSRomain Jobredeaux        in_apk: File. The resource ap_ package to be optimized.
1146*9e965d6fSRomain Jobredeaux        resource_path_shortening_map: File. The output path shortening map. Optional.
1147*9e965d6fSRomain Jobredeaux        resource_optimization_config: File. The input optimization config. Optional.
1148*9e965d6fSRomain Jobredeaux        aapt: FilesToRunProvider. The AAPT executable.
1149*9e965d6fSRomain Jobredeaux        busybox: FilesToRunProvider. The ResourceBusyBox executable.
1150*9e965d6fSRomain Jobredeaux        host_javabase: Target. The host javabase.
1151*9e965d6fSRomain Jobredeaux    """
1152*9e965d6fSRomain Jobredeaux
1153*9e965d6fSRomain Jobredeaux    output_files = [out_apk]
1154*9e965d6fSRomain Jobredeaux    input_files = [in_apk]
1155*9e965d6fSRomain Jobredeaux
1156*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
1157*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s")
1158*9e965d6fSRomain Jobredeaux    args.add("--tool", "AAPT2_OPTIMIZE")
1159*9e965d6fSRomain Jobredeaux    args.add("--")
1160*9e965d6fSRomain Jobredeaux    args.add("--aapt2", aapt.executable)
1161*9e965d6fSRomain Jobredeaux    args.add("--")
1162*9e965d6fSRomain Jobredeaux    if resource_path_shortening_map:
1163*9e965d6fSRomain Jobredeaux        args.add("--shorten-resource-paths")
1164*9e965d6fSRomain Jobredeaux        args.add("--resource-path-shortening-map", resource_path_shortening_map)
1165*9e965d6fSRomain Jobredeaux        output_files.append(resource_path_shortening_map)
1166*9e965d6fSRomain Jobredeaux    if resource_optimization_config:
1167*9e965d6fSRomain Jobredeaux        args.add("--collapse-resource-names")
1168*9e965d6fSRomain Jobredeaux        args.add("--resources-config-path", resource_optimization_config)
1169*9e965d6fSRomain Jobredeaux        input_files.append(resource_optimization_config)
1170*9e965d6fSRomain Jobredeaux    args.add("-o", out_apk)
1171*9e965d6fSRomain Jobredeaux    args.add(in_apk)
1172*9e965d6fSRomain Jobredeaux
1173*9e965d6fSRomain Jobredeaux    _java.run(
1174*9e965d6fSRomain Jobredeaux        ctx = ctx,
1175*9e965d6fSRomain Jobredeaux        host_javabase = host_javabase,
1176*9e965d6fSRomain Jobredeaux        executable = busybox,
1177*9e965d6fSRomain Jobredeaux        tools = [aapt],
1178*9e965d6fSRomain Jobredeaux        arguments = [args],
1179*9e965d6fSRomain Jobredeaux        inputs = input_files,
1180*9e965d6fSRomain Jobredeaux        outputs = output_files,
1181*9e965d6fSRomain Jobredeaux        mnemonic = "Aapt2Optimize",
1182*9e965d6fSRomain Jobredeaux        progress_message =
1183*9e965d6fSRomain Jobredeaux            "Optimizing Android resources for " + str(ctx.label),
1184*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
1185*9e965d6fSRomain Jobredeaux    )
1186*9e965d6fSRomain Jobredeaux
1187*9e965d6fSRomain Jobredeauxbusybox = struct(
1188*9e965d6fSRomain Jobredeaux    compile = _compile,
1189*9e965d6fSRomain Jobredeaux    merge_compiled = _merge_compiled,
1190*9e965d6fSRomain Jobredeaux    validate_and_link = _validate_and_link,
1191*9e965d6fSRomain Jobredeaux    merge_manifests = _merge_manifests,
1192*9e965d6fSRomain Jobredeaux    package = _package,
1193*9e965d6fSRomain Jobredeaux    parse = _parse,
1194*9e965d6fSRomain Jobredeaux    merge_assets = _merge_assets,
1195*9e965d6fSRomain Jobredeaux    make_resources_flag = _make_resources_flag,
1196*9e965d6fSRomain Jobredeaux    process_databinding = _process_databinding,
1197*9e965d6fSRomain Jobredeaux    generate_binary_r = _generate_binary_r,
1198*9e965d6fSRomain Jobredeaux    make_aar = _make_aar,
1199*9e965d6fSRomain Jobredeaux    shrink = _shrink,
1200*9e965d6fSRomain Jobredeaux    optimize = _optimize,
1201*9e965d6fSRomain Jobredeaux
1202*9e965d6fSRomain Jobredeaux    # Exposed for testing
1203*9e965d6fSRomain Jobredeaux    mergee_manifests_flag = _mergee_manifests_flag,
1204*9e965d6fSRomain Jobredeaux    get_unique_res_dirs = _get_unique_res_dirs,
1205*9e965d6fSRomain Jobredeaux    sanitize_assets_dir = _sanitize_assets_dir,
1206*9e965d6fSRomain Jobredeaux    extract_filters = _extract_filters,
1207*9e965d6fSRomain Jobredeaux)
1208