• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"""Bazel Android Resources."""
16
17load(":attrs.bzl", _attrs = "attrs")
18load(":busybox.bzl", _busybox = "busybox")
19load(":common.bzl", _common = "common")
20load(":java.bzl", _java = "java")
21load(":path.bzl", _path = "path")
22load(
23    ":providers.bzl",
24    "ResourcesNodeInfo",
25    "StarlarkAndroidResourcesInfo",
26)
27load(
28    ":utils.bzl",
29    "utils",
30    _compilation_mode = "compilation_mode",
31    _log = "log",
32)
33
34_RESOURCE_FOLDER_TYPES = [
35    "anim",
36    "animator",
37    "color",
38    "drawable",
39    "font",
40    "interpolator",
41    "layout",
42    "menu",
43    "mipmap",
44    "navigation",
45    "values",
46    "xml",
47    "raw",
48    "transition",
49]
50
51_RESOURCE_QUALIFIER_SEP = "-"
52
53_MANIFEST_MISSING_ERROR = (
54    "In target %s, manifest attribute is required when resource_files or " +
55    "assets are defined."
56)
57
58_ASSET_DEFINITION_ERROR = (
59    "In target %s, the assets and assets_dir attributes should be either " +
60    "both empty or non-empty."
61)
62
63_INCORRECT_RESOURCE_LAYOUT_ERROR = (
64    "'%s' is not in the expected resource directory structure of " +
65    "<resource directory>/{%s}/<file>" % (",").join(_RESOURCE_FOLDER_TYPES)
66)
67
68# Keys for manifest_values
69_VERSION_NAME = "versionName"
70_VERSION_CODE = "versionCode"
71
72# Resources context attributes.
73_ASSETS_PROVIDER = "assets_provider"
74_DATA_BINDING_LAYOUT_INFO = "data_binding_layout_info"
75_DEFINES_RESOURCES = "defines_resources"
76_DIRECT_ANDROID_RESOURCES = "direct_android_resources"
77_MERGED_MANIFEST = "merged_manifest"
78_PROVIDERS = "providers"
79_R_JAVA = "r_java"
80_RESOURCES_APK = "resources_apk"
81_VALIDATION_RESULTS = "validation_results"
82_VALIDATION_OUTPUTS = "validation_outputs"
83_RESOURCES_PROVIDER = "resources_provider"
84_STARLARK_PROCESSED_MANIFEST = "starlark_processed_manifest"
85_STARLARK_R_TXT = "starlark_r_txt"
86_STARLARK_PROCESSED_RESOURCES = "starlark_processed_resources"
87
88_ResourcesProcessContextInfo = provider(
89    "Resources context object",
90    fields = {
91        _DEFINES_RESOURCES: "If local resources were defined.",
92        _DIRECT_ANDROID_RESOURCES: "Direct android resources.",
93        _MERGED_MANIFEST: "Merged manifest.",
94        _PROVIDERS: "The list of all providers to propagate.",
95        _R_JAVA: "JavaInfo for R.jar.",
96        _DATA_BINDING_LAYOUT_INFO: "Databinding layout info file.",
97        _RESOURCES_APK: "ResourcesApk.",
98        _VALIDATION_RESULTS: "List of validation results.",
99        _VALIDATION_OUTPUTS: "List of outputs given to OutputGroupInfo _validation group",
100
101        # TODO(djwhang): The android_library aar generation requires direct
102        # access to providers. Remove once aar is its own rule.
103        _ASSETS_PROVIDER: "AndroidAssetsInfo provider.",
104        _RESOURCES_PROVIDER: "AndroidResourcesInfo provider.",
105        _STARLARK_PROCESSED_MANIFEST: "The processed manifest from the starlark resource processing pipeline.",
106        _STARLARK_R_TXT: "The R.txt from the starlark resource processing pipeline.",
107        _STARLARK_PROCESSED_RESOURCES: "The processed resources from the starlark processing pipeline.",
108    },
109)
110
111# Packaged resources context attributes.
112_PACKAGED_FINAL_MANIFEST = "processed_manifest"
113_PACKAGED_RESOURCE_APK = "resources_apk"
114_PACKAGED_CLASS_JAR = "class_jar"
115_PACKAGED_VALIDATION_RESULT = "validation_result"
116
117_ResourcesPackageContextInfo = provider(
118    "Packaged resources context object",
119    fields = {
120        _PACKAGED_FINAL_MANIFEST: "Final processed manifest.",
121        _PACKAGED_RESOURCE_APK: "ResourceApk.",
122        _PACKAGED_CLASS_JAR: "R class jar.",
123        _PACKAGED_VALIDATION_RESULT: "Validation result.",
124        _R_JAVA: "JavaInfo for R.jar",
125        _DATA_BINDING_LAYOUT_INFO: "Databinding layout info file.",
126        _PROVIDERS: "The list of all providers to propagate.",
127    },
128)
129
130def _generate_dummy_manifest(
131        ctx,
132        out_manifest = None,
133        java_package = None,
134        min_sdk_version = None):
135    content = """<?xml version="1.0" encoding="utf-8"?>
136<manifest xmlns:android="http://schemas.android.com/apk/res/android"
137    package="%s">""" % (java_package or "com.default")
138
139    if min_sdk_version:
140        content = content + """
141    <uses-sdk android:minSdkVersion="%s" />""" % min_sdk_version
142
143    content = content + """
144    <application>
145    </application>
146</manifest>"""
147
148    ctx.actions.write(
149        output = out_manifest,
150        content = content,
151    )
152
153def _add_g3itr(
154        ctx,
155        manifest = None,
156        out_manifest = None,
157        xsltproc = None,
158        instrument_xslt = None):
159    """Adds Google3InstrumentationTestRunner instrumentation element to the manifest.
160
161    Element is only added if the manifest contains an instrumentation element with
162    name "android.test.InstrumentationTestRunner". The added element's name attr is
163    "com.google.android.apps.common.testing.testrunner.Google3InstrumentationTestRunner".
164
165    Args:
166      ctx: The context.
167      manifest: File. The AndroidManifest.xml file.
168      out_manifest: File. The transformed AndroidManifest.xml.
169      xsltproc: FilesToRunProvider. The xsltproc executable or
170        FilesToRunProvider.
171      instrument_xslt: File. The add_g3itr.xslt file describing the xslt
172        transformation to apply.
173    """
174    args = ctx.actions.args()
175    args.add("--nonet")
176    args.add("--novalid")
177    args.add("-o", out_manifest)
178    args.add(instrument_xslt)
179    args.add(manifest)
180
181    ctx.actions.run(
182        executable = xsltproc,
183        arguments = [args],
184        inputs = [manifest, instrument_xslt],
185        outputs = [out_manifest],
186        mnemonic = "AddG3ITRStarlark",
187        progress_message = "Adding G3ITR to test manifest for %s" % ctx.label,
188    )
189
190def _get_legacy_mergee_manifests(resources_infos):
191    all_dependencies = depset(
192        transitive = [
193            ri.direct_android_resources
194            for ri in resources_infos
195        ] + [
196            ri.transitive_android_resources
197            for ri in resources_infos
198        ],
199    )
200
201    mergee_manifests = []
202    for dep in all_dependencies.to_list():
203        if dep.to_provider.manifest.exports_manifest:
204            mergee_manifests.append(dep.to_provider.manifest.manifest)
205
206    return depset(mergee_manifests)
207
208def _legacy_mergee_manifest(manifest):
209    sort_key = manifest.short_path + "#"
210    return sort_key + "--mergee=" + manifest.path
211
212def _legacy_merge_manifests(
213        ctx,
214        out_merged_manifest = None,
215        manifest = None,
216        mergee_manifests = None,
217        legacy_merger = None):
218    """Merges manifests with the legacy manifest merger."
219
220    This should not be called with empty mergee_manifests.
221
222    Args:
223      ctx: The context.
224      out_merged_manifest: File. The merged AndroidManifest.xml.
225      manifest: File. The AndroidManifest.xml.
226      mergee_manifests: A sequence of Files. All transitive manifests to be merged.
227      legacy_merger: A FilesToRunProvider. The legacy manifest merger executable.
228    """
229    args = ctx.actions.args()
230    args.use_param_file("%s", use_always = True)
231    args.set_param_file_format("multiline")
232    args.add("--merger=%s" % manifest.path)
233    args.add("--exclude_permission=all")
234    args.add("--output=%s" % out_merged_manifest.path)
235
236    manifest_params = ctx.actions.declare_file(ctx.label.name + "/legacy_merger.params")
237    manifest_args = ctx.actions.args()
238    manifest_args.use_param_file("%s", use_always = True)
239    manifest_args.set_param_file_format("multiline")
240    manifest_args.add_joined(mergee_manifests, map_each = _legacy_mergee_manifest, join_with = "\n")
241    ctx.actions.run_shell(
242        command = """
243# Sorts the mergee manifests by path and combines with other busybox args.
244set -e
245SORTED=`sort $1 | sed 's/^.*#//'`
246cat $2 > $3
247echo "$SORTED" >> $3
248""",
249        arguments = [manifest_args, args, manifest_params.path],
250        outputs = [manifest_params],
251    )
252    args = ctx.actions.args()
253    args.add(manifest_params, format = "--flagfile=%s")
254
255    ctx.actions.run(
256        executable = legacy_merger,
257        arguments = [args],
258        inputs = depset([manifest, manifest_params], transitive = [mergee_manifests]),
259        outputs = [out_merged_manifest],
260        mnemonic = "StarlarkLegacyAndroidManifestMerger",
261        progress_message = "Merging Android Manifests",
262    )
263
264def _make_databinding_outputs(
265        ctx,
266        resource_files):
267    """Helper method to create arguments for the process_databinding busybox tool.
268
269    Declares databinding-processed resource files that are generated by the
270    PROCESS_DATABINDING busybox tool, which must be declared underneath an output
271    resources directory and namespaced by their paths. The busybox takes the
272    output directory exec path and generates the underlying resource files.
273
274    Args:
275      ctx: The context.
276      resource_files: List of Files. The android resource files to be processed by
277        _process_databinding.
278
279    Returns:
280      A tuple containing the list of declared databinding processed resource files and the
281        output resource directory path expected by the busybox. The path is a full path.
282    """
283
284    # TODO(b/160907203): Clean up databinding_rel_path. We capitalize "Databinding" here to avoid
285    # conflicting with native artifact file names. This is changed back to "databinding" during
286    # process_starlark so that compiled resources exactly match those of the native resource
287    # processing pipeline. Even a single character mismatch in the file names causes selected
288    # resources to differ in the final APK.
289    databinding_rel_path = _path.join(["Databinding-processed-resources", ctx.label.name])
290    databinding_processed_resources = [
291        ctx.actions.declare_file(_path.join([databinding_rel_path, f.path]))
292        for f in resource_files
293    ]
294    databinding_resources_dirname = _path.join([
295        ctx.bin_dir.path,
296        ctx.label.package,
297        databinding_rel_path,
298    ])
299    return databinding_processed_resources, databinding_resources_dirname
300
301def _fix_databinding_compiled_resources(
302        ctx,
303        out_compiled_resources = None,
304        compiled_resources = None,
305        zip_tool = None):
306    """Fix compiled resources to match those produced by the native pipeline.
307
308    Changes "Databinding" to "databinding" in each compiled resource .flat file name and header.
309
310    Args:
311      ctx: The context.
312      out_compiled_resources: File. The modified compiled_resources output.
313      compiled_resources: File. The compiled_resources zip.
314      zip_tool: FilesToRunProvider. The zip tool executable or FilesToRunProvider
315    """
316    ctx.actions.run_shell(
317        outputs = [out_compiled_resources],
318        inputs = [compiled_resources],
319        tools = [zip_tool],
320        arguments = [compiled_resources.path, out_compiled_resources.path, zip_tool.executable.path],
321        command = """#!/bin/bash
322set -e
323
324IN_DIR=$(mktemp -d)
325OUT_DIR=$(mktemp -d)
326CUR_PWD=$(pwd)
327
328if zipinfo -t "$1"; then
329    ORDERED_LIST=`(unzip -l "$1" | sed -e '1,3d' | head -n -2 | tr -s " " | cut -d " " -f5)`
330
331    unzip -q "$1" -d "$IN_DIR"
332
333    # Iterate through the ordered list, change "Databinding" to "databinding" in the file header
334    # and file name and zip the files with the right comment
335    for FILE in $ORDERED_LIST; do
336        cd "$IN_DIR"
337        if [ -f "$FILE" ]; then
338            sed -i 's/Databinding\\-processed\\-resources/databinding\\-processed\\-resources/g' "$FILE"
339            NEW_NAME=`echo "$FILE" | sed 's/Databinding\\-processed\\-resources/databinding\\-processed\\-resources/g' | sed 's#'"$IN_DIR"'/##g'`
340            mkdir -p `dirname "$OUT_DIR/$NEW_NAME"` && touch "$OUT_DIR/$NEW_NAME"
341            cp -p "$FILE" "$OUT_DIR/$NEW_NAME"
342
343            PATH_SEGMENTS=(`echo ${FILE} | tr '/' ' '`)
344            BASE_PATH_SEGMENT="${PATH_SEGMENTS[0]}"
345                COMMENT=
346            if [ "${BASE_PATH_SEGMENT}" == "generated" ]; then
347                COMMENT="generated"
348            elif [ "${BASE_PATH_SEGMENT}" == "default" ]; then
349                COMMENT="default"
350            fi
351
352            cd "$OUT_DIR"
353            "$CUR_PWD/$3" -jt -X -0 -q -r -c "$CUR_PWD/$2" $NEW_NAME <<EOM
354${COMMENT}
355EOM
356        fi
357    done
358
359    cd "$CUR_PWD"
360    touch -r "$1" "$2"
361else
362    cp -p "$1" "$2"
363fi
364        """,
365    )
366
367def _is_resource_shrinking_enabled(
368        shrink_resources,
369        use_android_resource_shrinking):
370    if shrink_resources == _attrs.tristate.auto:
371        return use_android_resource_shrinking
372    return shrink_resources == _attrs.tristate.yes
373
374def _should_shrink_resource_cycles(
375        use_android_resource_cycle_shrinking,
376        resource_shrinking_enabled):
377    if use_android_resource_cycle_shrinking and not resource_shrinking_enabled:
378        fail("resource cycle shrinking can only be enabled when resource shrinking is enabled")
379    return use_android_resource_cycle_shrinking
380
381def _filter_multi_cpu_configuration_targets(
382        targets):
383    """Filter out duplicate split-configured targets.
384
385    This method simulates logic in the native rule where if a label_list attribute has
386    split-configuration but is requested in target mode, only targets from the first architecture
387    are returned. Without this filtering there are duplicate targets if multiple CPU configurations
388    are specified on the command line. This is the case with deps in the packaging step of
389    android_binary.
390
391    Args:
392      targets: A list of Target objects.
393
394    Returns:
395      A list of Target objects with duplicates removed.
396    """
397    seen_labels = {}
398    filtered_targets = []
399    for t in targets:
400        if t.label in seen_labels:
401            continue
402        seen_labels[t.label] = True
403        filtered_targets.append(t)
404    return filtered_targets
405
406def _package(
407        ctx,
408        assets = [],
409        assets_dir = None,
410        deps = [],
411        manifest = None,
412        manifest_values = None,
413        instruments = None,
414        resource_configs = None,
415        densities = [],
416        resource_files = [],
417        nocompress_extensions = [],
418        java_package = None,
419        package_id = None,
420        compilation_mode = _compilation_mode.FASTBUILD,
421        shrink_resources = None,
422        use_android_resource_shrinking = None,
423        use_android_resource_cycle_shrinking = None,
424        use_legacy_manifest_merger = False,
425        should_throw_on_conflict = True,
426        enable_data_binding = False,
427        enable_manifest_merging = True,
428        aapt = None,
429        android_jar = None,
430        legacy_merger = None,
431        xsltproc = None,
432        instrument_xslt = None,
433        busybox = None,
434        host_javabase = None):
435    """Package resources for top-level rules.
436
437    Args:
438      ctx: The context.
439      assets: sequence of Files. A list of assets to be packaged. All files be
440        under the assets_dir directory in the corresponding package.
441      assets_dir: String. A string giving the path to the files in assets. The
442        pair assets and assets_dir describe packaged assets and either both
443        parameters should be provided or none of them.
444      deps: sequence of Targets. The list of other libraries targets to link
445        against.
446      manifest: File. The input top-level AndroidManifest.xml.
447      manifest_values: String dictionary. Manifest values to substitute.
448      instruments: Optional target. The value of the "instruments" attr if set.
449      resource_configs: sequence of Strings. A list of resource_configuration_filters
450        to apply.
451      densities: sequence of Strings. A list of densities to filter for when building
452        the apk.
453      resource_files: sequence of Files. A list of Android resource files
454        to be processed.
455      nocompress_extensions: sequence of Strings. File extension to leave uncompressed
456        in the apk.
457      java_package: String. Java package for which java sources will be
458        generated. By default the package is inferred from the directory where
459        the BUILD file containing the rule is.
460      package_id: An optional integer in [2,255]. This is the prefix byte for
461        all generated resource IDs, defaults to 0x7F (127). 1 is reserved by the
462        framework, and some builds are known to crash when given IDs > 127.
463        Shared libraries are also assigned monotonically increasing IDs in
464        [2,126], so care should be taken that there is room at the lower end.
465      compilation_mode: String. A string that represents compilation mode. The
466        list of expected values are as follows: dbg, fastbuild, opt.
467      shrink_resources: Tristate. Whether resource shrinking is enabled by the rule.
468      use_android_resource_shrinking: Bool. Flag that controls the default value for
469        shrink_resources if the tristate value is auto (-1).
470      use_android_resource_cycle_shrinking: Bool. Flag that enables more shrinking of
471        code and resources by instructing AAPT2 to emit conditional Proguard keep rules.
472      use_legacy_manifest_merger: A boolean. Whether to use the legacy manifest merger
473      instead of the android manifest merger.
474      should_throw_on_conflict: A boolean. Determines whether an error should be thrown
475        when a resource conflict occurs.
476      enable_data_binding: boolean. If true, processesing the data binding
477        expressions in layout resources included through the resource_files
478        parameter is enabled. Without this setting, data binding expressions
479        produce build failures.
480      enable_manifest_merging: boolean. If true, manifest merging will be performed.
481      aapt: FilesToRunProvider. The aapt executable or FilesToRunProvider.
482      android_jar: File. The Android jar.
483      legacy_merger: FilesToRunProvider. The legacy manifest merger executable.
484      xsltproc: FilesToRunProvider. The xsltproc executable or
485        FilesToRunProvider.
486      instrument_xslt: File. The add_g3itr.xslt file describing the xslt
487        transformation to apply.
488      busybox: FilesToRunProvider. The ResourceBusyBox executable or
489        FilesToRunprovider
490      host_javabase: A Target. The host javabase.
491
492    Returns:
493      A ResourcesPackageContextInfo containing packaged resource artifacts and
494        providers.
495    """
496    _validate_resources(resource_files)
497
498    packaged_resources_ctx = {
499        _PROVIDERS: [],
500    }
501
502    g3itr_manifest = manifest
503
504    if xsltproc or instrument_xslt:
505        g3itr_manifest = ctx.actions.declare_file(
506            "_migrated/" + ctx.label.name + "add_g3itr/AndroidManifest.xml",
507        )
508        _add_g3itr(
509            ctx,
510            out_manifest = g3itr_manifest,
511            manifest = manifest,
512            xsltproc = xsltproc,
513            instrument_xslt = instrument_xslt,
514        )
515
516    direct_resources_nodes = []
517    transitive_resources_nodes = []
518    transitive_assets = []
519    transitive_assets_symbols = []
520    transitive_compiled_assets = []
521    transitive_resource_files = []
522    transitive_compiled_resources = []
523    transitive_manifests = []
524    transitive_r_txts = []
525    packages_to_r_txts_depset = dict()
526    for dep in utils.collect_providers(StarlarkAndroidResourcesInfo, deps):
527        direct_resources_nodes.append(dep.direct_resources_nodes)
528        transitive_resources_nodes.append(dep.transitive_resources_nodes)
529        transitive_assets.append(dep.transitive_assets)
530        transitive_assets_symbols.append(dep.transitive_assets_symbols)
531        transitive_compiled_assets.append(dep.transitive_compiled_assets)
532        transitive_resource_files.append(dep.transitive_resource_files)
533        transitive_compiled_resources.append(dep.transitive_compiled_resources)
534        transitive_manifests.append(dep.transitive_manifests)
535        transitive_r_txts.append(dep.transitive_r_txts)
536        for pkg, r_txts in dep.packages_to_r_txts.items():
537            packages_to_r_txts_depset.setdefault(pkg, []).append(r_txts)
538
539    mergee_manifests = depset([
540        node_info.manifest
541        for node_info in depset(transitive = transitive_resources_nodes + direct_resources_nodes).to_list()
542        if node_info.exports_manifest
543    ])
544
545    # TODO(b/156763506): Add analysis tests to verify logic around when manifest merging is configured.
546    # TODO(b/154153771): Run the android merger if mergee_manifests or manifest values are present.
547    merged_manifest = g3itr_manifest
548    if enable_manifest_merging and (manifest_values or mergee_manifests):
549        if use_legacy_manifest_merger:
550            # Legacy manifest merger only runs if mergee manifests are present
551            if mergee_manifests:
552                merged_manifest = ctx.actions.declare_file(
553                    "_migrated/_merged/" + ctx.label.name + "/AndroidManifest.xml",
554                )
555                _legacy_merge_manifests(
556                    ctx,
557                    out_merged_manifest = merged_manifest,
558                    manifest = g3itr_manifest,
559                    mergee_manifests = mergee_manifests,
560                    legacy_merger = legacy_merger,
561                )
562        else:
563            merged_manifest = ctx.actions.declare_file(
564                "_migrated/_merged/" + ctx.label.name + "/AndroidManifest.xml",
565            )
566            _busybox.merge_manifests(
567                ctx,
568                out_file = merged_manifest,
569                out_log_file = ctx.actions.declare_file(
570                    "_migrated/_merged/" + ctx.label.name + "/manifest_merger_log.txt",
571                ),
572                manifest = g3itr_manifest,
573                mergee_manifests = mergee_manifests,
574                manifest_values = manifest_values,
575                merge_type = "APPLICATION",
576                java_package = java_package,
577                busybox = busybox,
578                host_javabase = host_javabase,
579            )
580
581    processed_resources = resource_files
582    data_binding_layout_info = None
583    if enable_data_binding:
584        data_binding_layout_info = ctx.actions.declare_file("_migrated/" + ctx.label.name + "/layout-info.zip")
585        processed_resources, resources_dirname = _make_databinding_outputs(
586            ctx,
587            resource_files,
588        )
589        _busybox.process_databinding(
590            ctx,
591            out_databinding_info = data_binding_layout_info,
592            out_databinding_processed_resources = processed_resources,
593            databinding_resources_dirname = resources_dirname,
594            resource_files = resource_files,
595            java_package = java_package,
596            busybox = busybox,
597            host_javabase = host_javabase,
598        )
599
600    resource_apk = ctx.actions.declare_file(ctx.label.name + "_migrated/.ap_")
601    r_java = ctx.actions.declare_file("_migrated/" + ctx.label.name + ".srcjar")
602    r_txt = ctx.actions.declare_file(ctx.label.name + "_migrated/_symbols/R.txt")
603    processed_manifest = ctx.actions.declare_file(ctx.label.name + "_migrated/_processed_manifest/AndroidManifest.xml")
604    proguard_cfg = ctx.actions.declare_file(
605        "_migrated/proguard/%s/_%s_proguard.cfg" % (ctx.label.name, ctx.label.name),
606    )
607    main_dex_proguard_cfg = ctx.actions.declare_file(
608        "_migrated/proguard/%s/main_dex_%s_proguard.cfg" %
609        (ctx.label.name, ctx.label.name),
610    )
611    resource_files_zip = ctx.actions.declare_file(
612        "_migrated/" + ctx.label.name + "_files/resource_files.zip",
613    )
614    _busybox.package(
615        ctx,
616        out_file = resource_apk,
617        out_r_src_jar = r_java,
618        out_r_txt = r_txt,
619        out_symbols = ctx.actions.declare_file("_migrated/" + ctx.label.name + "_symbols/merged.bin"),
620        out_manifest = processed_manifest,
621        out_proguard_cfg = proguard_cfg,
622        out_main_dex_proguard_cfg = main_dex_proguard_cfg,
623        out_resource_files_zip = resource_files_zip,
624        application_id = manifest_values.get("applicationId", None),
625        package_id = package_id,
626        manifest = merged_manifest,
627        assets = assets,
628        assets_dir = assets_dir,
629        resource_files = processed_resources,
630        direct_resources_nodes =
631            depset(transitive = direct_resources_nodes, order = "preorder"),
632        transitive_resources_nodes =
633            depset(transitive = transitive_resources_nodes, order = "preorder"),
634        transitive_assets = transitive_assets,
635        transitive_compiled_assets = transitive_compiled_assets,
636        transitive_resource_files = transitive_resource_files,
637        transitive_compiled_resources = transitive_compiled_resources,
638        transitive_manifests = transitive_manifests,
639        transitive_r_txts = transitive_r_txts,
640        resource_configs = resource_configs,
641        densities = densities,
642        nocompress_extensions = nocompress_extensions,
643        java_package = java_package,
644        version_name = manifest_values[_VERSION_NAME] if _VERSION_NAME in manifest_values else None,
645        version_code = manifest_values[_VERSION_CODE] if _VERSION_CODE in manifest_values else None,
646        android_jar = android_jar,
647        aapt = aapt,
648        busybox = busybox,
649        host_javabase = host_javabase,
650        debug = compilation_mode != _compilation_mode.OPT,
651        should_throw_on_conflict = should_throw_on_conflict,
652    )
653    packaged_resources_ctx[_PACKAGED_FINAL_MANIFEST] = processed_manifest
654    packaged_resources_ctx[_PACKAGED_RESOURCE_APK] = resource_apk
655    packaged_resources_ctx[_PACKAGED_VALIDATION_RESULT] = resource_files_zip
656
657    resource_shrinking_enabled = _is_resource_shrinking_enabled(
658        shrink_resources,
659        use_android_resource_shrinking,
660    )
661    shrink_resource_cycles = _should_shrink_resource_cycles(
662        use_android_resource_cycle_shrinking,
663        resource_shrinking_enabled,
664    )
665
666    # Fix class jar name because some tests depend on {label_name}_resources.jar being the suffix of
667    # the path, with _RESOURCES_DO_NOT_USE removed from the label name.
668    _RESOURCES_SUFFIX = "_RESOURCES_DO_NOT_USE"
669    class_jar_name = ctx.label.name + "_migrated/_resources.jar"
670    if ctx.label.name.endswith(_RESOURCES_SUFFIX):
671        label_name = ctx.label.name[:-len(_RESOURCES_SUFFIX)]
672        class_jar_name = ctx.label.name + "_migrated/" + label_name + "_resources.jar"
673
674    class_jar = ctx.actions.declare_file(class_jar_name)
675    _busybox.generate_binary_r(
676        ctx,
677        out_class_jar = class_jar,
678        r_txt = r_txt,
679        manifest = processed_manifest,
680        package_for_r = java_package,
681        final_fields = not shrink_resource_cycles and not instruments,
682        resources_nodes = depset(transitive = direct_resources_nodes + transitive_resources_nodes),
683        transitive_r_txts = transitive_r_txts,
684        transitive_manifests = transitive_manifests,
685        busybox = busybox,
686        host_javabase = host_javabase,
687    )
688    packaged_resources_ctx[_PACKAGED_CLASS_JAR] = class_jar
689
690    java_info = JavaInfo(
691        output_jar = class_jar,
692        compile_jar = class_jar,
693        source_jar = r_java,
694    )
695
696    packaged_resources_ctx[_R_JAVA] = java_info
697    packaged_resources_ctx[_DATA_BINDING_LAYOUT_INFO] = data_binding_layout_info
698
699    packages_to_r_txts_depset.setdefault(java_package, []).append(depset([r_txt]))
700
701    packages_to_r_txts = dict()
702    for pkg, depsets in packages_to_r_txts_depset.items():
703        packages_to_r_txts[pkg] = depset(transitive = depsets)
704
705    # Adding empty depsets to unused fields of StarlarkAndroidResourcesInfo.
706    # Some root targets may depends on other root targets and try to access those fields.
707    packaged_resources_ctx[_PROVIDERS].append(StarlarkAndroidResourcesInfo(
708        direct_resources_nodes = depset(),
709        transitive_resources_nodes = depset(),
710        transitive_assets = depset(),
711        transitive_assets_symbols = depset(),
712        transitive_compiled_assets = depset(),
713        transitive_resource_files = depset(),
714        direct_compiled_resources = depset(),
715        transitive_compiled_resources = depset(),
716        transitive_manifests = depset(),
717        transitive_r_txts = depset(),
718        packages_to_r_txts = packages_to_r_txts,
719    ))
720
721    packaged_resources_ctx[_PROVIDERS].append(AndroidApplicationResourceInfo(
722        resource_apk = resource_apk,
723        resource_java_src_jar = r_java,
724        resource_java_class_jar = class_jar,
725        manifest = processed_manifest,
726        resource_proguard_config = proguard_cfg,
727        main_dex_proguard_config = main_dex_proguard_cfg,
728        r_txt = r_txt,
729        resources_zip = resource_files_zip,
730        databinding_info = data_binding_layout_info,
731    ))
732    return _ResourcesPackageContextInfo(**packaged_resources_ctx)
733
734def _liteparse(ctx, out_r_pb, resource_files, android_kit):
735    """Creates an R.pb which contains the resource ids gotten from a light parse.
736
737    Args:
738      ctx: The context.
739      out_r_pb: File. The R.pb output file.
740      resource_files: List of Files. The list of resource files.
741      android_kit: FilesToRunProvider. The Android Kit executable or
742        FilesToRunProvider.
743    """
744    args = ctx.actions.args()
745    args.use_param_file(param_file_arg = "--flagfile=%s", use_always = True)
746    args.set_param_file_format("multiline")
747    args.add_joined("--res_files", resource_files, join_with = ",")
748    args.add("--out", out_r_pb)
749
750    ctx.actions.run(
751        executable = android_kit,
752        arguments = ["liteparse", args],
753        inputs = resource_files,
754        outputs = [out_r_pb],
755        mnemonic = "ResLiteParse",
756        progress_message = "Lite parse Android Resources %s" % ctx.label,
757    )
758
759def _fastr(ctx, r_pbs, package, manifest, android_kit):
760    """Create R.srcjar from the given R.pb files in the transitive closure.
761
762    Args:
763      ctx: The context.
764      r_pbs: Transitive  set of resource pbs.
765      package: The package name of the compile-time R.java.
766      manifest: File. The AndroidManifest.xml file.
767      android_kit: FilesToRunProvider. The Android Kit executable or
768        FilesToRunProvider.
769
770    Returns:
771      The output R source jar artifact.
772    """
773    inputs = r_pbs
774    r_srcjar = ctx.actions.declare_file(ctx.label.name + "/resources/R-fastr.srcjar")
775    args = ctx.actions.args()
776    args.use_param_file(param_file_arg = "--flagfile=%s", use_always = True)
777    args.set_param_file_format("multiline")
778    args.add("-rJavaOutput", r_srcjar)
779    if package:
780        args.add("-packageForR", package)
781    else:
782        args.add("-manifest", manifest)
783        inputs = depset([manifest], transitive = [inputs])
784    args.add_joined("-resourcePbs", r_pbs, join_with = ",")
785
786    ctx.actions.run(
787        executable = android_kit,
788        arguments = ["rstub", args],
789        inputs = inputs,
790        outputs = [r_srcjar],
791        mnemonic = "CompileTimeR",
792        progress_message = "Generating compile-time R %s" % r_srcjar.short_path,
793    )
794    return r_srcjar
795
796def _compile(
797        ctx,
798        out_compiled_resources = None,
799        out_r_pb = None,
800        resource_files = [],
801        aapt = None,
802        android_kit = None,
803        busybox = None,
804        host_javabase = None):
805    """Compile Android Resources processing pipeline.
806
807    Args:
808      ctx: The context.
809      out_compiled_resources: File. The compiled resources output file.
810      out_r_pb: File. The R.pb output file.
811      resource_files: A list of Files. The resource files can be directories.
812      aapt: FilesToRunProvider. The aapt executable or FilesToRunProvider.
813      android_kit: FilesToRunProvider. The android_kit executable or
814        FilesToRunProvider.
815      busybox: FilesToRunProvider. The ResourceBusyBox executable or
816        FilesToRunprovider
817      host_javabase: A Target. The host javabase.
818    """
819    _liteparse(ctx, out_r_pb, resource_files, android_kit)
820    _busybox.compile(
821        ctx,
822        out_file = out_compiled_resources,
823        resource_files = resource_files,
824        aapt = aapt,
825        busybox = busybox,
826        host_javabase = host_javabase,
827    )
828
829def _make_aar(
830        ctx,
831        assets = [],
832        assets_dir = None,
833        resource_files = [],
834        class_jar = None,
835        r_txt = None,
836        manifest = None,
837        proguard_specs = [],
838        busybox = None,
839        host_javabase = None):
840    """Generate an android archive file.
841
842    Args:
843      ctx: The context.
844      assets: sequence of Files. A list of Android assets files to be processed.
845      assets_dir: String. The name of the assets directory.
846      resource_files: A list of Files. The resource files.
847      class_jar: File. The class jar file.
848      r_txt: File. The resource IDs outputted by linking resources in text.
849      manifest: File. The primary AndroidManifest.xml.
850      proguard_specs: List of File. The proguard spec files.
851      busybox: FilesToRunProvider. The ResourceBusyBox executable or
852        FilesToRunprovider
853      host_javabase: A Target. The host javabase.
854
855    Returns:
856      The output aar artifact.
857    """
858    aar = ctx.actions.declare_file(ctx.label.name + ".aar")
859    _busybox.make_aar(
860        ctx,
861        out_aar = aar,
862        assets = assets,
863        assets_dir = assets_dir,
864        resource_files = resource_files,
865        class_jar = class_jar,
866        r_txt = r_txt,
867        manifest = manifest,
868        proguard_specs = proguard_specs,
869        busybox = busybox,
870        host_javabase = host_javabase,
871    )
872    return aar
873
874def _validate(ctx, manifest, defined_assets, defined_assets_dir):
875    if ((defined_assets and not defined_assets_dir) or
876        (not defined_assets and defined_assets_dir)):
877        _log.error(_ASSET_DEFINITION_ERROR % ctx.label)
878
879    if not manifest:
880        _log.error(_MANIFEST_MISSING_ERROR % ctx.label)
881
882def _make_direct_assets_transitive(assets_info):
883    return AndroidAssetsInfo(
884        assets_info.label,
885        assets_info.validation_result,
886        depset([]),  # direct_parsed_assets
887        depset(
888            transitive = [
889                assets_info.direct_parsed_assets,
890                assets_info.transitive_parsed_assets,
891            ],
892            order = "preorder",
893        ),
894        assets_info.assets,
895        assets_info.symbols,
896        assets_info.compiled_symbols,
897    )
898
899def _make_direct_resources_transitive(resources_info):
900    return AndroidResourcesInfo(
901        resources_info.label,
902        resources_info.manifest,
903        resources_info.compiletime_r_txt,
904        # NB: the ordering of "direct" and "transitive" is inconsistent with that used for
905        # AndroidAssetsInfo.
906        depset(
907            transitive = [
908                # Ordering is inconsistent here too:
909                # https://github.com/bazelbuild/bazel/blob/82c7f48b4628ebbec18123afdbed701bbaa605e2/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java#L158
910                resources_info.transitive_android_resources,
911                resources_info.direct_android_resources,
912            ],
913            order = "preorder",
914        ),
915        depset([]),  # direct_android_resources
916        resources_info.transitive_resources,
917        resources_info.transitive_manifests,
918        resources_info.transitive_aapt2_r_txt,
919        resources_info.transitive_symbols_bin,
920        resources_info.transitive_compiled_symbols,
921        resources_info.transitive_static_lib,
922        resources_info.transitive_r_txt,
923        validation_artifacts = resources_info.validation_artifacts,
924    )
925
926def _export_assets(assets_info, exports):
927    all_providers = [assets_info] + utils.collect_providers(AndroidAssetsInfo, exports)
928    return AndroidAssetsInfo(
929        assets_info.label,
930        assets_info.validation_result,
931        direct_parsed_assets = utils.join_depsets(all_providers, "direct_parsed_assets", order = "preorder"),
932        transitive_parsed_assets = utils.join_depsets(all_providers, "transitive_parsed_assets", order = "preorder"),
933        transitive_assets = utils.join_depsets(all_providers, "assets", order = "preorder"),
934        transitive_symbols = utils.join_depsets(all_providers, "symbols", order = "preorder"),
935        transitive_compiled_symbols = utils.join_depsets(all_providers, "compiled_symbols", order = "preorder"),
936    )
937
938def _export_resources(resources_info, exports):
939    all_providers = [resources_info] + utils.collect_providers(AndroidResourcesInfo, exports)
940    return AndroidResourcesInfo(
941        resources_info.label,
942        resources_info.manifest,
943        resources_info.compiletime_r_txt,
944        **{attr: utils.join_depsets(all_providers, attr, order = "preorder") for attr in [
945            "transitive_android_resources",
946            "direct_android_resources",
947            "transitive_resources",
948            "transitive_manifests",
949            "transitive_aapt2_r_txt",
950            "transitive_symbols_bin",
951            "transitive_compiled_symbols",
952            "transitive_static_lib",
953            "transitive_r_txt",
954            "validation_artifacts",
955        ]}
956    )
957
958def _validate_resources(resource_files = None):
959    for resource_file in resource_files:
960        path_segments = resource_file.path.split("/")
961        if len(path_segments) < 3:
962            fail(_INCORRECT_RESOURCE_LAYOUT_ERROR % resource_file)
963
964        # Check the resource directory type if the resource file is not a Fileset.
965        if not resource_file.is_directory:
966            # The resource directory is presumed to be the second directory from the end.
967            # Resource directories can have multiple qualifiers, each one separated with a dash.
968            res_type = path_segments[-2].partition(_RESOURCE_QUALIFIER_SEP)[0]
969            if res_type not in _RESOURCE_FOLDER_TYPES:
970                fail(_INCORRECT_RESOURCE_LAYOUT_ERROR % resource_file)
971
972def _process_starlark(
973        ctx,
974        java_package = None,
975        manifest = None,
976        defined_assets = False,
977        assets = None,
978        defined_assets_dir = False,
979        assets_dir = None,
980        exports_manifest = False,
981        stamp_manifest = True,
982        deps = [],
983        exports = [],
984        resource_files = None,
985        neverlink = False,
986        enable_data_binding = False,
987        propagate_resources = True,
988        fix_resource_transitivity = False,
989        aapt = None,
990        android_jar = None,
991        android_kit = None,
992        busybox = None,
993        java_toolchain = None,
994        host_javabase = None,
995        instrument_xslt = None,
996        xsltproc = None,
997        zip_tool = None):
998    """Processes Android Resources.
999
1000    Args:
1001      ctx: The rules context.
1002      java_package: string. Java package for which java sources will be
1003        generated. By default the package is inferred from the directory where
1004        the BUILD file containing the rule is.
1005      manifest: File. The AndroidManifest.xml file.
1006      defined_assets: Bool. Signifies that the assets attribute was set, even
1007        if the value is an empty list.
1008      assets: sequence of Files. A list of Android assets files to be processed.
1009      defined_assets_dir: Bool. Signifies that the assets dir attribute was set,
1010        even if the value is an empty string.
1011      assets_dir: String. The name of the assets directory.
1012      exports_manifest: boolean. Whether to export manifest entries to the
1013        android_binary targets that depend on this target.
1014        NOTE: "uses-permissions" attributes are never exported.
1015      stamp_manifest: boolean. Whether to stamp the manifest with the java
1016        package of the target. If True, java_package needs to be passed to
1017        the function.
1018      deps: sequence of Targets. The list of other libraries targets to link
1019        against.
1020      exports: sequence of Targets. The closure of all rules reached via exports
1021        attributes are considered direct dependencies of any rule that directly
1022        depends on the target with exports. The exports are not direct deps of
1023        the rule they belong to (TODO(b/144134042): make this so).
1024      resource_files: sequence of Files. A list of Android resource files to be
1025        processed.
1026      neverlink: boolean. Only use this library for compilation and not runtime.
1027        The outputs of a rule marked as neverlink will not be used in .apk
1028        creation. Useful if the library will be provided by the runtime
1029        environment during execution.
1030      enable_data_binding: boolean. If true, processesing the data binding
1031        expressions in layout resources included through the resource_files
1032        parameter is enabled. Without this setting, data binding expressions
1033        produce build failures.
1034      propagate_resources: boolean. If false, the target will no longer propagate
1035        providers required for Android Resource processing/packaging. But will
1036        continue to propagate others (AndroidLibraryResourceClassJarProvider).
1037      fix_resource_transitivity: Whether to ensure that transitive resources are
1038        correctly marked as transitive.
1039      aapt: FilesToRunProvider. The aapt executable or FilesToRunProvider.
1040      android_jar: File. The android Jar.
1041      android_kit: FilesToRunProvider. The android_kit executable or
1042        FilesToRunProvider.
1043      busybox: FilesToRunProvider. The ResourceBusyBox executable or
1044        FilesToRunprovider
1045      java_toolchain: The java_toolchain Target.
1046      host_javabase: Target. The host javabase.
1047      instrument_xslt: File. The xslt transform to apply g3itr.
1048      xsltproc: FilesToRunProvider. The xsltproc executable or FilesToRunProvider.
1049      zip_tool: FilesToRunProvider. The zip tool executable or FilesToRunProvider.
1050
1051    Returns:
1052      A dict containing _ResourcesProcessContextInfo provider fields.
1053    """
1054    if (xsltproc and not instrument_xslt) or (not xsltproc and instrument_xslt):
1055        fail(
1056            "Error, both instrument_xslt and xsltproc need to be " +
1057            "specified or not, got:\nxlstproc = %s\ninstrument_xslt = %s" %
1058            (xsltproc, instrument_xslt),
1059        )
1060
1061    _validate_resources(resource_files)
1062
1063    defines_resources = bool(
1064        manifest or
1065        resource_files or
1066        defined_assets or
1067        defined_assets_dir or
1068        exports_manifest,
1069    )
1070
1071    # TODO(djwhang): Clean up the difference between neverlink the attribute used
1072    # by Java compilation and resources neverlink.
1073    resources_neverlink = (
1074        neverlink and (
1075            defines_resources or
1076            ctx.fragments.android.fixed_resource_neverlinking
1077        )
1078    )
1079
1080    resources_ctx = {
1081        _RESOURCES_APK: None,
1082        _PROVIDERS: [],
1083        # TODO(b/156530953): Move the validation result to the validation_outputs list when we are
1084        # done rolling out Starlark resources processing
1085        _VALIDATION_RESULTS: [],
1086        _DEFINES_RESOURCES: defines_resources,
1087        _R_JAVA: None,
1088        _DATA_BINDING_LAYOUT_INFO: None,
1089        _MERGED_MANIFEST: None,
1090        _STARLARK_PROCESSED_MANIFEST: None,
1091        _STARLARK_R_TXT: None,
1092        _STARLARK_PROCESSED_RESOURCES: [],
1093    }
1094
1095    if resource_files and not manifest:
1096        _log.error(_MANIFEST_MISSING_ERROR % ctx.label)
1097
1098    direct_resources_nodes = []
1099    transitive_resources_nodes = []
1100    transitive_assets = []
1101    transitive_assets_symbols = []
1102    transitive_compiled_assets = []
1103    direct_compiled_resources = []
1104    transitive_compiled_resources = []
1105    transitive_resources_files = []
1106    transitive_manifests = []
1107    transitive_r_txts = []
1108    packages_to_r_txts_depset = dict()
1109
1110    for dep in utils.collect_providers(StarlarkAndroidResourcesInfo, deps):
1111        direct_resources_nodes.append(dep.direct_resources_nodes)
1112        transitive_resources_nodes.append(dep.transitive_resources_nodes)
1113        transitive_assets.append(dep.transitive_assets)
1114        transitive_assets_symbols.append(dep.transitive_assets_symbols)
1115        transitive_compiled_assets.append(dep.transitive_compiled_assets)
1116        direct_compiled_resources.append(dep.direct_compiled_resources)
1117        transitive_compiled_resources.append(dep.transitive_compiled_resources)
1118        transitive_resources_files.append(dep.transitive_resource_files)
1119        transitive_manifests.append(dep.transitive_manifests)
1120        transitive_r_txts.append(dep.transitive_r_txts)
1121        for pkg, r_txts in dep.packages_to_r_txts.items():
1122            packages_to_r_txts_depset.setdefault(pkg, []).append(r_txts)
1123
1124    exports_direct_resources_nodes = []
1125    exports_transitive_resources_nodes = []
1126    exports_transitive_assets = []
1127    exports_transitive_assets_symbols = []
1128    exports_transitive_compiled_assets = []
1129    exports_direct_compiled_resources = []
1130    exports_transitive_compiled_resources = []
1131    exports_transitive_resources_files = []
1132    exports_transitive_manifests = []
1133    exports_transitive_r_txts = []
1134    for dep in utils.collect_providers(StarlarkAndroidResourcesInfo, exports):
1135        exports_direct_resources_nodes.append(dep.direct_resources_nodes)
1136        exports_transitive_resources_nodes.append(dep.transitive_resources_nodes)
1137        exports_transitive_assets.append(dep.transitive_assets)
1138        exports_transitive_assets_symbols.append(dep.transitive_assets_symbols)
1139        exports_transitive_compiled_assets.append(dep.transitive_compiled_assets)
1140        exports_direct_compiled_resources.append(dep.direct_compiled_resources)
1141        exports_transitive_compiled_resources.append(dep.transitive_compiled_resources)
1142        exports_transitive_resources_files.append(dep.transitive_resource_files)
1143        exports_transitive_manifests.append(dep.transitive_manifests)
1144        exports_transitive_r_txts.append(dep.transitive_r_txts)
1145        for pkg, r_txts in dep.packages_to_r_txts.items():
1146            packages_to_r_txts_depset.setdefault(pkg, []).append(r_txts)
1147
1148    # TODO(b/144134042): Don't merge exports; exports are not deps.
1149    direct_resources_nodes.extend(exports_direct_resources_nodes)
1150    transitive_resources_nodes.extend(exports_transitive_resources_nodes)
1151    transitive_assets.extend(exports_transitive_assets)
1152    transitive_assets_symbols.extend(exports_transitive_assets_symbols)
1153    transitive_compiled_assets.extend(exports_transitive_compiled_assets)
1154    direct_compiled_resources.extend(exports_direct_compiled_resources)
1155    transitive_compiled_resources.extend(exports_transitive_compiled_resources)
1156    transitive_resources_files.extend(exports_transitive_resources_files)
1157    transitive_manifests.extend(exports_transitive_manifests)
1158    transitive_r_txts.extend(exports_transitive_r_txts)
1159
1160    compiled_assets = None
1161    parsed_assets = None
1162    compiled_resources = None
1163    out_aapt2_r_txt = None
1164    r_txt = None
1165    data_binding_layout_info = None
1166    processed_resources = resource_files
1167    processed_manifest = None
1168    if not defines_resources:
1169        if aapt:
1170            # Generate an empty manifest with the right package
1171            generated_manifest = ctx.actions.declare_file(
1172                "_migrated/_generated/" + ctx.label.name + "/AndroidManifest.xml",
1173            )
1174            _generate_dummy_manifest(
1175                ctx,
1176                out_manifest = generated_manifest,
1177                java_package = java_package if java_package else ctx.label.package.replace("/", "."),
1178                min_sdk_version = 14,
1179            )
1180            r_txt = ctx.actions.declare_file(
1181                "_migrated/" + ctx.label.name + "_symbols/R.txt",
1182            )
1183            out_manifest = ctx.actions.declare_file(
1184                "_migrated/" + ctx.label.name + "_processed_manifest/AndroidManifest.xml",
1185            )
1186            _busybox.package(
1187                ctx,
1188                out_r_src_jar = ctx.actions.declare_file(
1189                    "_migrated/" + ctx.label.name + ".srcjar",
1190                ),
1191                out_r_txt = r_txt,
1192                out_manifest = out_manifest,
1193                manifest = generated_manifest,
1194                assets = assets,
1195                assets_dir = assets_dir,
1196                resource_files = resource_files,
1197                direct_resources_nodes =
1198                    depset(transitive = direct_resources_nodes, order = "preorder"),
1199                transitive_resources_nodes =
1200                    depset(transitive = transitive_resources_nodes, order = "preorder"),
1201                transitive_assets = transitive_assets,
1202                transitive_compiled_assets = transitive_compiled_assets,
1203                transitive_resource_files = transitive_resources_files,
1204                transitive_compiled_resources = transitive_compiled_resources,
1205                transitive_manifests = transitive_manifests,
1206                transitive_r_txts = transitive_r_txts,
1207                package_type = "LIBRARY",
1208                java_package = java_package,
1209                android_jar = android_jar,
1210                aapt = aapt,
1211                busybox = busybox,
1212                host_javabase = host_javabase,
1213                should_throw_on_conflict = False,
1214            )
1215            resources_ctx[_STARLARK_PROCESSED_MANIFEST] = out_manifest
1216            resources_ctx[_STARLARK_R_TXT] = r_txt
1217            resources_ctx[_STARLARK_PROCESSED_RESOURCES] = resource_files
1218
1219    else:
1220        if stamp_manifest:
1221            stamped_manifest = ctx.actions.declare_file(
1222                "_migrated/_renamed/" + ctx.label.name + "/AndroidManifest.xml",
1223            )
1224            _busybox.merge_manifests(
1225                ctx,
1226                out_file = stamped_manifest,
1227                manifest = manifest,
1228                merge_type = "LIBRARY",
1229                java_package = java_package,
1230                busybox = busybox,
1231                host_javabase = host_javabase,
1232            )
1233            manifest = stamped_manifest
1234
1235        if instrument_xslt:
1236            g3itr_manifest = ctx.actions.declare_file(
1237                "_migrated/" + ctx.label.name + "_g3itr_manifest/AndroidManifest.xml",
1238            )
1239            _add_g3itr(
1240                ctx,
1241                out_manifest = g3itr_manifest,
1242                manifest = manifest,
1243                xsltproc = xsltproc,
1244                instrument_xslt = instrument_xslt,
1245            )
1246            manifest = g3itr_manifest
1247
1248        parsed_assets = ctx.actions.declare_file(
1249            "_migrated/" + ctx.label.name + "_symbols/assets.bin",
1250        )
1251        _busybox.parse(
1252            ctx,
1253            out_symbols = parsed_assets,
1254            assets = assets,
1255            assets_dir = assets_dir,
1256            busybox = busybox,
1257            host_javabase = host_javabase,
1258        )
1259        merged_assets = ctx.actions.declare_file(
1260            "_migrated/" + ctx.label.name + "_files/assets.zip",
1261        )
1262        _busybox.merge_assets(
1263            ctx,
1264            out_assets_zip = merged_assets,
1265            assets = assets,
1266            assets_dir = assets_dir,
1267            symbols = parsed_assets,
1268            direct_resources_nodes = depset(
1269                transitive = direct_resources_nodes,
1270                order = "preorder",
1271            ),
1272            transitive_resources_nodes = depset(
1273                transitive = transitive_resources_nodes,
1274                order = "preorder",
1275            ),
1276            transitive_assets = transitive_assets,
1277            transitive_assets_symbols = transitive_assets_symbols,
1278            busybox = busybox,
1279            host_javabase = host_javabase,
1280        )
1281        resources_ctx[_VALIDATION_RESULTS].append(merged_assets)
1282
1283        if assets:
1284            compiled_assets = ctx.actions.declare_file(
1285                "_migrated/" + ctx.label.name + "_symbols/assets.zip",
1286            )
1287            _busybox.compile(
1288                ctx,
1289                out_file = compiled_assets,
1290                assets = assets,
1291                assets_dir = assets_dir,
1292                aapt = aapt,
1293                busybox = busybox,
1294                host_javabase = host_javabase,
1295            )
1296
1297        if enable_data_binding:
1298            data_binding_layout_info = ctx.actions.declare_file(
1299                "_migrated/databinding/" + ctx.label.name + "/layout-info.zip",
1300            )
1301            processed_resources, resources_dirname = _make_databinding_outputs(
1302                ctx,
1303                resource_files,
1304            )
1305            _busybox.process_databinding(
1306                ctx,
1307                out_databinding_info = data_binding_layout_info,
1308                out_databinding_processed_resources = processed_resources,
1309                databinding_resources_dirname = resources_dirname,
1310                resource_files = resource_files,
1311                java_package = java_package,
1312                busybox = busybox,
1313                host_javabase = host_javabase,
1314            )
1315
1316        compiled_resources = ctx.actions.declare_file(
1317            "_migrated/" + ctx.label.name + "_symbols/symbols.zip",
1318        )
1319        _busybox.compile(
1320            ctx,
1321            out_file = compiled_resources,
1322            resource_files = processed_resources,
1323            aapt = aapt,
1324            busybox = busybox,
1325            host_javabase = host_javabase,
1326        )
1327
1328        # TODO(b/160907203): Remove this fix once the native resource processing pipeline is turned off.
1329        if enable_data_binding:
1330            fixed_compiled_resources = ctx.actions.declare_file(
1331                "_migrated/fixed/" + ctx.label.name + "_symbols/symbols.zip",
1332            )
1333            _fix_databinding_compiled_resources(
1334                ctx,
1335                out_compiled_resources = fixed_compiled_resources,
1336                compiled_resources = compiled_resources,
1337                zip_tool = zip_tool,
1338            )
1339            compiled_resources = fixed_compiled_resources
1340
1341        out_class_jar = ctx.actions.declare_file(
1342            "_migrated/" + ctx.label.name + "_resources.jar",
1343        )
1344        processed_manifest = ctx.actions.declare_file(
1345            "_migrated/" + ctx.label.name + "_processed_manifest/AndroidManifest.xml",
1346        )
1347        out_aapt2_r_txt = ctx.actions.declare_file(
1348            "_migrated/" + ctx.label.name + "_symbols/R.aapt2.txt",
1349        )
1350        _busybox.merge_compiled(
1351            ctx,
1352            out_class_jar = out_class_jar,
1353            out_manifest = processed_manifest,
1354            out_aapt2_r_txt = out_aapt2_r_txt,
1355            java_package = java_package,
1356            manifest = manifest,
1357            compiled_resources = compiled_resources,
1358            direct_resources_nodes =
1359                depset(transitive = direct_resources_nodes, order = "preorder"),
1360            transitive_resources_nodes = depset(
1361                transitive = transitive_resources_nodes,
1362                order = "preorder",
1363            ),
1364            direct_compiled_resources = depset(
1365                transitive = direct_compiled_resources,
1366                order = "preorder",
1367            ),
1368            transitive_compiled_resources = depset(
1369                transitive = transitive_compiled_resources,
1370                order = "preorder",
1371            ),
1372            android_jar = android_jar,
1373            busybox = busybox,
1374            host_javabase = host_javabase,
1375        )
1376        resources_ctx[_MERGED_MANIFEST] = processed_manifest
1377
1378        apk = ctx.actions.declare_file(
1379            "_migrated/" + ctx.label.name + "_files/library.ap_",
1380        )
1381        r_java = ctx.actions.declare_file(
1382            "_migrated/" + ctx.label.name + ".srcjar",
1383        )
1384        r_txt = ctx.actions.declare_file(
1385            "_migrated/" + ctx.label.name + "_symbols/R.txt",
1386        )
1387        _busybox.validate_and_link(
1388            ctx,
1389            out_r_src_jar = r_java,
1390            out_r_txt = r_txt,
1391            out_file = apk,
1392            compiled_resources = compiled_resources,
1393            transitive_compiled_resources = depset(
1394                transitive = transitive_compiled_resources,
1395                order = "preorder",
1396            ),
1397            java_package = java_package,
1398            manifest = processed_manifest,
1399            android_jar = android_jar,
1400            aapt = aapt,
1401            busybox = busybox,
1402            host_javabase = host_javabase,
1403        )
1404        resources_ctx[_RESOURCES_APK] = apk
1405
1406        java_info = JavaInfo(
1407            output_jar = out_class_jar,
1408            compile_jar = out_class_jar,
1409            source_jar = r_java,
1410        )
1411
1412        packages_to_r_txts_depset.setdefault(java_package, []).append(depset([out_aapt2_r_txt]))
1413
1414        resources_ctx[_R_JAVA] = java_info
1415        resources_ctx[_DATA_BINDING_LAYOUT_INFO] = data_binding_layout_info
1416
1417        # In a normal build, the outputs of _busybox.validate_and_link are unused. However we need
1418        # this action to run to support resource visibility checks.
1419        resources_ctx[_VALIDATION_RESULTS].append(r_txt)
1420
1421        # Needed for AAR generation. The Starlark resource processing pipeline uses the aapt2_r_txt file,
1422        # which is why we can't use the StarlarkAndroidResourcesInfo provider when generating the aar.
1423        resources_ctx[_STARLARK_PROCESSED_MANIFEST] = processed_manifest
1424        resources_ctx[_STARLARK_R_TXT] = r_txt
1425        resources_ctx[_STARLARK_PROCESSED_RESOURCES] = processed_resources
1426
1427    # TODO(b/117338320): Transitive lists defined here are incorrect; direct should come
1428    # before transitive, and the order should be topological order instead of preorder.
1429    # However, some applications may depend on this incorrect order.
1430    if defines_resources:
1431        transitive_resources_nodes = transitive_resources_nodes + direct_resources_nodes
1432        direct_resources_nodes = []
1433        transitive_compiled_resources = transitive_compiled_resources + direct_compiled_resources
1434        direct_compiled_resources = []
1435    else:
1436        if fix_resource_transitivity:
1437            transitive_resources_nodes = transitive_resources_nodes + direct_resources_nodes
1438            direct_resources_nodes = []
1439            transitive_compiled_resources = transitive_compiled_resources + direct_compiled_resources
1440            direct_compiled_resources = []
1441
1442        # TODO(b/144163743): If the resource transitivity fix is disabled and resources-related
1443        # inputs are missing, we implicitly export deps here. This legacy behavior must exist in the
1444        # Starlark resource processing pipeline until we can clean up the depot.
1445
1446    packages_to_r_txts = dict()
1447    for pkg, depsets in packages_to_r_txts_depset.items():
1448        packages_to_r_txts[pkg] = depset(transitive = depsets)
1449
1450    # TODO(b/159916013): Audit neverlink behavior. Some processing can likely be skipped if the target is neverlink.
1451    # TODO(b/69668042): Don't propagate exported providers/artifacts. Exports should respect neverlink.
1452    if resources_neverlink:
1453        resources_ctx[_PROVIDERS].append(StarlarkAndroidResourcesInfo(
1454            direct_resources_nodes = depset(
1455                transitive = exports_direct_resources_nodes,
1456                order = "preorder",
1457            ),
1458            transitive_resources_nodes = depset(
1459                transitive = exports_transitive_resources_nodes,
1460                order = "preorder",
1461            ),
1462            transitive_assets = depset(
1463                transitive = exports_transitive_assets,
1464                order = "preorder",
1465            ),
1466            transitive_assets_symbols = depset(
1467                transitive = exports_transitive_assets_symbols,
1468                order = "preorder",
1469            ),
1470            transitive_compiled_assets = depset(
1471                transitive = exports_transitive_compiled_assets,
1472                order = "preorder",
1473            ),
1474            transitive_resource_files = depset(
1475                transitive = exports_transitive_resources_files,
1476                order = "preorder",
1477            ),
1478            direct_compiled_resources = depset(
1479                transitive = exports_direct_compiled_resources,
1480                order = "preorder",
1481            ),
1482            transitive_compiled_resources = depset(
1483                transitive = exports_transitive_compiled_resources,
1484                order = "preorder",
1485            ),
1486            transitive_manifests = depset(
1487                [processed_manifest] if processed_manifest else [],
1488                transitive = exports_transitive_manifests,
1489                order = "preorder",
1490            ),
1491            transitive_r_txts = depset(
1492                [out_aapt2_r_txt] if out_aapt2_r_txt else [],
1493                transitive = exports_transitive_r_txts,
1494                order = "preorder",
1495            ),
1496            packages_to_r_txts = packages_to_r_txts,
1497        ))
1498    else:
1499        # Depsets are ordered below to match the order in the legacy native rules.
1500        resources_ctx[_PROVIDERS].append(StarlarkAndroidResourcesInfo(
1501            direct_resources_nodes = depset(
1502                [ResourcesNodeInfo(
1503                    label = ctx.label,
1504                    assets = depset(assets),
1505                    assets_dir = assets_dir,
1506                    assets_symbols = parsed_assets,
1507                    compiled_assets = compiled_assets,
1508                    resource_files = depset(processed_resources),
1509                    compiled_resources = compiled_resources,
1510                    r_txt = out_aapt2_r_txt,
1511                    manifest = processed_manifest,
1512                    exports_manifest = exports_manifest,
1513                )] if defines_resources else [],
1514                transitive = direct_resources_nodes + exports_direct_resources_nodes,
1515                order = "preorder",
1516            ),
1517            transitive_resources_nodes = depset(
1518                transitive = transitive_resources_nodes + exports_transitive_resources_nodes,
1519                order = "preorder",
1520            ),
1521            transitive_assets = depset(
1522                assets,
1523                transitive = transitive_assets + exports_transitive_assets,
1524                order = "preorder",
1525            ),
1526            transitive_assets_symbols = depset(
1527                [parsed_assets] if parsed_assets else [],
1528                transitive = transitive_assets_symbols + exports_transitive_assets_symbols,
1529                order = "preorder",
1530            ),
1531            transitive_compiled_assets = depset(
1532                [compiled_assets] if compiled_assets else [],
1533                transitive = transitive_compiled_assets + exports_transitive_compiled_assets,
1534                order = "preorder",
1535            ),
1536            transitive_resource_files = depset(
1537                processed_resources,
1538                transitive = transitive_resources_files + exports_transitive_resources_files,
1539                order = "preorder",
1540            ),
1541            direct_compiled_resources = depset(
1542                [compiled_resources] if compiled_resources else [],
1543                transitive = direct_compiled_resources + exports_direct_compiled_resources,
1544                order = "preorder",
1545            ),
1546            transitive_compiled_resources = depset(
1547                [compiled_resources] if compiled_resources else [],
1548                transitive = transitive_compiled_resources + exports_transitive_compiled_resources,
1549                order = "preorder",
1550            ),
1551            transitive_manifests = depset(
1552                [processed_manifest] if processed_manifest else [],
1553                transitive = transitive_manifests + exports_transitive_manifests,
1554                order = "preorder",
1555            ),
1556            transitive_r_txts = depset(
1557                [out_aapt2_r_txt] if out_aapt2_r_txt else [],
1558                transitive = transitive_r_txts + exports_transitive_r_txts,
1559                order = "preorder",
1560            ),
1561            packages_to_r_txts = packages_to_r_txts,
1562        ))
1563
1564    if not propagate_resources:
1565        resources_ctx[_R_JAVA] = None
1566        resources_ctx[_PROVIDERS] = []
1567
1568    # TODO(b/69552500): In the Starlark Android Rules, the R compile time
1569    # JavaInfo is added as a runtime dependency to the JavaInfo. Stop
1570    # adding the R.jar as a runtime dependency.
1571    resources_ctx[_PROVIDERS].append(
1572        AndroidLibraryResourceClassJarProvider(
1573            depset(
1574                (resources_ctx[_R_JAVA].runtime_output_jars if resources_ctx[_R_JAVA] else []),
1575                transitive = [
1576                    p.jars
1577                    for p in utils.collect_providers(
1578                        AndroidLibraryResourceClassJarProvider,
1579                        deps,
1580                        exports,
1581                    )
1582                ],
1583                order = "preorder",
1584            ),
1585        ),
1586    )
1587
1588    return resources_ctx
1589
1590
1591def _process(
1592        ctx,
1593        manifest = None,
1594        resource_files = None,
1595        defined_assets = False,
1596        assets = None,
1597        defined_assets_dir = False,
1598        assets_dir = None,
1599        exports_manifest = False,
1600        java_package = None,
1601        custom_package = None,
1602        neverlink = False,
1603        enable_data_binding = False,
1604        deps = [],
1605        exports = [],
1606        android_jar = None,
1607        android_kit = None,
1608        aapt = None,
1609        busybox = None,
1610        xsltproc = None,
1611        instrument_xslt = None,
1612        java_toolchain = None,
1613        host_javabase = None,
1614        enable_res_v3 = False,
1615        res_v3_dummy_manifest = None,
1616        res_v3_dummy_r_txt = None,
1617        fix_resource_transitivity = False,
1618        fix_export_exporting = False,
1619        propagate_resources = True,
1620        zip_tool = None):
1621    out_ctx = _process_starlark(
1622        ctx,
1623        java_package = java_package,
1624        manifest = manifest,
1625        defined_assets = defined_assets,
1626        # TODO(b/159937795): When the Starlark Resources Processing pipeline is
1627        # default and the native version is no longer used, remove the depset
1628        # creation and directly pass through ctx.files.assets to this method.
1629        assets =
1630            depset(transitive = [target.files for target in assets]).to_list(),
1631        defined_assets_dir = defined_assets_dir,
1632        assets_dir = assets_dir,
1633        exports_manifest = exports_manifest,
1634        stamp_manifest = True if java_package else False,
1635        deps = deps,
1636        exports = exports,
1637        resource_files = depset(transitive = [target.files for target in resource_files]).to_list(),
1638        enable_data_binding = enable_data_binding,
1639        fix_resource_transitivity = fix_resource_transitivity,
1640        neverlink = neverlink,
1641        propagate_resources = propagate_resources,
1642        android_jar = android_jar,
1643        aapt = aapt,
1644        android_kit = android_kit,
1645        busybox = busybox,
1646        instrument_xslt = instrument_xslt,
1647        xsltproc = xsltproc,
1648        java_toolchain = java_toolchain,
1649        host_javabase = host_javabase,
1650        zip_tool = zip_tool,
1651    )
1652
1653
1654    if _VALIDATION_OUTPUTS not in out_ctx:
1655        out_ctx[_VALIDATION_OUTPUTS] = []
1656
1657    return _ResourcesProcessContextInfo(**out_ctx)
1658
1659resources = struct(
1660    process = _process,
1661    process_starlark = _process_starlark,
1662    package = _package,
1663    make_aar = _make_aar,
1664
1665    # Exposed for mobile-install
1666    compile = _compile,
1667    legacy_merge_manifests = _legacy_merge_manifests,
1668
1669    # Exposed for android_local_test and android_library
1670    generate_dummy_manifest = _generate_dummy_manifest,
1671)
1672
1673testing = struct(
1674    add_g3itr = _add_g3itr,
1675    filter_multi_cpu_configuration_targets = _filter_multi_cpu_configuration_targets,
1676    get_legacy_mergee_manifests = _get_legacy_mergee_manifests,
1677    make_databinding_outputs = _make_databinding_outputs,
1678    ResourcesPackageContextInfo = _ResourcesPackageContextInfo,
1679    ResourcesProcessContextInfo = _ResourcesProcessContextInfo,
1680)
1681