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