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