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