diff options
author | Alex Humesky <ahumesky@google.com> | 2021-03-12 19:28:48 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-03-12 19:28:48 +0000 |
commit | 92da1f5774730994d89834a998ceaacaa66a13d8 (patch) | |
tree | 1235b70b3a0d7150512ecc273c4db0294c76d6ca | |
parent | b8983ae9e51d225bb60d3298bd670284b615cc68 (diff) | |
parent | be08255c526ee9364a5f5089a4cd5c2afe4024ed (diff) | |
download | bazelbuild-rules_android-92da1f5774730994d89834a998ceaacaa66a13d8.tar.gz |
Merge remote-tracking branch 'remotes/aosp/upstream-pre-alpha' into import am: 6c9db3a63b am: 05eb06d367 am: 133707eb38 am: be08255c52
Original change: https://android-review.googlesource.com/c/platform/external/bazelbuild-rules_android/+/1628943
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: I1980bf4a1dde6c54d4832e8d498fafe038769102
107 files changed, 9768 insertions, 0 deletions
diff --git a/.bazelci/postsubmit.yml b/.bazelci/postsubmit.yml new file mode 100644 index 0000000..c1218a6 --- /dev/null +++ b/.bazelci/postsubmit.yml @@ -0,0 +1,22 @@ +--- +platforms: + ubuntu1604: + build_targets: + - "//..." + # test_targets: + # - "//..." + ubuntu1804: + build_targets: + - "//..." + # test_targets: + # - "//..." + macos: + build_targets: + - "//..." + # test_targets: + # - "//..." + windows: + build_targets: + - "//..." + # test_targets: + # - "//..." @@ -0,0 +1,9 @@ +# This the official list of authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. + +# Names should be added to this file as: +# Name or Organization <email address> +# The email address is not required for organizations. + +Google LLC diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..6902cfb --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @djwhang @jin @ahumesky @mauriciogg @timpeut @git-str diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..99da6f8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,39 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +**Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) +(CLA)**, which you can do online. + +The CLA is necessary mainly because you own the copyright to your changes, +even after your contribution becomes part of our codebase, so we need your +permission to use and distribute your code. We also need to be sure of +various other things — for instance that you'll tell us if you know that +your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +### The small print +Contributions made by corporations are covered by a different agreement than +the one above, the +[Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate). + +### Contribution process + +1. Explain your idea and discuss your plan with members of the team. The best + way to do this is to create + an [issue](https://github.com/bazelbuild/rules_android/issues) or comment on + an existing issue. +1. Prepare a git commit with your change. Don't forget to + add [tests](https://github.com/bazelbuild/rules_android/tree/master/tests). + Run the existing tests with `bazel test //...`. Update + [README.md](https://github.com/bazelbuild/rules_android/blob/master/README.md) + if appropriate. +1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request/). + This will start the code review process. **All submissions, including + submissions by project members, require review.** +1. You may be asked to make some changes. You'll also need to sign the CLA at + this point, if you haven't done so already. Our continuous integration bots + will test your change automatically on supported platforms. Once everything + looks good, your change will be merged. diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..8fc0e51 --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,16 @@ +# People who have agreed to one of the CLAs and can contribute patches. +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. +# +# https://developers.google.com/open-source/cla/individual +# https://developers.google.com/open-source/cla/corporate +# +# Names should be added to this file as: +# Name <email address> +Daniel Whang <djwhang@google.com> +Mauricio Galindo <mauriciogg@google.com> +Stefan Ramsauer <str@google.com> +Tim Peut <timpeut@google.com> +Alex Humesky <ahumesky@google.com> +Jingwen Chen <jingwen@google.com> @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6cba04f --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# Android support in Bazel + +## Disclaimer + +NOTE: This branch contains a development preview of the Starlark implementation of Android rules for Bazel. This code is incomplete and may not function as-is. + +Bazel 4.0.0 or newer and the following flags are necessary to use these rules: +``` +--experimental_enable_android_migration_apis +--experimental_google_legacy_api +--incompatible_java_common_parameters +--android_databinding_use_v3_4_args +--experimental_android_databinding_v2 +``` + +Also, register the Android toolchains in the `WORKSPACE` file with: +``` +register_toolchains( + "@build_bazel_rules_android//toolchains/android:android_default_toolchain", + "@build_bazel_rules_android//toolchains/android_sdk:android_sdk_tools", +) +``` +(Assuming that the Android rules repository in the `WORKSPACE` file is named `build_bazel_rules_android`.) + +## Overview + +This repository contains the Starlark implementation of Android rules in Bazel. + +The rules are being incrementally converted from their native implementations +in the [Bazel source +tree](https://source.bazel.build/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/android/). + +For the list of Android rules, see the Bazel [documentation](https://docs.bazel.build/versions/master/be/android.html). + +## Getting Started +To use the new Bazel Android rules, add the following to your WORKSPACE file: + + load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + http_archive( + name = "build_bazel_rules_android", + urls = ["https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"], + sha256 = "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", + strip_prefix = "rules_android-0.1.1", + ) + +Then, in your BUILD files, import and use the rules: + + load("@build_bazel_rules_android//rules:rules.bzl", "android_library") + android_library( + ... + ) diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..57e46c3 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,71 @@ + +# Android Bazel Roadmap + +This document describes the major release milestones for the Android Bazel +Rules. There are three major pillars that we are focused on when developing the +Android rules - **Performance**, **Features**, and **Developer Experience** - +and for each milestone we list the main items for each pillar. Progress on each +item is tracked via an issue. + +If you have feedback on this roadmap (including feature and reprioritization +requests) please open an issue or comment on the existing one. + +## Rules Alpha (est. mid 2019) + +The primary goal of the Rules Alpha release is to start collecting feedback from +projects and developers that are interested in being early adopters of the +rules. Our intention is for Rules Alpha to be a 1:1 identical drop-in +replacement for the native Android rules, although undoubtedly there will be +missing features and we cannot always guarantee 100% backwards compatibility. + +### Performance + +* Use AAPT2 for resource processing +* Use D8 for Dexing + +### Features + +* Support android_instrumentation_test on macOS +* Support building and testing on Google Cloud Platform Remote Build Execution +* Support new Android App Bundle format +* Accept APKs directly into android_instrumentation_test +* Simplified package and dependency management +* Improve Kotlin interoperability +* Integration with Bazel's platforms and toolchains support +* Modern and correct NDK support + +### Developer Experience + +* Documentation for Android with Bazel compatibility across Windows, macOS, + Linux +* Documentation for Android with Bazel compatibility across Android Studio + versions +* Stable and reliable CI +* NDK documentation and samples + +## Rules Beta (est. late 2019) + +The goal for the Rules Beta release is to provide a stable, (mostly) feature +complete version of the rules for all developers and projects. We intend the +Rules Beta release to be the first version of the rules to be broadly adopted, +and will comply with Bazel's backwards compatibility guarantees. + +### Performance + +* Improve resource processing speed and incrementality +* Decouple Java compilation from R.class generation +* Launch Bazel mobile-install v2 + +### Features + +* New android_application rule for app packaging / sourceless binary / + android_application +* Improved support for AAR creation +* Support Databinding 3.4.0 (v2) +* Support `bazel coverage` for all test rules +* Integration with Android Lint + +### Developer Experience + +* Document best practices +* Best in class tutorials and migration guides diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 0000000..9c8339a --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,3 @@ +workspace(name = "build_bazel_rules_android") + +register_toolchains("//android/toolchains/emulator:all") diff --git a/rules/BUILD b/rules/BUILD new file mode 100644 index 0000000..b233605 --- /dev/null +++ b/rules/BUILD @@ -0,0 +1,18 @@ +exports_files([ + "data_binding_annotation_template.txt", + "res_v3_dummy_AndroidManifest.xml", + "res_v3_dummy_R.txt", + "robolectric_properties_template.txt", +]) + +alias( + name = "ResourceProcessorBusyBox", + actual = "@bazel_tools//tools/android:busybox", + visibility = ["//visibility:public"], +) + +alias( + name = "current_java_runtime", + actual = "@bazel_tools//tools/jdk:current_java_runtime", + visibility = ["//visibility:public"], +) diff --git a/rules/aar_import/BUILD b/rules/aar_import/BUILD new file mode 100644 index 0000000..50d41fe --- /dev/null +++ b/rules/aar_import/BUILD @@ -0,0 +1,21 @@ +# The aar_import rule. + +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + +licenses(["notice"]) + +exports_files(["rule.bzl"]) + +filegroup( + name = "all_files", + srcs = glob(["**"]), +) + +bzl_library( + name = "bzl", + srcs = glob(["*.bzl"]), + deps = [ + "@rules_android//rules:common_bzl", + "@rules_android//rules/flags:bzl", + ], +) diff --git a/rules/aar_import/attrs.bzl b/rules/aar_import/attrs.bzl new file mode 100644 index 0000000..5ac9c7a --- /dev/null +++ b/rules/aar_import/attrs.bzl @@ -0,0 +1,64 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Attributes.""" + +load( + "@rules_android//rules:attrs.bzl", + _attrs = "attrs", +) + +ATTRS = _attrs.add( + dict( + aar = attr.label( + allow_single_file = [".aar"], + mandatory = True, + ), + data = attr.label_list(allow_files = True), + deps = attr.label_list( + allow_files = False, + providers = [JavaInfo], + ), + exports = attr.label_list( + allow_files = False, + allow_rules = ["aar_import", "java_import"], + ), + has_lint_jar = attr.bool( + default = False, + doc = "Whether the aar contains a lint.jar. This is required to " + + "know at analysis time if a lint jar is included in the aar.", + ), + package = attr.string( + doc = "Package to use while processing the aar at analysis time. " + + "This needs to be the same value as the manifest's package.", + ), + srcjar = attr.label( + allow_single_file = [".srcjar"], + doc = + "A srcjar file that contains the source code for the JVM " + + "artifacts stored within the AAR.", + ), + _flags = attr.label( + default = "@rules_android//rules/flags", + ), + _java_toolchain = attr.label( + default = Label("//tools/jdk:toolchain_android_only"), + ), + _host_javabase = attr.label( + cfg = "host", + default = Label("//tools/jdk:current_java_runtime"), + ), + ), + _attrs.DATA_CONTEXT, +) diff --git a/rules/aar_import/impl.bzl b/rules/aar_import/impl.bzl new file mode 100644 index 0000000..96baa2b --- /dev/null +++ b/rules/aar_import/impl.bzl @@ -0,0 +1,547 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Implementation.""" + +load( + "@rules_android//rules:acls.bzl", + _acls = "acls", +) +load( + "@rules_android//rules:common.bzl", + _common = "common", +) +load("@rules_android//rules:intellij.bzl", "intellij") +load( + "@rules_android//rules:java.bzl", + _java = "java", +) +load("@rules_android//rules:providers.bzl", "AndroidLintRulesInfo") +load( + "@rules_android//rules:resources.bzl", + _resources = "resources", +) +load( + "@rules_android//rules:utils.bzl", + _get_android_toolchain = "get_android_toolchain", + _utils = "utils", +) + +RULE_PREFIX = "_aar" +ANDROID_MANIFEST = "AndroidManifest.xml" +LINT_JAR = "lint.jar" +_UNEXPECTED_LINT_JAR_ERROR = ( + "In target %s, has_lint_jar attribute is required when the aar contains " + + "a lint.jar file." +) + +def _create_aar_artifact(ctx, name): + return ctx.actions.declare_file("%s/%s/%s" % (RULE_PREFIX, ctx.label.name, name)) + +def _create_aar_tree_artifact(ctx, name): + return ctx.actions.declare_directory("%s/unzipped/%s/%s" % (RULE_PREFIX, name, ctx.label.name)) + +# Create an action to extract a file (specified by the parameter filename) from an AAR file. +def _extract_single_file( + ctx, + out_file, + aar, + filename, + unzip_tool): + args = ctx.actions.args() + args.add(aar) + args.add(filename) + args.add("-d", out_file.dirname) + + ctx.actions.run( + executable = unzip_tool, + arguments = [args], + inputs = [aar], + outputs = [out_file], + mnemonic = "AarFileExtractor", + progress_message = "Extracting %s from %s" % (filename, aar.basename), + ) + +def _extract_resources( + ctx, + out_resources_dir, + out_assets_dir, + aar, + aar_resources_extractor_tool): + args = ctx.actions.args() + args.add("--input_aar", aar) + args.add("--output_res_dir", out_resources_dir.path) + args.add("--output_assets_dir", out_assets_dir.path) + ctx.actions.run( + executable = aar_resources_extractor_tool, + arguments = [args], + inputs = [aar], + outputs = [out_resources_dir, out_assets_dir], + mnemonic = "AarResourcesExtractor", + progress_message = "Extracting resources and assets from %s" % aar.basename, + ) + +def _extract_native_libs( + ctx, + output_zip, + aar, + android_cpu, + aar_native_libs_zip_creator_tool): + args = ctx.actions.args() + args.add("--input_aar", aar) + args.add("--cpu", android_cpu) + args.add("--output_zip", output_zip) + ctx.actions.run( + executable = aar_native_libs_zip_creator_tool, + arguments = [args], + inputs = [aar], + outputs = [output_zip], + mnemonic = "AarNativeLibsFilter", + progress_message = "Filtering AAR native libs by architecture", + ) + +def _process_resources( + ctx, + aar, + manifest, + deps, + aar_resources_extractor_tool, + unzip_tool): + # Extract resources and assets, if they exist. + resources = _create_aar_tree_artifact(ctx, "resources") + assets = _create_aar_tree_artifact(ctx, "assets") + _extract_resources( + ctx, + resources, + assets, + aar, + aar_resources_extractor_tool, + ) + + resources_ctx = _resources.process_starlark( + ctx, + manifest = manifest, + assets = [assets], + assets_dir = assets.path, + resource_files = [resources], + stamp_manifest = False, + deps = ctx.attr.deps, + exports = ctx.attr.exports, + exports_manifest = getattr(ctx.attr, "exports_manifest", True), + + # Tool and Processing related inputs + aapt = _get_android_toolchain(ctx).aapt2.files_to_run, + android_jar = ctx.attr._android_sdk[AndroidSdkInfo].android_jar, + android_kit = _get_android_toolchain(ctx).android_kit.files_to_run, + busybox = _get_android_toolchain(ctx).android_resources_busybox.files_to_run, + java_toolchain = _common.get_java_toolchain(ctx), + host_javabase = _common.get_host_javabase(ctx), + instrument_xslt = _utils.only(_get_android_toolchain(ctx).add_g3itr_xslt.files.to_list()), + xsltproc = _get_android_toolchain(ctx).xsltproc_tool.files_to_run, + ) + + # TODO: replace android_data + # data_ctx = android_data.make_context(ctx.actions, ctx.attr) + # resource_apk = android_data.process_aar_import_data( + # data_ctx, + # resources, + # assets, + # manifest, + # deps = deps, + # ) + # resources_ctx["validation_results"].append( + # _utils.only(resource_apk[AndroidResourcesInfo].direct_android_resources.to_list()).java_class_jar, + # ) + # resources_ctx["providers"].append(resource_apk[AndroidResourcesInfo]) + # resources_ctx["providers"].append(resource_apk[AndroidAssetsInfo]) + + if not _acls.in_aar_propagate_resources(str(ctx.label)): + resources_ctx["providers"] = [] + + return struct(**resources_ctx) + +def _extract_jars( + ctx, + out_jars_tree_artifact, + out_jars_params_file, + aar, + aar_embedded_jars_extractor_tool): + args = ctx.actions.args() + args.add("--input_aar", aar) + args.add("--output_dir", out_jars_tree_artifact.path) + args.add("--output_singlejar_param_file", out_jars_params_file) + ctx.actions.run( + executable = aar_embedded_jars_extractor_tool, + arguments = [args], + inputs = [aar], + outputs = [out_jars_tree_artifact, out_jars_params_file], + mnemonic = "AarEmbeddedJarsExtractor", + progress_message = "Extracting classes.jar and libs/*.jar from %s" % aar.basename, + ) + +def _merge_jars( + ctx, + out_jar, + jars_tree_artifact, + jars_param_file, + single_jar_tool): + args = ctx.actions.args() + args.add("--output", out_jar) + args.add("--dont_change_compression") + args.add("--normalize") + args.add("@" + jars_param_file.path) + ctx.actions.run( + executable = single_jar_tool, + arguments = [args], + inputs = [jars_tree_artifact, jars_param_file], + outputs = [out_jar], + mnemonic = "AarJarsMerger", + progress_message = "Merging AAR embedded jars", + ) + +def _extract_and_merge_jars( + ctx, + out_jar, + aar, + aar_embedded_jars_extractor_tool, + single_jar_tool): + """Extracts all the Jars within the AAR and produces a single jar. + + An AAR may have multiple Jar files embedded within it. This method + extracts and merges all Jars. + """ + jars_tree_artifact = _create_aar_tree_artifact(ctx, "jars") + jars_params_file = _create_aar_artifact(ctx, "jar_merging_params") + _extract_jars( + ctx, + jars_tree_artifact, + jars_params_file, + aar, + aar_embedded_jars_extractor_tool, + ) + _merge_jars( + ctx, + out_jar, + jars_tree_artifact, + jars_params_file, + single_jar_tool, + ) + +def _create_import_deps_check( + ctx, + jars_to_check, + declared_deps, + transitive_deps, + bootclasspath, + jdeps_output, + import_deps_checker_tool, + host_javabase): + args = ctx.actions.args() + args.add_all(jars_to_check, before_each = "--input") + args.add_all(declared_deps, before_each = "--directdep") + args.add_all(transitive_deps, before_each = "--classpath_entry") + args.add_all(bootclasspath, before_each = "--bootclasspath_entry") + args.add("--checking_mode=error") + args.add("--jdeps_output", jdeps_output) + args.add("--rule_label", ctx.label) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = import_deps_checker_tool, + arguments = [args], + inputs = depset( + jars_to_check, + transitive = [ + declared_deps, + transitive_deps, + bootclasspath, + ], + ), + outputs = [jdeps_output], + mnemonic = "ImportDepsChecker", + progress_message = "Checking the completeness of the deps for %s" % jars_to_check, + ) + +def _process_jars( + ctx, + out_jar, + aar, + source_jar, + r_java, + deps, + exports, + enable_desugar_java8, + enable_imports_deps_check, + bootclasspath, + desugar_java8_extra_bootclasspath, + aar_embedded_jars_extractor_tool, + import_deps_checker_tool, + single_jar_tool, + java_toolchain, + host_javabase): + providers = [] + validation_results = [] + r_java_info = [r_java] if r_java else [] + + # An aar may have multple Jar files, extract and merge into a single jar. + _extract_and_merge_jars( + ctx, + out_jar, + aar, + aar_embedded_jars_extractor_tool, + single_jar_tool, + ) + + java_infos = deps + exports + + if enable_desugar_java8: + bootclasspath = depset(transitive = [ + desugar_java8_extra_bootclasspath, + bootclasspath, + ]) + + merged_java_info = java_common.merge(java_infos + r_java_info) + jdeps_artifact = _create_aar_artifact(ctx, "jdeps.proto") + _create_import_deps_check( + ctx, + [out_jar], + merged_java_info.compile_jars, + merged_java_info.transitive_compile_time_jars, + bootclasspath, + jdeps_artifact, + import_deps_checker_tool, + host_javabase, + ) + if enable_imports_deps_check: + validation_results.append(jdeps_artifact) + + java_info = JavaInfo( + out_jar, + compile_jar = java_common.stamp_jar( + actions = ctx.actions, + jar = out_jar, + target_label = ctx.label, + java_toolchain = java_toolchain, + ), + source_jar = source_jar, + neverlink = False, + deps = r_java_info + java_infos, # TODO(djwhang): Exports are not deps. + exports = + (r_java_info if _acls.in_aar_import_exports_r_java(str(ctx.label)) else []) + + java_infos, # TODO(djwhang): Deps are not exports. + # TODO(djwhang): AarImportTest is not expecting jdeps, enable or remove it completely + # jdeps = jdeps_artifact, + ) + providers.append(java_info) + + return struct( + java_info = java_info, + providers = providers, + validation_results = validation_results, + ) + +def _validate_rule( + ctx, + aar, + manifest, + checks): + package = _java.resolve_package_from_label(ctx.label, ctx.attr.package) + validation_output = ctx.actions.declare_file("%s_validation_output" % ctx.label.name) + + args = ctx.actions.args() + args.add("-aar", aar) + inputs = [aar] + args.add("-label", str(ctx.label)) + if _acls.in_aar_import_pkg_check(str(ctx.label)): + args.add("-pkg", package) + args.add("-manifest", manifest) + inputs.append(manifest) + if ctx.attr.has_lint_jar: + args.add("-has_lint_jar") + args.add("-output", validation_output) + + ctx.actions.run( + executable = checks, + arguments = [args], + inputs = inputs, + outputs = [validation_output], + mnemonic = "ValidateAAR", + progress_message = "Validating aar_import %s" % str(ctx.label), + ) + return validation_output + +def _process_lint_rules( + ctx, + aar, + unzip_tool): + providers = [] + + if ctx.attr.has_lint_jar: + lint_jar = _create_aar_artifact(ctx, LINT_JAR) + _extract_single_file( + ctx, + lint_jar, + aar, + LINT_JAR, + unzip_tool, + ) + providers.append(AndroidLintRulesInfo( + lint_jar = lint_jar, + )) + + providers.extend(_utils.collect_providers( + AndroidLintRulesInfo, + ctx.attr.exports, + )) + return providers + +def impl(ctx): + """The rule implementation. + + Args: + ctx: The context. + + Returns: + A list of providers. + """ + providers = [] + validation_outputs = [] + + aar = _utils.only(ctx.files.aar) + unzip_tool = _get_android_toolchain(ctx).unzip_tool.files_to_run + + # Extract the AndroidManifest.xml from the AAR. + android_manifest = _create_aar_artifact(ctx, ANDROID_MANIFEST) + _extract_single_file( + ctx, + android_manifest, + aar, + ANDROID_MANIFEST, + unzip_tool, + ) + + resources_ctx = _process_resources( + ctx, + aar = aar, + manifest = android_manifest, + deps = ctx.attr.deps, + aar_resources_extractor_tool = + _get_android_toolchain(ctx).aar_resources_extractor.files_to_run, + unzip_tool = unzip_tool, + ) + providers.extend(resources_ctx.providers) + + merged_jar = _create_aar_artifact(ctx, "classes_and_libs_merged.jar") + jvm_ctx = _process_jars( + ctx, + out_jar = merged_jar, + aar = aar, + source_jar = ctx.file.srcjar, + deps = _utils.collect_providers(JavaInfo, ctx.attr.deps), + r_java = resources_ctx.r_java, + exports = _utils.collect_providers(JavaInfo, ctx.attr.exports), + enable_desugar_java8 = ctx.fragments.android.desugar_java8, + enable_imports_deps_check = + _acls.in_aar_import_deps_checker(str(ctx.label)), + aar_embedded_jars_extractor_tool = + _get_android_toolchain(ctx).aar_embedded_jars_extractor.files_to_run, + bootclasspath = + ctx.attr._java_toolchain[java_common.JavaToolchainInfo].bootclasspath, + desugar_java8_extra_bootclasspath = + _get_android_toolchain(ctx).desugar_java8_extra_bootclasspath.files, + import_deps_checker_tool = + _get_android_toolchain(ctx).import_deps_checker.files_to_run, + single_jar_tool = + ctx.attr._java_toolchain[java_common.JavaToolchainInfo].single_jar, + java_toolchain = + ctx.attr._java_toolchain[java_common.JavaToolchainInfo], + host_javabase = ctx.attr._host_javabase, + ) + providers.extend(jvm_ctx.providers) + validation_outputs.extend(jvm_ctx.validation_results) + + native_libs = _create_aar_artifact(ctx, "native_libs.zip") + _extract_native_libs( + ctx, + native_libs, + aar = aar, + android_cpu = ctx.fragments.android.android_cpu, + aar_native_libs_zip_creator_tool = + _get_android_toolchain(ctx).aar_native_libs_zip_creator.files_to_run, + ) + native_libs_infos = _utils.collect_providers( + AndroidNativeLibsInfo, + ctx.attr.deps, + ctx.attr.exports, + ) + providers.append( + AndroidNativeLibsInfo( + depset( + [native_libs], + transitive = [info.native_libs for info in native_libs_infos], + ), + ), + ) + + lint_providers = _process_lint_rules( + ctx, + aar = aar, + unzip_tool = unzip_tool, + ) + providers.extend(lint_providers) + + validation_outputs.append(_validate_rule( + ctx, + aar = aar, + manifest = android_manifest, + checks = _get_android_toolchain(ctx).aar_import_checks.files_to_run, + )) + + providers.append( + intellij.make_android_ide_info( + ctx, + java_package = _java.resolve_package_from_label(ctx.label, ctx.attr.package), + manifest = resources_ctx.merged_manifest, + defines_resources = resources_ctx.defines_resources, + merged_manifest = resources_ctx.merged_manifest, + resources_apk = resources_ctx.resources_apk, + r_jar = _utils.only(resources_ctx.r_java.outputs.jars) if resources_ctx.r_java else None, + java_info = jvm_ctx.java_info, + signed_apk = None, # signed_apk, always empty for aar_import + apks_under_test = [], # apks_under_test, always empty for aar_import + native_libs = dict(), # nativelibs, always empty for aar_import + idlclass = _get_android_toolchain(ctx).idlclass.files_to_run, + host_javabase = _common.get_host_javabase(ctx), + ), + ) + + providers.append(OutputGroupInfo(_validation = depset(validation_outputs))) + + # There isn't really any use case for building an aar_import target on its own, so the files to + # build could be empty. The R class JAR and merged JARs are added here as a sanity check for + # Bazel developers so that `bazel build java/com/my_aar_import` will fail if the resource + # processing or JAR merging steps fail. + files_to_build = [] + files_to_build.extend(resources_ctx.validation_results) # TODO(djwhang): This should be validation. + files_to_build.append(merged_jar) + + providers.append( + DefaultInfo( + files = depset(files_to_build), + runfiles = ctx.runfiles(), + ), + ) + + return providers diff --git a/rules/aar_import/rule.bzl b/rules/aar_import/rule.bzl new file mode 100644 index 0000000..fa78a88 --- /dev/null +++ b/rules/aar_import/rule.bzl @@ -0,0 +1,26 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""aar_import rule.""" + +load(":attrs.bzl", _ATTRS = "ATTRS") +load(":impl.bzl", _impl = "impl") + +aar_import = rule( + attrs = _ATTRS, + fragments = ["android"], + implementation = _impl, + provides = [AndroidNativeLibsInfo, JavaInfo], + toolchains = ["@rules_android//toolchains/android:toolchain_type"], +) diff --git a/rules/acls.bzl b/rules/acls.bzl new file mode 100644 index 0000000..ade99db --- /dev/null +++ b/rules/acls.bzl @@ -0,0 +1,318 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Access Control Lists. + +To create a new list: + 1. Create new .bzl file in this directory with a list of targets. + 2. Create matching method in this file. + 3. Add matching method to struct. + +To check an ACL: + 1. Import the `acls` struct. + 2. Check `acls.list_name(fqn)` using the //fully/qualified:target + +To update a list: + 1. Directly add/remove/edit targets in the appropriate .bzl file +""" + +load("@rules_android//rules/acls:aar_import_deps_checker.bzl", "AAR_IMPORT_DEPS_CHECKER_FALLBACK", "AAR_IMPORT_DEPS_CHECKER_ROLLOUT") +load("@rules_android//rules/acls:aar_import_explicit_exports_manifest.bzl", "AAR_IMPORT_EXPLICIT_EXPORTS_MANIFEST") +load("@rules_android//rules/acls:aar_import_exports_r_java.bzl", "AAR_IMPORT_EXPORTS_R_JAVA") +load("@rules_android//rules/acls:aar_import_package_check.bzl", "AAR_IMPORT_PKG_CHECK_FALLBACK", "AAR_IMPORT_PKG_CHECK_ROLLOUT") +load("@rules_android//rules/acls:aar_propagate_resources.bzl", "AAR_PROPAGATE_RESOURCES_FALLBACK", "AAR_PROPAGATE_RESOURCES_ROLLOUT") +load("@rules_android//rules/acls:ait_install_snapshots.bzl", "APP_INSTALLATION_SNAPSHOT", "APP_INSTALLATION_SNAPSHOT_FALLBACK") +load("@rules_android//rules/acls:ait_virtual_device.bzl", "AIT_VIRTUAL_DEVICE_FALLBACK", "AIT_VIRTUAL_DEVICE_ROLLOUT") +load("@rules_android//rules/acls:allow_resource_conflicts.bzl", "ALLOW_RESOURCE_CONFLICTS") +load("@rules_android//rules/acls:android_archive_dogfood.bzl", "ANDROID_ARCHIVE_DOGFOOD") +load("@rules_android//rules/acls:android_test_lockdown.bzl", "ANDROID_TEST_LOCKDOWN_GENERATOR_FUNCTIONS", "ANDROID_TEST_LOCKDOWN_TARGETS") +load("@rules_android//rules/acls:android_device_plugin_rollout.bzl", "ANDROID_DEVICE_PLUGIN_FALLBACK", "ANDROID_DEVICE_PLUGIN_ROLLOUT") +load("@rules_android//rules/acls:android_instrumentation_binary_starlark_resources.bzl", "ANDROID_INSTRUMENTATION_BINARY_STARLARK_RESOURCES_FALLBACK", "ANDROID_INSTRUMENTATION_BINARY_STARLARK_RESOURCES_ROLLOUT") +load("@rules_android//rules/acls:android_feature_splits_dogfood.bzl", "ANDROID_FEATURE_SPLITS_DOGFOOD") +load("@rules_android//rules/acls:android_library_implicit_exports.bzl", "ANDROID_LIBRARY_IMPLICIT_EXPORTS", "ANDROID_LIBRARY_IMPLICIT_EXPORTS_GENERATOR_FUNCTIONS") +load("@rules_android//rules/acls:android_library_resources_without_srcs.bzl", "ANDROID_LIBRARY_RESOURCES_WITHOUT_SRCS", "ANDROID_LIBRARY_RESOURCES_WITHOUT_SRCS_GENERATOR_FUNCTIONS") +load("@rules_android//rules/acls:android_lint_rollout.bzl", "ANDROID_LINT_ROLLOUT") +load("@rules_android//rules/acls:android_build_stamping_rollout.bzl", "ANDROID_BUILD_STAMPING_FALLBACK", "ANDROID_BUILD_STAMPING_ROLLOUT") +load("@rules_android//rules/acls:b122039567.bzl", "B122039567") +load("@rules_android//rules/acls:b123854163.bzl", "B123854163") +load("@rules_android//rules/acls:dex2oat_opts.bzl", "CAN_USE_DEX2OAT_OPTIONS") +load("@rules_android//rules/acls:fix_application_id.bzl", "FIX_APPLICATION_ID_FALLBACK", "FIX_APPLICATION_ID_ROLLOUT") +load("@rules_android//rules/acls:fix_export_exporting_rollout.bzl", "FIX_EXPORT_EXPORTING_FALLBACK", "FIX_EXPORT_EXPORTING_ROLLOUT") +load("@rules_android//rules/acls:fix_resource_transitivity_rollout.bzl", "FIX_RESOURCE_TRANSITIVITY_FALLBACK", "FIX_RESOURCE_TRANSITIVITY_ROLLOUT") +load("@rules_android//rules/acls:host_dex2oat_rollout.bzl", "AIT_USE_HOST_DEX2OAT_ROLLOUT", "AIT_USE_HOST_DEX2OAT_ROLLOUT_FALLBACK") +load("@rules_android//rules/acls:install_apps_in_data.bzl", "INSTALL_APPS_IN_DATA") +load("@rules_android//rules/acls:local_test_multi_proto.bzl", "LOCAL_TEST_MULTI_PROTO_PKG") +load("@rules_android//rules/acls:local_test_rollout.bzl", "LOCAL_TEST_FALLBACK", "LOCAL_TEST_ROLLOUT") +load("@rules_android//rules/acls:local_test_starlark_resources.bzl", "LOCAL_TEST_STARLARK_RESOURCES_FALLBACK", "LOCAL_TEST_STARLARK_RESOURCES_ROLLOUT") +load("@rules_android//rules/acls:nitrogen_test_runner_rollout.bzl", "NITROGEN_AT_TEST_RUNNER_ROLLOUT", "NITROGEN_TEST_RUNNER_FALLBACK", "NITROGEN_TEST_RUNNER_ROLLOUT") +load("@rules_android//rules/acls:android_test_platform_rollout.bzl", "ANDROID_TEST_PLATFORM_FALLBACK", "ANDROID_TEST_PLATFORM_ROLLOUT") +load("@rules_android//rules/acls:sourceless_binary_rollout.bzl", "SOURCELESS_BINARY_FALLBACK", "SOURCELESS_BINARY_ROLLOUT") +load("@rules_android//rules/acls:test_to_instrument_test_rollout.bzl", "TEST_TO_INSTRUMENT_TEST_FALLBACK", "TEST_TO_INSTRUMENT_TEST_ROLLOUT") +load( + "@rules_android//rules/acls:partial_jetification_targets.bzl", + "PARTIAL_JETIFICATION_TARGETS_FALLBACK", + "PARTIAL_JETIFICATION_TARGETS_ROLLOUT", +) +load("@rules_android//rules/acls:kt_android_library_rollout.bzl", "KT_ANDROID_LIBRARY_FALLBACK", "KT_ANDROID_LIBRARY_ROLLOUT") + +def _in_aar_import_deps_checker(fqn): + return not _matches(fqn, AAR_IMPORT_DEPS_CHECKER_FALLBACK_DICT) and _matches(fqn, AAR_IMPORT_DEPS_CHECKER_ROLLOUT_DICT) + +def _in_aar_import_explicit_exports_manifest(fqn): + return _matches(fqn, AAR_IMPORT_EXPLICIT_EXPORTS_MANIFEST_DICT) + +def _in_aar_import_exports_r_java(fqn): + return _matches(fqn, AAR_IMPORT_EXPORTS_R_JAVA_DICT) + +def _in_aar_import_pkg_check(fqn): + return not _matches(fqn, AAR_IMPORT_PKG_CHECK_FALLBACK_DICT) and _matches(fqn, AAR_IMPORT_PKG_CHECK_ROLLOUT_DICT) + +def _in_aar_propagate_resources(fqn): + return not _matches(fqn, AAR_PROPAGATE_RESOURCES_FALLBACK_DICT) and _matches(fqn, AAR_PROPAGATE_RESOURCES_ROLLOUT_DICT) + +def _in_ait_virtual_device(fqn): + return not _matches(fqn, AIT_VIRTUAL_DEVICE_FALLBACK_DICT) and _matches(fqn, AIT_VIRTUAL_DEVICE_ROLLOUT_DICT) + +def _in_android_archive_dogfood(fqn): + return _matches(fqn, ANDROID_ARCHIVE_DOGFOOD_DICT) + +def _in_android_device_plugin_rollout(fqn): + return not _matches(fqn, ANDROID_DEVICE_PLUGIN_FALLBACK_DICT) and _matches(fqn, ANDROID_DEVICE_PLUGIN_ROLLOUT_DICT) + +def _in_android_instrumentation_binary_starlark_resources(fqn): + return not _matches(fqn, ANDROID_INSTRUMENTATION_BINARY_STARLARK_RESOURCES_FALLBACK_DICT) and _matches(fqn, ANDROID_INSTRUMENTATION_BINARY_STARLARK_RESOURCES_ROLLOUT_DICT) + +def _in_android_feature_splits_dogfood(fqn): + return _matches(fqn, ANDROID_FEATURE_SPLITS_DOGFOOD_DICT) + +def _in_android_lint_rollout(fqn): + return _matches(fqn, ANDROID_LINT_ROLLOUT_DICT) + +def _in_android_build_stamping_rollout(fqn): + return not _matches(fqn, ANDROID_BUILD_STAMPING_FALLBACK_DICT) and _matches(fqn, ANDROID_BUILD_STAMPING_ROLLOUT_DICT) + +def _in_android_test_lockdown_allowlist(fqn, generator): + return _matches(fqn, ANDROID_TEST_LOCKDOWN_TARGETS_DICT) or generator in ANDROID_TEST_LOCKDOWN_GENERATOR_FUNCTIONS_DICT + +def _in_b122039567(fqn): + return _matches(fqn, B122039567_DICT) + +def _in_b123854163(fqn): + return _matches(fqn, B123854163_DICT) + +def _in_android_library_implicit_exports(fqn): + return _matches(fqn, ANDROID_LIBRARY_IMPLICIT_EXPORTS_DICT) + +def _in_android_library_implicit_exports_generator_functions(gfn): + return gfn in ANDROID_LIBRARY_IMPLICIT_EXPORTS_GENERATOR_FUNCTIONS_DICT + +def _in_android_library_resources_without_srcs(fqn): + return _matches(fqn, ANDROID_LIBRARY_RESOURCES_WITHOUT_SRCS_DICT) + +def _in_android_library_resources_without_srcs_generator_functions(gfn): + return gfn in ANDROID_LIBRARY_RESOURCES_WITHOUT_SRCS_GENERATOR_FUNCTIONS_DICT + +def _in_app_installation_snapshot(fqn): + return not _matches(fqn, APP_INSTALLATION_SNAPSHOT_FALLBACK_DICT) and _matches(fqn, APP_INSTALLATION_SNAPSHOT_DICT) + +def _in_dex2oat_opts(fqn): + return _matches(fqn, CAN_USE_DEX2OAT_OPTIONS_DICT) + +def _in_fix_application_id(fqn): + return not _matches(fqn, FIX_APPLICATION_ID_FALLBACK_DICT) and _matches(fqn, FIX_APPLICATION_ID_ROLLOUT_DICT) + +def _in_fix_export_exporting_rollout(fqn): + return not _matches(fqn, FIX_EXPORT_EXPORTING_FALLBACK_DICT) and _matches(fqn, FIX_EXPORT_EXPORTING_ROLLOUT_DICT) + +def _in_fix_resource_transivity_rollout(fqn): + return not _matches(fqn, FIX_RESOURCE_TRANSIVITY_FALLBACK_DICT) and _matches(fqn, FIX_RESOURCE_TRANSIVITY_ROLLOUT_DICT) + +def _in_host_dex2oat_rollout(fqn): + return not _matches(fqn, AIT_USE_HOST_DEX2OAT_ROLLOUT_FALLBACK_DICT) and _matches(fqn, AIT_USE_HOST_DEX2OAT_ROLLOUT_DICT) + +def _in_install_apps_in_data(fqn): + return _matches(fqn, AIT_INSTALL_APPS_IN_DATA_DICT) + +def _in_local_test_multi_proto(fqn): + return _matches(fqn, LOCAL_TEST_MULTI_PROTO_PKG_DICT) + +def _in_local_test_rollout(fqn): + return not _matches(fqn, LOCAL_TEST_FALLBACK_DICT) and _matches(fqn, LOCAL_TEST_ROLLOUT_DICT) + +def _in_local_test_starlark_resources(fqn): + return not _matches(fqn, LOCAL_TEST_STARLARK_RESOURCES_FALLBACK_DICT) and _matches(fqn, LOCAL_TEST_STARLARK_RESOURCES_ROLLOUT_DICT) + +def _in_nitrogen_test_runner_rollout(fqn): + return not _matches(fqn, NITROGEN_TEST_RUNNER_FALLBACK_DICT) and _matches(fqn, NITROGEN_TEST_RUNNER_ROLLOUT_DICT) + +def _in_nitrogen_at_test_runner_rollout(fqn): + return not _matches(fqn, NITROGEN_TEST_RUNNER_FALLBACK_DICT) and _matches(fqn, NITROGEN_AT_TEST_RUNNER_ROLLOUT_DICT) + +def _in_android_test_platform_rollout(fqn): + return not _matches(fqn, ANDROID_TEST_PLATFORM_FALLBACK_DICT) and _matches(fqn, ANDROID_TEST_PLATFORM_ROLLOUT_DICT) + +def _in_sourceless_binary_rollout(fqn): + return not _matches(fqn, SOURCELESS_BINARY_FALLBACK_DICT) and _matches(fqn, SOURCELESS_BINARY_ROLLOUT_DICT) + +def _in_test_to_instrument_test_rollout(fqn): + return not _matches(fqn, TEST_TO_INSTRUMENT_TEST_FALLBACK_DICT) and _matches(fqn, TEST_TO_INSTRUMENT_TEST_ROLLOUT_DICT) + +def _in_allow_resource_conflicts(fqn): + return _matches(fqn, ALLOW_RESOURCE_CONFLICTS_DICT) + +def _in_partial_jetification_targets(fqn): + return not _matches(fqn, PARTIAL_JETIFICATION_TARGETS_FALLBACK_DICT) and _matches(fqn, PARTIAL_JETIFICATION_TARGETS_ROLLOUT_DICT) + +def _in_kt_android_library_rollout(fqn): + return not _matches(fqn, KT_ANDROID_LIBRARY_FALLBACK_DICT) and _matches(fqn, KT_ANDROID_LIBRARY_ROLLOUT_DICT) + +def _make_dict(lst): + """Do not use this method outside of this file.""" + return {t: True for t in lst} + +AAR_IMPORT_DEPS_CHECKER_FALLBACK_DICT = _make_dict(AAR_IMPORT_DEPS_CHECKER_FALLBACK) +AAR_IMPORT_DEPS_CHECKER_ROLLOUT_DICT = _make_dict(AAR_IMPORT_DEPS_CHECKER_ROLLOUT) +AAR_IMPORT_EXPLICIT_EXPORTS_MANIFEST_DICT = _make_dict(AAR_IMPORT_EXPLICIT_EXPORTS_MANIFEST) +AAR_IMPORT_EXPORTS_R_JAVA_DICT = _make_dict(AAR_IMPORT_EXPORTS_R_JAVA) +AAR_IMPORT_PKG_CHECK_FALLBACK_DICT = _make_dict(AAR_IMPORT_PKG_CHECK_FALLBACK) +AAR_IMPORT_PKG_CHECK_ROLLOUT_DICT = _make_dict(AAR_IMPORT_PKG_CHECK_ROLLOUT) +AAR_PROPAGATE_RESOURCES_FALLBACK_DICT = _make_dict(AAR_PROPAGATE_RESOURCES_FALLBACK) +AAR_PROPAGATE_RESOURCES_ROLLOUT_DICT = _make_dict(AAR_PROPAGATE_RESOURCES_ROLLOUT) +AIT_VIRTUAL_DEVICE_FALLBACK_DICT = _make_dict(AIT_VIRTUAL_DEVICE_FALLBACK) +AIT_VIRTUAL_DEVICE_ROLLOUT_DICT = _make_dict(AIT_VIRTUAL_DEVICE_ROLLOUT) +ANDROID_ARCHIVE_DOGFOOD_DICT = _make_dict(ANDROID_ARCHIVE_DOGFOOD) +ANDROID_DEVICE_PLUGIN_ROLLOUT_DICT = _make_dict(ANDROID_DEVICE_PLUGIN_ROLLOUT) +ANDROID_DEVICE_PLUGIN_FALLBACK_DICT = _make_dict(ANDROID_DEVICE_PLUGIN_FALLBACK) +ANDROID_INSTRUMENTATION_BINARY_STARLARK_RESOURCES_ROLLOUT_DICT = _make_dict(ANDROID_INSTRUMENTATION_BINARY_STARLARK_RESOURCES_ROLLOUT) +ANDROID_INSTRUMENTATION_BINARY_STARLARK_RESOURCES_FALLBACK_DICT = _make_dict(ANDROID_INSTRUMENTATION_BINARY_STARLARK_RESOURCES_FALLBACK) +ANDROID_FEATURE_SPLITS_DOGFOOD_DICT = _make_dict(ANDROID_FEATURE_SPLITS_DOGFOOD) +ANDROID_LIBRARY_IMPLICIT_EXPORTS_DICT = _make_dict(ANDROID_LIBRARY_IMPLICIT_EXPORTS) +ANDROID_LIBRARY_IMPLICIT_EXPORTS_GENERATOR_FUNCTIONS_DICT = _make_dict(ANDROID_LIBRARY_IMPLICIT_EXPORTS_GENERATOR_FUNCTIONS) +ANDROID_LIBRARY_RESOURCES_WITHOUT_SRCS_DICT = _make_dict(ANDROID_LIBRARY_RESOURCES_WITHOUT_SRCS) +ANDROID_LIBRARY_RESOURCES_WITHOUT_SRCS_GENERATOR_FUNCTIONS_DICT = _make_dict(ANDROID_LIBRARY_RESOURCES_WITHOUT_SRCS_GENERATOR_FUNCTIONS) +ANDROID_LINT_ROLLOUT_DICT = _make_dict(ANDROID_LINT_ROLLOUT) +ANDROID_BUILD_STAMPING_ROLLOUT_DICT = _make_dict(ANDROID_BUILD_STAMPING_ROLLOUT) +ANDROID_BUILD_STAMPING_FALLBACK_DICT = _make_dict(ANDROID_BUILD_STAMPING_FALLBACK) +ANDROID_TEST_LOCKDOWN_GENERATOR_FUNCTIONS_DICT = _make_dict(ANDROID_TEST_LOCKDOWN_GENERATOR_FUNCTIONS) +ANDROID_TEST_LOCKDOWN_TARGETS_DICT = _make_dict(ANDROID_TEST_LOCKDOWN_TARGETS) +APP_INSTALLATION_SNAPSHOT_DICT = _make_dict(APP_INSTALLATION_SNAPSHOT) +APP_INSTALLATION_SNAPSHOT_FALLBACK_DICT = _make_dict(APP_INSTALLATION_SNAPSHOT_FALLBACK) +B122039567_DICT = _make_dict(B122039567) +B123854163_DICT = _make_dict(B123854163) +CAN_USE_DEX2OAT_OPTIONS_DICT = _make_dict(CAN_USE_DEX2OAT_OPTIONS) +FIX_APPLICATION_ID_FALLBACK_DICT = _make_dict(FIX_APPLICATION_ID_FALLBACK) +FIX_APPLICATION_ID_ROLLOUT_DICT = _make_dict(FIX_APPLICATION_ID_ROLLOUT) +FIX_RESOURCE_TRANSIVITY_FALLBACK_DICT = _make_dict(FIX_RESOURCE_TRANSITIVITY_FALLBACK) +FIX_RESOURCE_TRANSIVITY_ROLLOUT_DICT = _make_dict(FIX_RESOURCE_TRANSITIVITY_ROLLOUT) +FIX_EXPORT_EXPORTING_FALLBACK_DICT = _make_dict(FIX_EXPORT_EXPORTING_FALLBACK) +FIX_EXPORT_EXPORTING_ROLLOUT_DICT = _make_dict(FIX_EXPORT_EXPORTING_ROLLOUT) +AIT_USE_HOST_DEX2OAT_ROLLOUT_DICT = _make_dict(AIT_USE_HOST_DEX2OAT_ROLLOUT) +AIT_USE_HOST_DEX2OAT_ROLLOUT_FALLBACK_DICT = _make_dict(AIT_USE_HOST_DEX2OAT_ROLLOUT_FALLBACK) +AIT_INSTALL_APPS_IN_DATA_DICT = _make_dict(INSTALL_APPS_IN_DATA) +LOCAL_TEST_MULTI_PROTO_PKG_DICT = _make_dict(LOCAL_TEST_MULTI_PROTO_PKG) +LOCAL_TEST_FALLBACK_DICT = _make_dict(LOCAL_TEST_FALLBACK) +LOCAL_TEST_ROLLOUT_DICT = _make_dict(LOCAL_TEST_ROLLOUT) +LOCAL_TEST_STARLARK_RESOURCES_FALLBACK_DICT = _make_dict(LOCAL_TEST_STARLARK_RESOURCES_FALLBACK) +LOCAL_TEST_STARLARK_RESOURCES_ROLLOUT_DICT = _make_dict(LOCAL_TEST_STARLARK_RESOURCES_ROLLOUT) +NITROGEN_TEST_RUNNER_FALLBACK_DICT = _make_dict(NITROGEN_TEST_RUNNER_FALLBACK) +NITROGEN_TEST_RUNNER_ROLLOUT_DICT = _make_dict(NITROGEN_TEST_RUNNER_ROLLOUT) +NITROGEN_AT_TEST_RUNNER_ROLLOUT_DICT = _make_dict(NITROGEN_AT_TEST_RUNNER_ROLLOUT) +ANDROID_TEST_PLATFORM_FALLBACK_DICT = _make_dict(ANDROID_TEST_PLATFORM_FALLBACK) +ANDROID_TEST_PLATFORM_ROLLOUT_DICT = _make_dict(ANDROID_TEST_PLATFORM_ROLLOUT) +SOURCELESS_BINARY_FALLBACK_DICT = _make_dict(SOURCELESS_BINARY_FALLBACK) +SOURCELESS_BINARY_ROLLOUT_DICT = _make_dict(SOURCELESS_BINARY_ROLLOUT) +TEST_TO_INSTRUMENT_TEST_FALLBACK_DICT = _make_dict(TEST_TO_INSTRUMENT_TEST_FALLBACK) +TEST_TO_INSTRUMENT_TEST_ROLLOUT_DICT = _make_dict(TEST_TO_INSTRUMENT_TEST_ROLLOUT) +ALLOW_RESOURCE_CONFLICTS_DICT = _make_dict(ALLOW_RESOURCE_CONFLICTS) +PARTIAL_JETIFICATION_TARGETS_ROLLOUT_DICT = _make_dict(PARTIAL_JETIFICATION_TARGETS_ROLLOUT) +PARTIAL_JETIFICATION_TARGETS_FALLBACK_DICT = _make_dict(PARTIAL_JETIFICATION_TARGETS_FALLBACK) +KT_ANDROID_LIBRARY_ROLLOUT_DICT = _make_dict(KT_ANDROID_LIBRARY_ROLLOUT) +KT_ANDROID_LIBRARY_FALLBACK_DICT = _make_dict(KT_ANDROID_LIBRARY_FALLBACK) + +def _matches(fqn, dct): + if not fqn.startswith("//"): + fail("Fully qualified target should start with '//', got: " + fqn) + + if fqn in dct: + return True + + pkg_and_target = fqn.split(":") + if len(pkg_and_target) != 2: + fail("Expected fully qualified target, got: " + fqn) + pkg = pkg_and_target[0] + + if (pkg + ":__pkg__") in dct: + return True + + pkg = pkg.lstrip("//") + pkg_parts = pkg.split("/") + ancestor_pkg = "//" + + if (ancestor_pkg + ":__subpackages__") in dct: + return True + + for pkg_part in pkg_parts: + ancestor_pkg = ( + (ancestor_pkg + "/" + pkg_part) if ancestor_pkg != "//" else ("//" + pkg_part) + ) + if (ancestor_pkg + ":__subpackages__") in dct: + return True + + return False + +acls = struct( + in_aar_import_deps_checker = _in_aar_import_deps_checker, + in_aar_import_pkg_check = _in_aar_import_pkg_check, + in_aar_import_explicit_exports_manifest = _in_aar_import_explicit_exports_manifest, + in_aar_import_exports_r_java = _in_aar_import_exports_r_java, + in_aar_propagate_resources = _in_aar_propagate_resources, + in_ait_virtual_device = _in_ait_virtual_device, + in_b122039567 = _in_b122039567, + in_b123854163 = _in_b123854163, + in_android_archive_dogfood = _in_android_archive_dogfood, + in_android_device_plugin_rollout = _in_android_device_plugin_rollout, + in_android_instrumentation_binary_starlark_resources = _in_android_instrumentation_binary_starlark_resources, + in_android_feature_splits_dogfood = _in_android_feature_splits_dogfood, + in_android_library_implicit_exports = _in_android_library_implicit_exports, + in_android_library_implicit_exports_generator_functions = _in_android_library_implicit_exports_generator_functions, + in_android_library_resources_without_srcs = _in_android_library_resources_without_srcs, + in_android_library_resources_without_srcs_generator_functions = _in_android_library_resources_without_srcs_generator_functions, + in_android_lint_rollout = _in_android_lint_rollout, + in_android_build_stamping_rollout = _in_android_build_stamping_rollout, + in_android_test_lockdown_allowlist = _in_android_test_lockdown_allowlist, + in_app_installation_snapshot = _in_app_installation_snapshot, + in_dex2oat_opts = _in_dex2oat_opts, + in_fix_application_id = _in_fix_application_id, + in_fix_export_exporting_rollout = _in_fix_export_exporting_rollout, + in_fix_resource_transivity_rollout = _in_fix_resource_transivity_rollout, + in_host_dex2oat_rollout = _in_host_dex2oat_rollout, + in_install_apps_in_data = _in_install_apps_in_data, + in_local_test_multi_proto = _in_local_test_multi_proto, + in_local_test_rollout = _in_local_test_rollout, + in_local_test_starlark_resources = _in_local_test_starlark_resources, + in_nitrogen_test_runner_rollout = _in_nitrogen_test_runner_rollout, + in_nitrogen_at_test_runner_rollout = _in_nitrogen_at_test_runner_rollout, + in_android_test_platform_rollout = _in_android_test_platform_rollout, + in_sourceless_binary_rollout = _in_sourceless_binary_rollout, + in_test_to_instrument_test_rollout = _in_test_to_instrument_test_rollout, + in_allow_resource_conflicts = _in_allow_resource_conflicts, + in_partial_jetification_targets = _in_partial_jetification_targets, + in_kt_android_library_rollout = _in_kt_android_library_rollout, +) + +# Visible for testing +testing = struct( + matches = _matches, + make_dict = _make_dict, +) diff --git a/rules/acls/BUILD b/rules/acls/BUILD new file mode 100644 index 0000000..3c45ae3 --- /dev/null +++ b/rules/acls/BUILD @@ -0,0 +1,6 @@ +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + +bzl_library( + name = "bzl", + srcs = glob(["*.bzl"]), +) diff --git a/rules/acls/aar_import_deps_checker.bzl b/rules/acls/aar_import_deps_checker.bzl new file mode 100644 index 0000000..dabfd31 --- /dev/null +++ b/rules/acls/aar_import_deps_checker.bzl @@ -0,0 +1,27 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allowlist to run ImportDepsChecker on aar_import. + +See b/148478031 for context. +""" + +# keep sorted +AAR_IMPORT_DEPS_CHECKER_ROLLOUT = [ + "//:__subpackages__", +] + +# keep sorted +AAR_IMPORT_DEPS_CHECKER_FALLBACK = [ +] diff --git a/rules/acls/aar_import_explicit_exports_manifest.bzl b/rules/acls/aar_import_explicit_exports_manifest.bzl new file mode 100644 index 0000000..fb3a0b9 --- /dev/null +++ b/rules/acls/aar_import_explicit_exports_manifest.bzl @@ -0,0 +1,19 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for aar_import rule to explcitly set exports_manifest.""" + +# keep sorted +AAR_IMPORT_EXPLICIT_EXPORTS_MANIFEST = [ +] diff --git a/rules/acls/aar_import_exports_r_java.bzl b/rules/acls/aar_import_exports_r_java.bzl new file mode 100644 index 0000000..c0a07a4 --- /dev/null +++ b/rules/acls/aar_import_exports_r_java.bzl @@ -0,0 +1,19 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for aar_import rule to export the R.java.""" + +# keep sorted +AAR_IMPORT_EXPORTS_R_JAVA = [ +] diff --git a/rules/acls/aar_import_package_check.bzl b/rules/acls/aar_import_package_check.bzl new file mode 100644 index 0000000..54b2b51 --- /dev/null +++ b/rules/acls/aar_import_package_check.bzl @@ -0,0 +1,21 @@ +# Copyright 2021 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for checking the package value with the manifest.""" +AAR_IMPORT_PKG_CHECK_ROLLOUT = [ + "//:__subpackages__", +] + +AAR_IMPORT_PKG_CHECK_FALLBACK = [ +] diff --git a/rules/acls/aar_propagate_resources.bzl b/rules/acls/aar_propagate_resources.bzl new file mode 100644 index 0000000..48ab3ba --- /dev/null +++ b/rules/acls/aar_propagate_resources.bzl @@ -0,0 +1,24 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allowlist for propagating resources and assets from aar_import (b/138322659).""" + +# keep sorted +AAR_PROPAGATE_RESOURCES_ROLLOUT = [ + "//:__subpackages__", +] + +# keep sorted +AAR_PROPAGATE_RESOURCES_FALLBACK = [ +] diff --git a/rules/acls/ait_install_snapshots.bzl b/rules/acls/ait_install_snapshots.bzl new file mode 100644 index 0000000..ff11e64 --- /dev/null +++ b/rules/acls/ait_install_snapshots.bzl @@ -0,0 +1,23 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Packages in this list will use devices with app installation snapshots.""" + +# keep sorted +APP_INSTALLATION_SNAPSHOT = [ +] + +# keep sorted +APP_INSTALLATION_SNAPSHOT_FALLBACK = [ +] diff --git a/rules/acls/ait_virtual_device.bzl b/rules/acls/ait_virtual_device.bzl new file mode 100644 index 0000000..f5ec1b6 --- /dev/null +++ b/rules/acls/ait_virtual_device.bzl @@ -0,0 +1,21 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for switching to virtual_device in android_instrumentation_test.""" +AIT_VIRTUAL_DEVICE_ROLLOUT = [ + "//:__subpackages__", +] + +AIT_VIRTUAL_DEVICE_FALLBACK = [ +] diff --git a/rules/acls/allow_resource_conflicts.bzl b/rules/acls/allow_resource_conflicts.bzl new file mode 100644 index 0000000..d4f9742 --- /dev/null +++ b/rules/acls/allow_resource_conflicts.bzl @@ -0,0 +1,20 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" Packages of android_binary, android_test, and android_local_test targets that are allowed to contain resource conflicts. + +See b/125484033. +""" + +ALLOW_RESOURCE_CONFLICTS = [] diff --git a/rules/acls/android_archive_dogfood.bzl b/rules/acls/android_archive_dogfood.bzl new file mode 100644 index 0000000..2320db3 --- /dev/null +++ b/rules/acls/android_archive_dogfood.bzl @@ -0,0 +1,20 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allowlist for targets able to use the android_archive rule.""" + +# keep sorted +ANDROID_ARCHIVE_DOGFOOD = [ + "//:__subpackages__", +] diff --git a/rules/acls/android_binary_starlark_resources.bzl b/rules/acls/android_binary_starlark_resources.bzl new file mode 100644 index 0000000..0291cb6 --- /dev/null +++ b/rules/acls/android_binary_starlark_resources.bzl @@ -0,0 +1,22 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for rollout of Starlark resource processing pipeline in android_binary.""" + +ANDROID_BINARY_STARLARK_RESOURCES_ROLLOUT = [ + "//:__subpackages__", +] + +ANDROID_BINARY_STARLARK_RESOURCES_FALLBACK = [ +] diff --git a/rules/acls/android_build_stamping_rollout.bzl b/rules/acls/android_build_stamping_rollout.bzl new file mode 100644 index 0000000..5b1169a --- /dev/null +++ b/rules/acls/android_build_stamping_rollout.bzl @@ -0,0 +1,22 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for build stamping in the Android Rules.""" + +# keep sorted +ANDROID_BUILD_STAMPING_ROLLOUT = [ +] + +# keep sorted +ANDROID_BUILD_STAMPING_FALLBACK = [] diff --git a/rules/acls/android_device_plugin_rollout.bzl b/rules/acls/android_device_plugin_rollout.bzl new file mode 100644 index 0000000..310da7d --- /dev/null +++ b/rules/acls/android_device_plugin_rollout.bzl @@ -0,0 +1,26 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow and fallback lists for ATP Device Plugin rollout.""" + +# Targets for ATP Device Plugin Rollout +ANDROID_DEVICE_PLUGIN_ROLLOUT = [ + "//:__subpackages__", +] + +_READY_TO_ROLLOUT_IN_NEXT_RELEASE = [ +] + +ANDROID_DEVICE_PLUGIN_FALLBACK = [ +] + _READY_TO_ROLLOUT_IN_NEXT_RELEASE diff --git a/rules/acls/android_feature_splits_dogfood.bzl b/rules/acls/android_feature_splits_dogfood.bzl new file mode 100644 index 0000000..159ef42 --- /dev/null +++ b/rules/acls/android_feature_splits_dogfood.bzl @@ -0,0 +1,24 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allowlist for packages able to use Android feature splits. + +Dynamic feature splits are still in development and at this stage are only suitable for use +in an experimental capacity. +""" + +# keep sorted +ANDROID_FEATURE_SPLITS_DOGFOOD = [ + "//:__subpackages__", +] diff --git a/rules/acls/android_instrumentation_binary_starlark_resources.bzl b/rules/acls/android_instrumentation_binary_starlark_resources.bzl new file mode 100644 index 0000000..0e55315 --- /dev/null +++ b/rules/acls/android_instrumentation_binary_starlark_resources.bzl @@ -0,0 +1,22 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for rollout of Starlark resource processing pipeline in instrumentation binaries.""" + +ANDROID_INSTRUMENTATION_BINARY_STARLARK_RESOURCES_ROLLOUT = [ + "//:__subpackages__", +] + +ANDROID_INSTRUMENTATION_BINARY_STARLARK_RESOURCES_FALLBACK = [ +] diff --git a/rules/acls/android_library_implicit_exports.bzl b/rules/acls/android_library_implicit_exports.bzl new file mode 100644 index 0000000..521c2ac --- /dev/null +++ b/rules/acls/android_library_implicit_exports.bzl @@ -0,0 +1,23 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for b/144163743 - deprecated implicit exports.""" + +# These macros can create android_library targets with deps and no srcs with no way for +# their users to control this. +ANDROID_LIBRARY_IMPLICIT_EXPORTS_GENERATOR_FUNCTIONS = [ +] + +ANDROID_LIBRARY_IMPLICIT_EXPORTS = [ +] diff --git a/rules/acls/android_library_resources_without_srcs.bzl b/rules/acls/android_library_resources_without_srcs.bzl new file mode 100644 index 0000000..b376e30 --- /dev/null +++ b/rules/acls/android_library_resources_without_srcs.bzl @@ -0,0 +1,19 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for b/144163743, allowing implicit export of deps when resources and deps are present.""" + +ANDROID_LIBRARY_RESOURCES_WITHOUT_SRCS_GENERATOR_FUNCTIONS = [] + +ANDROID_LIBRARY_RESOURCES_WITHOUT_SRCS = ["//:__subpackages__"] diff --git a/rules/acls/android_library_starlark_resources.bzl b/rules/acls/android_library_starlark_resources.bzl new file mode 100644 index 0000000..46e68a5 --- /dev/null +++ b/rules/acls/android_library_starlark_resources.bzl @@ -0,0 +1,23 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for diff test for android_library native resource processing vs Starlark processed resources.""" + +# keep sorted +ANDROID_LIBRARY_STARLARK_RESOURCES_ROLLOUT = [ + "//:__subpackages__", +] + +ANDROID_LIBRARY_STARLARK_RESOURCES_FALLBACK = [ +] diff --git a/rules/acls/android_lint_rollout.bzl b/rules/acls/android_lint_rollout.bzl new file mode 100644 index 0000000..65f9ff7 --- /dev/null +++ b/rules/acls/android_lint_rollout.bzl @@ -0,0 +1,19 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for Android Lint in the Android Rules.""" + +# keep sorted +ANDROID_LINT_ROLLOUT = [ +] diff --git a/rules/acls/android_test_lockdown.bzl b/rules/acls/android_test_lockdown.bzl new file mode 100644 index 0000000..8dce844 --- /dev/null +++ b/rules/acls/android_test_lockdown.bzl @@ -0,0 +1,21 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allowlist of macro and targets that are allowed to use android_test.""" + +ANDROID_TEST_LOCKDOWN_GENERATOR_FUNCTIONS = [ +] + +ANDROID_TEST_LOCKDOWN_TARGETS = [ +] diff --git a/rules/acls/android_test_platform_rollout.bzl b/rules/acls/android_test_platform_rollout.bzl new file mode 100644 index 0000000..47b879e --- /dev/null +++ b/rules/acls/android_test_platform_rollout.bzl @@ -0,0 +1,26 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow and fallback lists for Android Test Platform rollout""" + +# Targets for Android Test Platform Rollout +ANDROID_TEST_PLATFORM_ROLLOUT = [ + "//:__subpackages__", +] + +_READY_TO_ROLLOUT_IN_NEXT_RELEASE = [ +] + +ANDROID_TEST_PLATFORM_FALLBACK = [ +] + _READY_TO_ROLLOUT_IN_NEXT_RELEASE diff --git a/rules/acls/android_test_starlark_resources.bzl b/rules/acls/android_test_starlark_resources.bzl new file mode 100644 index 0000000..2510931 --- /dev/null +++ b/rules/acls/android_test_starlark_resources.bzl @@ -0,0 +1,17 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for diff test for android_test native vs Starlark processed resources.""" + +ANDROID_TEST_STARLARK_RESOURCES = [] diff --git a/rules/acls/b122039567.bzl b/rules/acls/b122039567.bzl new file mode 100644 index 0000000..907b08e --- /dev/null +++ b/rules/acls/b122039567.bzl @@ -0,0 +1,18 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for b/122039567.""" + +B122039567 = [ +] diff --git a/rules/acls/b123854163.bzl b/rules/acls/b123854163.bzl new file mode 100644 index 0000000..d23efb5 --- /dev/null +++ b/rules/acls/b123854163.bzl @@ -0,0 +1,18 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for b/123854163.""" + +B123854163 = [ +] diff --git a/rules/acls/dex2oat_opts.bzl b/rules/acls/dex2oat_opts.bzl new file mode 100644 index 0000000..b935a1f --- /dev/null +++ b/rules/acls/dex2oat_opts.bzl @@ -0,0 +1,19 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Packages in this list are allowed to specify custom dex2oat options.""" + +# keep sorted +CAN_USE_DEX2OAT_OPTIONS = [ +] diff --git a/rules/acls/fix_application_id.bzl b/rules/acls/fix_application_id.bzl new file mode 100644 index 0000000..41c18b7 --- /dev/null +++ b/rules/acls/fix_application_id.bzl @@ -0,0 +1,27 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allowlist for fixing the implicit application ID in manifest processing. + +See b/111923269 for context. +""" + +# keep sorted +FIX_APPLICATION_ID_ROLLOUT = [ + "//:__subpackages__", +] + +# keep sorted +FIX_APPLICATION_ID_FALLBACK = [ +] diff --git a/rules/acls/fix_export_exporting_rollout.bzl b/rules/acls/fix_export_exporting_rollout.bzl new file mode 100644 index 0000000..cb68adf --- /dev/null +++ b/rules/acls/fix_export_exporting_rollout.bzl @@ -0,0 +1,24 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allowlist for making exports actually be exported.""" + +# keep sorted +FIX_EXPORT_EXPORTING_ROLLOUT = [ + "//:__subpackages__", +] + +# keep sorted +FIX_EXPORT_EXPORTING_FALLBACK = [ +] diff --git a/rules/acls/fix_resource_transitivity_rollout.bzl b/rules/acls/fix_resource_transitivity_rollout.bzl new file mode 100644 index 0000000..bdde15f --- /dev/null +++ b/rules/acls/fix_resource_transitivity_rollout.bzl @@ -0,0 +1,22 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allowlist for fixing resource dependencies passing through rules with no manifest.""" + +# keep sorted +FIX_RESOURCE_TRANSITIVITY_ROLLOUT = [ + "//:__subpackages__", +] + +FIX_RESOURCE_TRANSITIVITY_FALLBACK = [] diff --git a/rules/acls/host_dex2oat_rollout.bzl b/rules/acls/host_dex2oat_rollout.bzl new file mode 100644 index 0000000..b3da4ee --- /dev/null +++ b/rules/acls/host_dex2oat_rollout.bzl @@ -0,0 +1,27 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Whitelist for using host dex2oat with android_instrumentation_test.""" + +ANDROID_TEST_HOST_DEX2OAT_ROLLOUT = [ + "//...", +] + +# keep sorted +AIT_USE_HOST_DEX2OAT_ROLLOUT = [ + "//:__subpackages__", +] + +AIT_USE_HOST_DEX2OAT_ROLLOUT_FALLBACK = [ +] diff --git a/rules/acls/install_apps_in_data.bzl b/rules/acls/install_apps_in_data.bzl new file mode 100644 index 0000000..58994bf --- /dev/null +++ b/rules/acls/install_apps_in_data.bzl @@ -0,0 +1,18 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Whitelist for using installing apps in data attr in android_instrumentation_test.""" + +INSTALL_APPS_IN_DATA = [ +] diff --git a/rules/acls/kt_android_library_rollout.bzl b/rules/acls/kt_android_library_rollout.bzl new file mode 100644 index 0000000..50c43a4 --- /dev/null +++ b/rules/acls/kt_android_library_rollout.bzl @@ -0,0 +1,24 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list to rollout the kt_android_library rule from rules_android.""" + +# keep sorted +KT_ANDROID_LIBRARY_ROLLOUT = [ + "//:__subpackages__", +] + +# keep sorted +KT_ANDROID_LIBRARY_FALLBACK = [ +] diff --git a/rules/acls/library_rollout.bzl b/rules/acls/library_rollout.bzl new file mode 100644 index 0000000..cb42a88 --- /dev/null +++ b/rules/acls/library_rollout.bzl @@ -0,0 +1,23 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for Starlark android_library rollout""" + +LIBRARY_ROLLOUT = [ + # keep sorted + "//:__subpackages__", +] + +LIBRARY_FALLBACK = [ +] diff --git a/rules/acls/library_rollout_override.bzl b/rules/acls/library_rollout_override.bzl new file mode 100644 index 0000000..805bf0f --- /dev/null +++ b/rules/acls/library_rollout_override.bzl @@ -0,0 +1,17 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A Starlark android_library rollout override switch, for testing.""" + +LIBRARY_ROLLOUT_OVERRIDE = None # A tristate: None, True or False. diff --git a/rules/acls/local_test_multi_proto.bzl b/rules/acls/local_test_multi_proto.bzl new file mode 100644 index 0000000..e0bc06b --- /dev/null +++ b/rules/acls/local_test_multi_proto.bzl @@ -0,0 +1,23 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allowlist for android_local_test targets allowed to depend on java_proto_library. + +See b/120162253 for context. +""" + +LOCAL_TEST_MULTI_PROTO = [ +] + +LOCAL_TEST_MULTI_PROTO_PKG = [x + ":__pkg__" for x in LOCAL_TEST_MULTI_PROTO] diff --git a/rules/acls/local_test_rollout.bzl b/rules/acls/local_test_rollout.bzl new file mode 100644 index 0000000..889d82c --- /dev/null +++ b/rules/acls/local_test_rollout.bzl @@ -0,0 +1,22 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow and fallback lists for Starlark android_local_test rollout""" + +LOCAL_TEST_ROLLOUT = [ + "//:__subpackages__", +] + +LOCAL_TEST_FALLBACK = [ +] diff --git a/rules/acls/local_test_starlark_resources.bzl b/rules/acls/local_test_starlark_resources.bzl new file mode 100644 index 0000000..19c1777 --- /dev/null +++ b/rules/acls/local_test_starlark_resources.bzl @@ -0,0 +1,22 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for android_local_test Starlark processed resources.""" + +LOCAL_TEST_STARLARK_RESOURCES_ROLLOUT = [ +] + +LOCAL_TEST_STARLARK_RESOURCES_FALLBACK = [ + "//:__subpackages__", +] diff --git a/rules/acls/nitrogen_test_runner_rollout.bzl b/rules/acls/nitrogen_test_runner_rollout.bzl new file mode 100644 index 0000000..891671e --- /dev/null +++ b/rules/acls/nitrogen_test_runner_rollout.bzl @@ -0,0 +1,28 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow and fallback lists for Nitrogen rollout""" + +# Nitrogen targets for android_instrumentation_test rollout +NITROGEN_TEST_RUNNER_ROLLOUT = [ + "//:__subpackages__", +] + +# Nitrogen targets for android_test rollout +NITROGEN_AT_TEST_RUNNER_ROLLOUT = [ + "//:__subpackages__", +] + +NITROGEN_TEST_RUNNER_FALLBACK = [ +] diff --git a/rules/acls/partial_jetification_targets.bzl b/rules/acls/partial_jetification_targets.bzl new file mode 100644 index 0000000..490c3ea --- /dev/null +++ b/rules/acls/partial_jetification_targets.bzl @@ -0,0 +1,20 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for targets or subsets of targets to partially jetify at build time""" + +PARTIAL_JETIFICATION_TARGETS_ROLLOUT = [ +] + +PARTIAL_JETIFICATION_TARGETS_FALLBACK = [] diff --git a/rules/acls/sourceless_binary_rollout.bzl b/rules/acls/sourceless_binary_rollout.bzl new file mode 100644 index 0000000..132ba10 --- /dev/null +++ b/rules/acls/sourceless_binary_rollout.bzl @@ -0,0 +1,21 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for sourceless android_binary rollout""" + +SOURCELESS_BINARY_ROLLOUT = [ +] + +SOURCELESS_BINARY_FALLBACK = [ +] diff --git a/rules/acls/starlark_resources_diff.bzl b/rules/acls/starlark_resources_diff.bzl new file mode 100644 index 0000000..ed7752e --- /dev/null +++ b/rules/acls/starlark_resources_diff.bzl @@ -0,0 +1,18 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for diff test for native vs Starlark resource processing pipelines.""" + +STARLARK_RESOURCES_DIFF = [ +] diff --git a/rules/acls/test_to_instrument_test_rollout.bzl b/rules/acls/test_to_instrument_test_rollout.bzl new file mode 100644 index 0000000..835880d --- /dev/null +++ b/rules/acls/test_to_instrument_test_rollout.bzl @@ -0,0 +1,21 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Allow list for android_test to android_instrumentation_test rollout""" + +TEST_TO_INSTRUMENT_TEST_ROLLOUT = [ +] + +TEST_TO_INSTRUMENT_TEST_FALLBACK = [ +] diff --git a/rules/android_binary.bzl b/rules/android_binary.bzl new file mode 100644 index 0000000..1760e75 --- /dev/null +++ b/rules/android_binary.bzl @@ -0,0 +1,42 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel rule for building an APK.""" + +load(":migration_tag_DONOTUSE.bzl", "add_migration_tag") +load("@rules_android//rules/android_packaged_resources:rule.bzl", "android_packaged_resources_macro") + +def android_binary(**attrs): + """Bazel android_binary rule. + + https://docs.bazel.build/versions/master/be/android.html#android_binary + + Args: + **attrs: Rule attributes + """ + packaged_resources_name = ":%s_RESOURCES_DO_NOT_USE" % attrs["name"] + android_packaged_resources_macro( + **dict( + attrs, + name = packaged_resources_name[1:], + visibility = ["//visibility:private"], + ) + ) + + attrs.pop("$enable_manifest_merging", None) + + native.android_binary( + application_resources = packaged_resources_name, + **add_migration_tag(attrs) + ) diff --git a/rules/android_library/BUILD b/rules/android_library/BUILD new file mode 100644 index 0000000..09ca5b8 --- /dev/null +++ b/rules/android_library/BUILD @@ -0,0 +1,21 @@ +# The android_library rule. + +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + +licenses(["notice"]) + +exports_files(["rule.bzl"]) + +filegroup( + name = "all_files", + srcs = glob(["**"]), +) + +bzl_library( + name = "bzl", + srcs = glob(["*.bzl"]), + deps = [ + "@rules_android//rules:common_bzl", + "@rules_android//rules/flags:bzl", + ], +) diff --git a/rules/android_library/attrs.bzl b/rules/android_library/attrs.bzl new file mode 100644 index 0000000..16a18e7 --- /dev/null +++ b/rules/android_library/attrs.bzl @@ -0,0 +1,73 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Attributes.""" + +load( + "@rules_android//rules:attrs.bzl", + _attrs = "attrs", +) + +ATTRS = _attrs.add( + dict( + deps = attr.label_list( + providers = [ + [CcInfo], + [JavaInfo], + ], + ), + enable_data_binding = attr.bool(default = False), + exported_plugins = attr.label_list( + allow_rules = [ + "java_plugin", + ], + cfg = "host", + ), + exports = attr.label_list( + providers = [ + [CcInfo], + [JavaInfo], + ], + ), + exports_manifest = + _attrs.tristate.create(default = _attrs.tristate.no), + idl_import_root = attr.string(), + idl_parcelables = attr.label_list(allow_files = [".aidl"]), + idl_preprocessed = attr.label_list(allow_files = [".aidl"]), + idl_srcs = attr.label_list(allow_files = [".aidl"]), + neverlink = attr.bool(default = False), + proguard_specs = attr.label_list(allow_files = True), + srcs = attr.label_list( + allow_files = [".java", ".srcjar"], + ), + # TODO(b/127517031): Remove these entries once fixed. + _defined_assets = attr.bool(default = False), + _defined_assets_dir = attr.bool(default = False), + _defined_idl_import_root = attr.bool(default = False), + _defined_idl_parcelables = attr.bool(default = False), + _defined_idl_srcs = attr.bool(default = False), + _defined_local_resources = attr.bool(default = False), + _java_toolchain = attr.label( + cfg = "host", + default = Label("//tools/jdk:toolchain_android_only"), + ), + # TODO(str): Remove when fully migrated to android_instrumentation_test + _android_test_migration = attr.bool(default = False), + _flags = attr.label( + default = "@rules_android//rules/flags", + ), + ), + _attrs.COMPILATION, + _attrs.DATA_CONTEXT, +) diff --git a/rules/android_library/impl.bzl b/rules/android_library/impl.bzl new file mode 100644 index 0000000..232899c --- /dev/null +++ b/rules/android_library/impl.bzl @@ -0,0 +1,534 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Implementation.""" + +load("@rules_android//rules:acls.bzl", "acls") +load("@rules_android//rules:attrs.bzl", _attrs = "attrs") +load("@rules_android//rules:common.bzl", _common = "common") +load("@rules_android//rules:data_binding.bzl", _data_binding = "data_binding") +load("@rules_android//rules:idl.bzl", _idl = "idl") +load("@rules_android//rules:intellij.bzl", _intellij = "intellij") +load("@rules_android//rules:java.bzl", _java = "java") +load( + "@rules_android//rules:processing_pipeline.bzl", + "ProviderInfo", + "processing_pipeline", +) +load("@rules_android//rules:proguard.bzl", _proguard = "proguard") +load("@rules_android//rules:resources.bzl", _resources = "resources") +load("@rules_android//rules:utils.bzl", "get_android_sdk", "get_android_toolchain", "log", "utils") +load("@rules_android//rules/flags:flags.bzl", _flags = "flags") + +_USES_DEPRECATED_IMPLICIT_EXPORT_ERROR = ( + "The android_library rule will be deprecating the use of deps to export " + + "targets implicitly. " + + "Please use android_library.exports to explicitly specify the exported " + + "targets of %s." +) + +_SRCS_CONTAIN_RESOURCE_LABEL_ERROR = ( + "The srcs attribute of an android_library rule should not contain label " + + "with resources %s" +) + +_IDL_IMPORT_ROOT_SET_WITHOUT_SRCS_OR_PARCELABLES_ERROR = ( + "The 'idl_import_root' attribute of the android_library rule was set, " + + "but neither 'idl_srcs' nor 'idl_parcelables' were specified." +) + +_IDL_SRC_FROM_DIFFERENT_PACKAGE_ERROR = ( + "Do not import '%s' directly. You should either move the file to this " + + "package or depend on an appropriate rule there." +) + +# Android library AAR context attributes. +_PROVIDERS = "providers" +_VALIDATION_OUTPUTS = "validation_outputs" + +_AARContextInfo = provider( + "Android library AAR context object", + fields = { + _PROVIDERS: "The list of all providers to propagate.", + _VALIDATION_OUTPUTS: "List of outputs given to OutputGroupInfo _validation group", + }, +) + +def _uses_deprecated_implicit_export(ctx): + if not ctx.attr.deps: + return False + return not (ctx.files.srcs or + ctx.files.idl_srcs or + ctx.attr._defined_assets or + ctx.files.resource_files or + ctx.attr.manifest) + +def _uses_resources_and_deps_without_srcs(ctx): + if not ctx.attr.deps: + return False + if not (ctx.attr._defined_assets or + ctx.files.resource_files or + ctx.attr.manifest): + return False + return not (ctx.files.srcs or ctx.files.idl_srcs) + +def _check_deps_without_java_srcs(ctx): + if not ctx.attr.deps or ctx.files.srcs or ctx.files.idl_srcs: + return False + gfn = getattr(ctx.attr, "generator_function", "") + if _uses_deprecated_implicit_export(ctx): + if (acls.in_android_library_implicit_exports_generator_functions(gfn) or + acls.in_android_library_implicit_exports(str(ctx.label))): + return True + else: + # TODO(b/144163743): add a test for this. + log.error(_USES_DEPRECATED_IMPLICIT_EXPORT_ERROR % ctx.label) + if _uses_resources_and_deps_without_srcs(ctx): + if (acls.in_android_library_resources_without_srcs_generator_functions(gfn) or + acls.in_android_library_resources_without_srcs(str(ctx.label))): + return True + return False + +def _validate_rule_context(ctx): + # Verify that idl_import_root is specified with idl_src or idl_parcelables. + if (ctx.attr._defined_idl_import_root and + not (ctx.attr._defined_idl_srcs or ctx.attr._defined_idl_parcelables)): + log.error(_IDL_IMPORT_ROOT_SET_WITHOUT_SRCS_OR_PARCELABLES_ERROR) + + # Verify that idl_srcs are not from another package. + for idl_src in ctx.attr.idl_srcs: + if ctx.label.package != idl_src.label.package: + log.error(_IDL_SRC_FROM_DIFFERENT_PACKAGE_ERROR % idl_src.label) + + return struct( + enable_deps_without_srcs = _check_deps_without_java_srcs(ctx), + ) + +def _exceptions_processor(ctx, **unused_ctxs): + return ProviderInfo( + name = "exceptions_ctx", + value = _validate_rule_context(ctx), + ) + +def _process_resources(ctx, java_package, **unused_ctxs): + # exports_manifest can be overridden by a bazel flag. + if ctx.attr.exports_manifest == _attrs.tristate.auto: + exports_manifest = ctx.fragments.android.get_exports_manifest_default + else: + exports_manifest = ctx.attr.exports_manifest == _attrs.tristate.yes + + # Process Android Resources + resources_ctx = _resources.process( + ctx, + manifest = ctx.file.manifest, + resource_files = ctx.attr.resource_files, + defined_assets = ctx.attr._defined_assets, + assets = ctx.attr.assets, + defined_assets_dir = ctx.attr._defined_assets_dir, + assets_dir = ctx.attr.assets_dir, + exports_manifest = exports_manifest, + java_package = java_package, + custom_package = ctx.attr.custom_package, + neverlink = ctx.attr.neverlink, + enable_data_binding = ctx.attr.enable_data_binding, + deps = ctx.attr.deps, + exports = ctx.attr.exports, + + # Processing behavior changing flags. + enable_res_v3 = _flags.get(ctx).android_enable_res_v3, + # TODO(b/144163743): remove fix_resource_transitivity, which was only added to emulate + # misbehavior on the Java side. + fix_resource_transitivity = bool(ctx.attr.srcs), + fix_export_exporting = acls.in_fix_export_exporting_rollout(str(ctx.label)), + android_test_migration = ctx.attr._android_test_migration, + + # Tool and Processing related inputs + aapt = get_android_toolchain(ctx).aapt2.files_to_run, + android_jar = get_android_sdk(ctx).android_jar, + android_kit = get_android_toolchain(ctx).android_kit.files_to_run, + busybox = get_android_toolchain(ctx).android_resources_busybox.files_to_run, + java_toolchain = _common.get_java_toolchain(ctx), + host_javabase = _common.get_host_javabase(ctx), + instrument_xslt = utils.only(get_android_toolchain(ctx).add_g3itr_xslt.files.to_list()), + res_v3_dummy_manifest = utils.only( + get_android_toolchain(ctx).res_v3_dummy_manifest.files.to_list(), + ), + res_v3_dummy_r_txt = utils.only( + get_android_toolchain(ctx).res_v3_dummy_r_txt.files.to_list(), + ), + xsltproc = get_android_toolchain(ctx).xsltproc_tool.files_to_run, + zip_tool = get_android_toolchain(ctx).zip_tool.files_to_run, + ) + + # TODO(b/139305816): Remove the ability for android_library to be added in + # the srcs attribute of another android_library. + if resources_ctx.defines_resources: + # Verify that srcs do no contain labels. + for src in ctx.attr.srcs: + if AndroidResourcesInfo in src: + log.error(_SRCS_CONTAIN_RESOURCE_LABEL_ERROR % + src[AndroidResourcesInfo].label) + + return ProviderInfo( + name = "resources_ctx", + value = resources_ctx, + ) + +def _process_idl(ctx, **unused_sub_ctxs): + return ProviderInfo( + name = "idl_ctx", + value = _idl.process( + ctx, + idl_srcs = ctx.files.idl_srcs, + idl_parcelables = ctx.files.idl_parcelables, + idl_import_root = + ctx.attr.idl_import_root if ctx.attr._defined_idl_import_root else None, + idl_preprocessed = ctx.files.idl_preprocessed, + deps = utils.collect_providers(AndroidIdlInfo, ctx.attr.deps), + exports = utils.collect_providers(AndroidIdlInfo, ctx.attr.exports), + aidl = get_android_sdk(ctx).aidl, + aidl_lib = get_android_sdk(ctx).aidl_lib, + aidl_framework = get_android_sdk(ctx).framework_aidl, + ), + ) + +def _process_data_binding(ctx, java_package, resources_ctx, **unused_sub_ctxs): + return ProviderInfo( + name = "db_ctx", + value = _data_binding.process( + ctx, + defines_resources = resources_ctx.defines_resources, + enable_data_binding = ctx.attr.enable_data_binding, + java_package = java_package, + deps = utils.collect_providers(DataBindingV2Info, ctx.attr.deps), + exports = utils.collect_providers(DataBindingV2Info, ctx.attr.exports), + data_binding_exec = get_android_toolchain(ctx).data_binding_exec.files_to_run, + data_binding_annotation_processor = + get_android_toolchain(ctx).data_binding_annotation_processor[JavaInfo], + data_binding_annotation_template = + utils.only(get_android_toolchain(ctx).data_binding_annotation_template.files.to_list()), + ), + ) + +def _process_proguard(ctx, idl_ctx, **unused_sub_ctxs): + return ProviderInfo( + name = "proguard_ctx", + value = _proguard.process( + ctx, + proguard_configs = ctx.files.proguard_specs, + proguard_spec_providers = utils.collect_providers( + ProguardSpecProvider, + ctx.attr.deps, + ctx.attr.exports, + ctx.attr.plugins, + ctx.attr.exported_plugins, + idl_ctx.idl_deps, + ), + proguard_allowlister = + get_android_toolchain(ctx).proguard_allowlister.files_to_run, + ), + ) + +def _process_jvm(ctx, exceptions_ctx, resources_ctx, idl_ctx, db_ctx, **unused_sub_ctxs): + java_info = _java.compile_android( + ctx, + ctx.outputs.lib_jar, + ctx.outputs.lib_src_jar, + srcs = ctx.files.srcs + idl_ctx.idl_java_srcs + db_ctx.java_srcs, + javac_opts = ctx.attr.javacopts + db_ctx.javac_opts, + r_java = resources_ctx.r_java, + deps = + utils.collect_providers(JavaInfo, ctx.attr.deps, idl_ctx.idl_deps), + exports = utils.collect_providers(JavaInfo, ctx.attr.exports), + plugins = ( + utils.collect_providers(JavaInfo, ctx.attr.plugins) + + db_ctx.java_plugins + ), + exported_plugins = utils.collect_providers( + JavaInfo, + ctx.attr.exported_plugins, + ), + annotation_processor_additional_outputs = ( + db_ctx.java_annotation_processor_additional_outputs + ), + annotation_processor_additional_inputs = ( + db_ctx.java_annotation_processor_additional_inputs + ), + enable_deps_without_srcs = exceptions_ctx.enable_deps_without_srcs, + neverlink = ctx.attr.neverlink, + strict_deps = "DEFAULT", + java_toolchain = _common.get_java_toolchain(ctx), + ) + + return ProviderInfo( + name = "jvm_ctx", + value = struct( + java_info = java_info, + providers = [java_info], + ), + ) + +def _process_aar(ctx, java_package, resources_ctx, proguard_ctx, **unused_ctx): + aar_ctx = { + _PROVIDERS: [], + _VALIDATION_OUTPUTS: [], + } + + starlark_aar = _resources.make_aar( + ctx, + manifest = resources_ctx.starlark_processed_manifest, + assets = ctx.files.assets, + assets_dir = ctx.attr.assets_dir, + resource_files = resources_ctx.starlark_processed_resources if not ctx.attr.neverlink else [], + class_jar = ctx.outputs.lib_jar, + r_txt = resources_ctx.starlark_r_txt, + proguard_specs = proguard_ctx.proguard_configs, + busybox = get_android_toolchain(ctx).android_resources_busybox.files_to_run, + host_javabase = _common.get_host_javabase(ctx), + ) + + # TODO(b/170409221): Clean this up once Starlark migration is complete. Create and propagate + # a native aar info provider with the Starlark artifacts to avoid breaking downstream + # targets. + if not ctx.attr.neverlink: + aar_ctx[_PROVIDERS].append(AndroidLibraryAarInfo( + aar = starlark_aar, + manifest = resources_ctx.starlark_processed_manifest, + aars_from_deps = utils.collect_providers( + AndroidLibraryAarInfo, + ctx.attr.deps, + ctx.attr.exports, + ), + defines_local_resources = resources_ctx.defines_resources, + )) + + return ProviderInfo( + name = "aar_ctx", + value = _AARContextInfo(**aar_ctx), + ) + +def _process_native(ctx, idl_ctx, **unused_ctx): + return ProviderInfo( + name = "native_ctx", + value = struct( + providers = [ + AndroidNativeLibsInfo( + depset( + transitive = [ + p.native_libs + for p in utils.collect_providers( + AndroidNativeLibsInfo, + ctx.attr.deps, + ctx.attr.exports, + ) + ], + order = "preorder", + ), + ), + AndroidCcLinkParamsInfo( + cc_common.merge_cc_infos( + cc_infos = [ + info.cc_info + for info in utils.collect_providers( + JavaCcLinkParamsInfo, + ctx.attr.deps, + ctx.attr.exports, + idl_ctx.idl_deps, + ) + ] + + [ + info.link_params + for info in utils.collect_providers( + AndroidCcLinkParamsInfo, + ctx.attr.deps, + ctx.attr.exports, + idl_ctx.idl_deps, + ) + ] + + utils.collect_providers( + CcInfo, + ctx.attr.deps, + ctx.attr.exports, + idl_ctx.idl_deps, + ), + ), + ), + ], + ), + ) + +def _process_intellij(ctx, java_package, resources_ctx, idl_ctx, jvm_ctx, **unused_sub_ctxs): + android_ide_info = _intellij.make_android_ide_info( + ctx, + java_package = java_package, + manifest = ctx.file.manifest, + defines_resources = resources_ctx.defines_resources, + merged_manifest = resources_ctx.merged_manifest, + resources_apk = resources_ctx.resources_apk, + r_jar = utils.only(resources_ctx.r_java.outputs.jars) if resources_ctx.r_java else None, + idl_import_root = idl_ctx.idl_import_root, + idl_srcs = idl_ctx.idl_srcs, + idl_java_srcs = idl_ctx.idl_java_srcs, + java_info = jvm_ctx.java_info, + signed_apk = None, # signed_apk, always empty for android_library. + aar = getattr(ctx.outputs, "aar", None), # Deprecate aar for android_library. + apks_under_test = [], # apks_under_test, always empty for android_library + native_libs = dict(), # nativelibs, always empty for android_library + idlclass = get_android_toolchain(ctx).idlclass.files_to_run, + host_javabase = _common.get_host_javabase(ctx), + ) + return ProviderInfo( + name = "intellij_ctx", + value = struct( + android_ide_info = android_ide_info, + providers = [android_ide_info], + ), + ) + +def _process_coverage(ctx, **unused_ctx): + return ProviderInfo( + name = "coverage_ctx", + value = struct( + providers = [ + coverage_common.instrumented_files_info( + ctx, + dependency_attributes = ["assets", "deps", "exports"], + ), + ], + ), + ) + +# Order dependent, as providers will not be available to downstream processors +# that may depend on the provider. Iteration order for a dictionary is based on +# insertion. +PROCESSORS = dict( + ExceptionsProcessor = _exceptions_processor, + ResourceProcessor = _process_resources, + IdlProcessor = _process_idl, + DataBindingProcessor = _process_data_binding, + JvmProcessor = _process_jvm, + ProguardProcessor = _process_proguard, + AarProcessor = _process_aar, + NativeProcessor = _process_native, + IntelliJProcessor = _process_intellij, + CoverageProcessor = _process_coverage, +) + +# TODO(b/119560471): Deprecate the usage of legacy providers. +def _make_legacy_provider(intellij_ctx, jvm_ctx, providers): + return struct( + android = _intellij.make_legacy_android_provider(intellij_ctx.android_ide_info), + java = struct( + annotation_processing = jvm_ctx.java_info.annotation_processing, + compilation_info = jvm_ctx.java_info.compilation_info, + outputs = jvm_ctx.java_info.outputs, + source_jars = depset(jvm_ctx.java_info.source_jars), + transitive_deps = jvm_ctx.java_info.transitive_compile_time_jars, + transitive_exports = jvm_ctx.java_info.transitive_exports, + transitive_runtime_deps = jvm_ctx.java_info.transitive_runtime_jars, + transitive_source_jars = jvm_ctx.java_info.transitive_source_jars, + ), + providers = providers, + ) + +def finalize( + ctx, + resources_ctx, + intellij_ctx, + jvm_ctx, + proguard_ctx, + providers, + validation_outputs, + **unused_ctxs): + """Creates the DefaultInfo and OutputGroupInfo providers. + + Args: + ctx: The context. + resources_ctx: ProviderInfo. The resources ctx. + intellij_ctx: ProviderInfo. The intellij ctx. + jvm_ctx: ProviderInfo. The jvm ctx. + proguard_ctx: ProviderInfo. The proguard ctx. + providers: sequence of providers. The providers to propagate. + validation_outputs: sequence of Files. The validation outputs. + **unused_ctxs: Unused ProviderInfo. + + Returns: + A struct with Android and Java legacy providers and a list of providers. + """ + transitive_runfiles = [] + if not ctx.attr.neverlink: + for p in utils.collect_providers( + DefaultInfo, + ctx.attr.deps, + ctx.attr.exports, + ): + transitive_runfiles.append(p.data_runfiles.files) + transitive_runfiles.append(p.default_runfiles.files) + runfiles = ctx.runfiles( + files = ( + (resources_ctx.r_java.runtime_output_jars if resources_ctx.r_java and not ctx.attr.neverlink else []) + + ([ctx.outputs.lib_jar] if (ctx.attr.srcs or ctx.attr.idl_srcs) and not ctx.attr.neverlink else []) + ), + transitive_files = depset(transitive = transitive_runfiles), + collect_default = True, + ) + files = [ctx.outputs.lib_jar] + if getattr(ctx.outputs, "resources_src_jar", None): + files.append(ctx.outputs.resources_src_jar) + if getattr(ctx.outputs, "resources_jar", None): + files.append(ctx.outputs.resources_jar) + + providers.extend([ + DefaultInfo( + files = depset(files), + runfiles = runfiles, + ), + OutputGroupInfo( + compilation_outputs = depset([ctx.outputs.lib_jar]), + _source_jars = depset( + [ctx.outputs.lib_src_jar], + transitive = [jvm_ctx.java_info.transitive_source_jars], + ), + _hidden_top_level_INTERNAL_ = depset( + resources_ctx.validation_results, + transitive = [ + info._hidden_top_level_INTERNAL_ + for info in utils.collect_providers( + OutputGroupInfo, + ctx.attr.deps, + ctx.attr.exports, + ) + ] + [proguard_ctx.transitive_proguard_configs], + ), + _validation = depset(validation_outputs), + ), + ]) + return _make_legacy_provider(intellij_ctx, jvm_ctx, providers) + +_PROCESSING_PIPELINE = processing_pipeline.make_processing_pipeline( + processors = PROCESSORS, + finalize = finalize, +) + +def impl(ctx): + """The rule implementation. + + Args: + ctx: The context. + + Returns: + A legacy struct provider. + """ + java_package = _java.resolve_package_from_label(ctx.label, ctx.attr.custom_package) + return processing_pipeline.run(ctx, java_package, _PROCESSING_PIPELINE) diff --git a/rules/android_library/rule.bzl b/rules/android_library/rule.bzl new file mode 100644 index 0000000..f267b37 --- /dev/null +++ b/rules/android_library/rule.bzl @@ -0,0 +1,135 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""android_library rule.""" + +load(":attrs.bzl", _ATTRS = "ATTRS") +load(":impl.bzl", _impl = "impl") +load( + "@rules_android//rules:attrs.bzl", + _attrs = "attrs", +) + +def _outputs(_defined_local_resources): + outputs = dict( + lib_jar = "lib%{name}.jar", + lib_src_jar = "lib%{name}-src.jar", + aar = "%{name}.aar", + ) + + if _defined_local_resources: + # TODO(b/177261846): resource-related predeclared outputs need to be re-pointed at the + # corresponding artifacts in the Starlark pipeline. + outputs.update( + dict( + resources_src_jar = "_migrated/%{name}.srcjar", + resources_txt = "_migrated/%{name}_symbols/R.txt", + resources_jar = "_migrated/%{name}_resources.jar", + ), + ) + + return outputs + +def make_rule( + attrs = _ATTRS, + implementation = _impl, + outputs = _outputs, + additional_toolchains = []): + """Makes the rule. + + Args: + attrs: A dict. The attributes for the rule. + implementation: A function. The rule's implementation method. + + Returns: + A rule. + """ + return rule( + attrs = attrs, + fragments = [ + "android", + "java", + ], + implementation = implementation, + provides = [ + AndroidCcLinkParamsInfo, + AndroidIdeInfo, + AndroidIdlInfo, + AndroidLibraryResourceClassJarProvider, + AndroidNativeLibsInfo, + JavaInfo, + ], + outputs = outputs, + toolchains = [ + "@rules_android//toolchains/android:toolchain_type", + "@rules_android//toolchains/android_sdk:toolchain_type", + ] + additional_toolchains, + _skylark_testable = True, + ) + +android_library = make_rule() + +def _is_defined(name, attrs): + return name in attrs and attrs[name] != None + +def attrs_metadata(attrs): + """Adds additional metadata for specific android_library attrs. + + Bazel native rules have additional capabilities when inspecting attrs that + are not available in Starlark. For example, native rules are able to + determine if an attribute was set by a user and make decisions based on this + knowledge - sometimes the behavior may differ if the user specifies the + default value of the attribute. As such the Starlark android_library uses + this shim to provide similar capabilities. + + Args: + attrs: The attributes passed to the android_library rule. + + Returns: + A dictionary containing attr values with additional metadata. + """ + + # Required for the outputs. + attrs["$defined_local_resources"] = bool( + attrs.get("assets") or + attrs.get("assets_dir") or + attrs.get("assets_dir") == "" or + attrs.get("export_manifest") or + attrs.get("manifest") or + attrs.get("resource_files"), + ) + + # TODO(b/116691720): Remove normalization when bug is fixed. + if _is_defined("exports_manifest", attrs): + attrs["exports_manifest"] = _attrs.tristate.normalize( + attrs.get("exports_manifest"), + ) + + # TODO(b/127517031): Remove these entries once fixed. + attrs["$defined_assets"] = _is_defined("assets", attrs) + attrs["$defined_assets_dir"] = _is_defined("assets_dir", attrs) + attrs["$defined_idl_import_root"] = _is_defined("idl_import_root", attrs) + attrs["$defined_idl_parcelables"] = _is_defined("idl_parcelables", attrs) + attrs["$defined_idl_srcs"] = _is_defined("idl_srcs", attrs) + return attrs + +def android_library_macro(**attrs): + """Bazel android_library rule. + + https://docs.bazel.build/versions/master/be/android.html#android_library + + Args: + **attrs: Rule attributes + """ + android_library(**attrs_metadata(attrs)) diff --git a/rules/android_local_test.bzl b/rules/android_local_test.bzl new file mode 100644 index 0000000..9b1fe39 --- /dev/null +++ b/rules/android_local_test.bzl @@ -0,0 +1,27 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel rule for Android local test.""" + +load(":migration_tag_DONOTUSE.bzl", _add_migration_tag = "add_migration_tag") + +def android_local_test(**attrs): + """Bazel android_local_test rule. + + https://docs.bazel.build/versions/master/be/android.html#android_local_test + + Args: + **attrs: Rule attributes + """ + native.android_local_test(**_add_migration_tag(attrs)) diff --git a/rules/android_ndk_repository.bzl b/rules/android_ndk_repository.bzl new file mode 100644 index 0000000..34aa2e3 --- /dev/null +++ b/rules/android_ndk_repository.bzl @@ -0,0 +1,25 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel rule for Android ndk repository.""" + +def android_ndk_repository(**attrs): + """Bazel android_ndk_repository rule. + + https://docs.bazel.build/versions/master/be/android.html#android_ndk_repository + + Args: + **attrs: Rule attributes + """ + native.android_ndk_repository(**attrs) diff --git a/rules/android_packaged_resources/BUILD b/rules/android_packaged_resources/BUILD new file mode 100644 index 0000000..f858689 --- /dev/null +++ b/rules/android_packaged_resources/BUILD @@ -0,0 +1,25 @@ +# Starlark Resource Packaging for Android Rules. + +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + +package( + default_visibility = + ["//third_party/bazel_rules/rules_android"], +) + +licenses(["notice"]) + +exports_files(["rule.bzl"]) + +filegroup( + name = "all_files", + srcs = glob(["**"]), +) + +bzl_library( + name = "bzl", + srcs = glob(["*.bzl"]), + deps = [ + "@rules_android//rules:common_bzl", + ], +) diff --git a/rules/android_packaged_resources/attrs.bzl b/rules/android_packaged_resources/attrs.bzl new file mode 100644 index 0000000..5a7bca7 --- /dev/null +++ b/rules/android_packaged_resources/attrs.bzl @@ -0,0 +1,69 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Attributes.""" + +load( + "@rules_android//rules:attrs.bzl", + _attrs = "attrs", +) + +ATTRS = _attrs.replace( + _attrs.add( + dict( + deps = attr.label_list( + allow_files = True, + allow_rules = [ + "aar_import", + "android_library", + "cc_library", + "java_import", + "java_library", + "java_lite_proto_library", + ], + providers = [ + [CcInfo], + [JavaInfo], + ["AndroidResourcesInfo", "AndroidAssetsInfo"], + ], + cfg = android_common.multi_cpu_configuration, + ), + enable_data_binding = attr.bool(), + instruments = attr.label(), + manifest_values = attr.string_dict(), + manifest_merger = attr.string( + default = "auto", + values = ["auto", "legacy", "android", "force_android"], + ), + native_target = attr.label( + allow_files = False, + allow_rules = ["android_binary", "android_test"], + ), + resource_configuration_filters = attr.string_list(), + densities = attr.string_list(), + nocompress_extensions = attr.string_list(), + shrink_resources = _attrs.tristate.create( + default = _attrs.tristate.auto, + ), + _defined_resource_files = attr.bool(default = False), + _enable_manifest_merging = attr.bool(default = True), + ), + _attrs.COMPILATION, + _attrs.DATA_CONTEXT, + ), + # TODO(b/167599192): don't override manifest attr to remove .xml file restriction. + manifest = attr.label( + allow_single_file = True, + ), +) diff --git a/rules/android_packaged_resources/impl.bzl b/rules/android_packaged_resources/impl.bzl new file mode 100644 index 0000000..e3d6ac0 --- /dev/null +++ b/rules/android_packaged_resources/impl.bzl @@ -0,0 +1,111 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Implementation.""" + +load("@rules_android//rules:acls.bzl", "acls") +load("@rules_android//rules:java.bzl", "java") +load( + "@rules_android//rules:processing_pipeline.bzl", + "ProviderInfo", + "processing_pipeline", +) +load("@rules_android//rules:resources.bzl", _resources = "resources") +load("@rules_android//rules:utils.bzl", "compilation_mode", "get_android_toolchain", "utils") + +def _process_resources(ctx, java_package, **unused_ctxs): + packaged_resources_ctx = _resources.package( + ctx, + assets = ctx.files.assets, + assets_dir = ctx.attr.assets_dir, + resource_files = ctx.files.resource_files, + manifest = ctx.file.manifest, + manifest_values = utils.expand_make_vars(ctx, ctx.attr.manifest_values), + resource_configs = ctx.attr.resource_configuration_filters, + densities = ctx.attr.densities, + nocompress_extensions = ctx.attr.nocompress_extensions, + java_package = java_package, + compilation_mode = compilation_mode.get(ctx), + shrink_resources = ctx.attr.shrink_resources, + use_android_resource_shrinking = ctx.fragments.android.use_android_resource_shrinking, + use_android_resource_cycle_shrinking = ctx.fragments.android.use_android_resource_cycle_shrinking, + use_legacy_manifest_merger = use_legacy_manifest_merger(ctx), + should_throw_on_conflict = not acls.in_allow_resource_conflicts(str(ctx.label)), + enable_data_binding = ctx.attr.enable_data_binding, + enable_manifest_merging = ctx.attr._enable_manifest_merging, + deps = ctx.attr.deps, + instruments = ctx.attr.instruments, + aapt = get_android_toolchain(ctx).aapt2.files_to_run, + android_jar = ctx.attr._android_sdk[AndroidSdkInfo].android_jar, + legacy_merger = ctx.attr._android_manifest_merge_tool.files_to_run, + xsltproc = ctx.attr._xsltproc_tool.files_to_run, + instrument_xslt = ctx.file._add_g3itr_xslt, + busybox = get_android_toolchain(ctx).android_resources_busybox.files_to_run, + host_javabase = ctx.attr._host_javabase, + ) + return ProviderInfo( + name = "packaged_resources_ctx", + value = packaged_resources_ctx, + ) + +def use_legacy_manifest_merger(ctx): + """Whether legacy manifest merging is enabled. + + Args: + ctx: The context. + + Returns: + Boolean indicating whether legacy manifest merging is enabled. + """ + manifest_merger = ctx.attr.manifest_merger + android_manifest_merger = ctx.fragments.android.manifest_merger + + if android_manifest_merger == "force_android": + return False + if manifest_merger == "auto": + manifest_merger = android_manifest_merger + + return manifest_merger == "legacy" + +def finalize(ctx, providers, validation_outputs, **unused_ctxs): + providers.append( + OutputGroupInfo( + _validation = depset(validation_outputs), + ), + ) + return providers + +# Order dependent, as providers will not be available to downstream processors +# that may depend on the provider. Iteration order for a dictionary is based on +# insertion. +PROCESSORS = dict( + ResourceProcessor = _process_resources, +) + +_PROCESSING_PIPELINE = processing_pipeline.make_processing_pipeline( + processors = PROCESSORS, + finalize = finalize, +) + +def impl(ctx): + """The rule implementation. + + Args: + ctx: The context. + + Returns: + A list of providers. + """ + java_package = java.resolve_package_from_label(ctx.label, ctx.attr.custom_package) + return processing_pipeline.run(ctx, java_package, _PROCESSING_PIPELINE) diff --git a/rules/android_packaged_resources/rule.bzl b/rules/android_packaged_resources/rule.bzl new file mode 100644 index 0000000..db3f96a --- /dev/null +++ b/rules/android_packaged_resources/rule.bzl @@ -0,0 +1,91 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Starlark Resource Packaging for Android Rules.""" + +load(":attrs.bzl", "ATTRS") +load(":impl.bzl", "impl") +load( + "@rules_android//rules:attrs.bzl", + _attrs = "attrs", +) + +_DEFAULT_ALLOWED_ATTRS = ["name", "visibility", "tags", "testonly", "transitive_configs", "$enable_manifest_merging"] + +_DEFAULT_PROVIDES = [AndroidApplicationResourceInfo, OutputGroupInfo] + +# TODO(b/167721629): Rename android_packaged_resources to android_binary_internal. +def make_rule( + attrs = ATTRS, + implementation = impl, + provides = _DEFAULT_PROVIDES): + """Makes the rule. + + Args: + attrs: A dict. The attributes for the rule. + implementation: A function. The rule's implementation method. + provides: A list. The providers that the rule must provide. + + Returns: + A rule. + """ + return rule( + attrs = attrs, + implementation = implementation, + provides = provides, + toolchains = ["@rules_android//toolchains/android:toolchain_type"], + _skylark_testable = True, + fragments = [ + "android", + "java", + ], + ) + +_android_packaged_resources = make_rule() + +def sanitize_attrs(attrs, allowed_attrs = ATTRS.keys()): + """Sanitizes the attributes. + + The android_packaged_resources has a subset of the android_binary attributes, but is + called from the android_binary macro with the same full set of attributes. This removes + any unnecessary attributes. + + Args: + attrs: A dict. The attributes for the android_packaged_resources rule. + allowed_attrs: The list of attribute keys to keep. + + Returns: + A dictionary containing valid attributes. + """ + for attr_name in attrs.keys(): + if attr_name not in allowed_attrs and attr_name not in _DEFAULT_ALLOWED_ATTRS: + attrs.pop(attr_name, None) + + # Some teams set this to a boolean/None which works for the native attribute but breaks + # the Starlark attribute. + if attr_name == "shrink_resources": + if attrs[attr_name] == None: + attrs.pop(attr_name, None) + else: + attrs[attr_name] = _attrs.tristate.normalize(attrs[attr_name]) + + return attrs + +def android_packaged_resources_macro(**attrs): + """android_packaged_resources rule. + + Args: + **attrs: Rule attributes + """ + _android_packaged_resources(**sanitize_attrs(attrs)) diff --git a/rules/android_sdk.bzl b/rules/android_sdk.bzl new file mode 100644 index 0000000..cf824e1 --- /dev/null +++ b/rules/android_sdk.bzl @@ -0,0 +1,53 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel rule for Android sdk.""" + +load(":attrs.bzl", "ANDROID_SDK_ATTRS") + +def _impl(ctx): + proguard = ctx.attr._proguard if ctx.attr._proguard else ctx.attr.proguard + android_sdk_info = AndroidSdkInfo( + ctx.attr.build_tools_version, + ctx.file.framework_aidl, + ctx.attr.aidl_lib, + ctx.file.android_jar, + ctx.file.source_properties, + ctx.file.shrinked_android_jar, + ctx.file.main_dex_classes, + ctx.attr.adb.files_to_run, + ctx.attr.dx.files_to_run, + ctx.attr.main_dex_list_creator.files_to_run, + ctx.attr.aidl.files_to_run, + ctx.attr.aapt.files_to_run, + ctx.attr.aapt2.files_to_run, + ctx.attr.apkbuilder.files_to_run if ctx.attr.apkbuilder else None, + ctx.attr.apksigner.files_to_run, + proguard.files_to_run, + ctx.attr.zipalign.files_to_run, + # Passing the 'system' here is only necessary to support native android_binary. + # TODO(b/149114743): remove this after the migration to android_application. + ctx.attr._system[java_common.BootClassPathInfo] if ctx.attr._system and java_common.BootClassPathInfo in ctx.attr._system else None, + ) + return [ + android_sdk_info, + platform_common.ToolchainInfo(android_sdk_info = android_sdk_info), + ] + +android_sdk = rule( + attrs = ANDROID_SDK_ATTRS, + implementation = _impl, + fragments = ["java"], + provides = [AndroidSdkInfo], +) diff --git a/rules/android_sdk_repository.bzl b/rules/android_sdk_repository.bzl new file mode 100644 index 0000000..f82f6e6 --- /dev/null +++ b/rules/android_sdk_repository.bzl @@ -0,0 +1,25 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel rule for Android sdk repository.""" + +def android_sdk_repository(**attrs): + """Bazel android_sdk_repository rule. + + https://docs.bazel.build/versions/master/be/android.html#android_sdk_repository + + Args: + **attrs: Rule attributes + """ + native.android_sdk_repository(**attrs) diff --git a/rules/android_tools_defaults_jar.bzl b/rules/android_tools_defaults_jar.bzl new file mode 100644 index 0000000..b226882 --- /dev/null +++ b/rules/android_tools_defaults_jar.bzl @@ -0,0 +1,32 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel rule for Android tools defaults jar.""" + +load(":attrs.bzl", "ANDROID_TOOLS_DEFAULTS_JAR_ATTRS") +load(":utils.bzl", "get_android_sdk") + +def _impl(ctx): + return [ + DefaultInfo( + files = depset([get_android_sdk(ctx).android_jar]), + ), + ] + +android_tools_defaults_jar = rule( + attrs = ANDROID_TOOLS_DEFAULTS_JAR_ATTRS, + implementation = _impl, + fragments = ["android"], + toolchains = ["@rules_android//toolchains/android_sdk:toolchain_type"], +) diff --git a/rules/attrs.bzl b/rules/attrs.bzl new file mode 100644 index 0000000..eca1947 --- /dev/null +++ b/rules/attrs.bzl @@ -0,0 +1,286 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Common attributes for Android rules.""" + +load(":utils.bzl", "log") + +def _add(attrs, *others): + new = {} + new.update(attrs) + for o in others: + for name in o.keys(): + if name in new: + log.error("Attr '%s' is defined twice." % name) + new[name] = o[name] + return new + +def _replace(attrs, **kwargs): + # Verify that new values are replacing existing ones, not adding. + for name in kwargs.keys(): + if name not in attrs: + log.error("Attr '%s' is not defined, replacement failed." % name) + new = dict() + new.update(attrs) + new.update(kwargs) + return new + +def _make_tristate_attr(default, doc = "", mandatory = False): + return attr.int( + default = default, + doc = doc, + mandatory = mandatory, + values = [-1, 0, 1], + ) + +def _normalize_tristate(attr_value): + """Normalizes the tristate value going into a rule. + + This is required because "tristate" is not officially supported as an + attribute type. An equivalent attribute type is an in with a constrained + set of values, namely [-1, 0, 1]. Unfortunately, tristate accepts + multiple types, integers, booleans and strings ("auto"). As a result, this + method normalizes the inputs to an integer. + + This method needs to be applied to attributes that were formally tristate + to normalize the inputs. + """ + if type(attr_value) == "int": + return attr_value + + if type(attr_value) == "string": + if attr_value.lower() == "auto": + return -1 + + if type(attr_value) == "bool": + return int(attr_value) + + return attr_value # Return unknown type, let the rule fail. + +_tristate = struct( + create = _make_tristate_attr, + normalize = _normalize_tristate, + yes = 1, + no = 0, + auto = -1, +) + +_JAVA_RUNTIME = dict( + _host_javabase = attr.label( + cfg = "host", + default = Label("@rules_android//rules:current_java_runtime"), + ), +) + + +# Android SDK attribute. +_ANDROID_SDK = dict( + _android_sdk = attr.label( + allow_rules = ["android_sdk"], + default = configuration_field( + fragment = "android", + name = "android_sdk_label", + ), + providers = [AndroidSdkInfo], + ), +) + +# Compilation attributes for Android rules. +_COMPILATION = _add( + dict( + assets = attr.label_list( + allow_files = True, + cfg = "target", + ), + assets_dir = attr.string(), + custom_package = attr.string(), + manifest = attr.label( + allow_single_file = [".xml"], + ), + resource_files = attr.label_list( + allow_files = True, + ), + data = attr.label_list( + allow_files = True, + ), + plugins = attr.label_list( + allow_rules = ["java_plugin"], + cfg = "host", + ), + javacopts = attr.string_list(), + # TODO: Expose getPlugins() in JavaConfiguration.java + # com/google/devtools/build/lib/rules/java/JavaConfiguration.java + # com/google/devtools/build/lib/rules/java/JavaOptions.java + # + # _java_plugins = attr.label( + # allow_rules = ["java_plugin"], + # default = configuration_field( + # fragment = "java", + # name = "plugin", + # ), + # ), + ), + _JAVA_RUNTIME, +) + +# Attributes for rules that use the AndroidDataContext android_data.make_context +_DATA_CONTEXT = _add( + dict( + # Additional attrs needed for AndroidDataContext + _add_g3itr_xslt = attr.label( + cfg = "host", + default = Label("//tools/android/xslt:add_g3itr.xslt"), + allow_single_file = True, + ), + _android_manifest_merge_tool = attr.label( + cfg = "host", + default = Label("//tools/android:merge_manifests"), + executable = True, + ), + # TODO(b/145617058) Switching back to head RPBB until the Android rules release process is improved + _android_resources_busybox = attr.label( + cfg = "host", + default = Label("@rules_android//rules:ResourceProcessorBusyBox"), + executable = True, + ), + _xsltproc_tool = attr.label( + cfg = "host", + default = Label("//tools/android/xslt:xslt"), + allow_files = True, + ), + ), + _ANDROID_SDK, +) + + + + + + + +ANDROID_SDK_ATTRS = dict( + aapt = attr.label( + allow_single_file = True, + cfg = "host", + executable = True, + mandatory = True, + ), + aapt2 = attr.label( + allow_single_file = True, + cfg = "host", + executable = True, + ), + aidl = attr.label( + allow_files = True, + cfg = "host", + executable = True, + mandatory = True, + ), + aidl_lib = attr.label( + allow_files = [".jar"], + ), + android_jar = attr.label( + allow_single_file = [".jar"], + cfg = "host", + mandatory = True, + ), + annotations_jar = attr.label( + allow_single_file = [".jar"], + cfg = "host", + ), + apkbuilder = attr.label( + allow_files = True, + cfg = "host", + executable = True, + ), + apksigner = attr.label( + allow_files = True, + cfg = "host", + executable = True, + mandatory = True, + ), + adb = attr.label( + allow_single_file = True, + cfg = "host", + executable = True, + mandatory = True, + ), + build_tools_version = attr.string(), + dx = attr.label( + allow_files = True, + cfg = "host", + executable = True, + mandatory = True, + ), + framework_aidl = attr.label( + allow_single_file = True, + cfg = "host", + mandatory = True, + ), + main_dex_classes = attr.label( + allow_single_file = True, + cfg = "host", + mandatory = True, + ), + main_dex_list_creator = attr.label( + allow_files = True, + cfg = "host", + executable = True, + mandatory = True, + ), + proguard = attr.label( + allow_files = True, + cfg = "host", + executable = True, + mandatory = True, + ), + shrinked_android_jar = attr.label( + allow_single_file = True, + cfg = "host", + mandatory = True, + ), + source_properties = attr.label( + allow_single_file = True, + cfg = "host", + ), + zipalign = attr.label( + allow_single_file = True, + cfg = "host", + executable = True, + mandatory = True, + ), + _proguard = attr.label( + cfg = "host", + default = configuration_field( + fragment = "java", + name = "proguard_top", + ), + ), + _system = attr.label( + default = Label("//tools/android:bootclasspath_android_only"), + ), +) + +ANDROID_TOOLS_DEFAULTS_JAR_ATTRS = _add(_ANDROID_SDK) + + +attrs = struct( + ANDROID_SDK = _ANDROID_SDK, + COMPILATION = _COMPILATION, + DATA_CONTEXT = _DATA_CONTEXT, + JAVA_RUNTIME = _JAVA_RUNTIME, + tristate = _tristate, + add = _add, + replace = _replace, +) diff --git a/rules/busybox.bzl b/rules/busybox.bzl new file mode 100644 index 0000000..f0d78ac --- /dev/null +++ b/rules/busybox.bzl @@ -0,0 +1,1033 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel ResourcesBusyBox Commands.""" + +load(":java.bzl", _java = "java") + +_ANDROID_RESOURCES_STRICT_DEPS = "android_resources_strict_deps" + +def _sanitize_assets_dir(assets_dir): + sanitized_assets_dir = "/".join( + [ + part + for part in assets_dir.split("/") + if part != "" and part != "." + ], + ) + + return "/" + sanitized_assets_dir if assets_dir.startswith("/") else sanitized_assets_dir + +def _get_unique_assets_dirs(assets, assets_dir): + """Find the unique assets directories, partitioned by assets_dir. + + Args: + assets: A list of Files. List of asset files to process. + assets_dir: String. String giving the path to the files in assets. + + Returns: + A list of short_paths representing unique asset dirs. + """ + if not assets: + return [] + + dirs = dict() + + assets_dir = _sanitize_assets_dir(assets_dir) + if assets_dir: + partition_by = "/%s/" % assets_dir.strip("/") + for f in assets: + if f.is_directory and f.path.endswith(partition_by[:-1]): + # If f is a directory, check if its path ends with the assets_dir. + dirs[f.path] = True + elif f.is_directory and "_aar/unzipped" in f.path: + # Assets from an aar_import rule are extracted in a + # "assets" subdirectory of the given path + dirs["%s/assets" % f.path] = True + else: + # Partition to remove subdirectories beneath assets_dir + # Also removes the trailing / + dirs["".join(f.path.rpartition(partition_by)[:2])[:-1]] = True + else: + # Use the dirname of the generating target if no assets_dir. + for f in assets: + if f.is_source: + dirs[f.owner.package] = True + else: + # Prepend the root path for generated files. + dirs[f.root.path + "/" + f.owner.package] = True + return dirs.keys() + +def _get_unique_res_dirs(resource_files): + """Find the unique res dirs. + + Args: + resource_files: A list of Files. A list of resource_files. + + Returns: + A list of short_paths representing unique res dirs from the given resource files. + """ + dirs = dict() + for f in resource_files: + if f.is_directory: + dirs[f.path] = True + else: + dirs[f.dirname.rpartition("/" + f.dirname.split("/")[-1])[0]] = True + return dirs.keys() + +def _make_serialized_resources_flag( + assets = [], + assets_dir = None, + resource_files = [], + label = "", + symbols = None): + return ";".join( + [ + "#".join(_get_unique_res_dirs(resource_files)), + "#".join(_get_unique_assets_dirs(assets, assets_dir)), + label, + symbols.path if symbols else "", + ], + ).rstrip(":") + +def _make_resources_flag( + assets = [], + assets_dir = None, + resource_files = [], + manifest = None, + r_txt = None, + symbols = None): + return ":".join( + [ + "#".join(_get_unique_res_dirs(resource_files)), + "#".join(_get_unique_assets_dirs(assets, assets_dir)), + manifest.path if manifest else "", + r_txt.path if r_txt else "", + symbols.path if symbols else "", + ], + ) + +def _path(f): + return f.path + +def _make_package_resources_flags(resources_node): + if not (resources_node.manifest and resources_node.r_txt and resources_node.compiled_resources): + return None + flag = _make_resources_flag( + resource_files = resources_node.resource_files.to_list(), + assets = resources_node.assets.to_list(), + assets_dir = resources_node.assets_dir, + manifest = resources_node.manifest, + r_txt = resources_node.r_txt, + symbols = resources_node.compiled_resources, + ) + return flag + +def _make_package_assets_flags(resources_node): + assets = resources_node.assets.to_list() + if not assets: + return None + return _make_serialized_resources_flag( + assets = assets, + assets_dir = resources_node.assets_dir, + label = str(resources_node.label), + symbols = resources_node.compiled_assets, + ) + +def _extract_filters( + raw_list): + """Extract densities and resource_configuration filters from raw string lists. + + In BUILD files, string lists can be represented as a list of strings, a single comma-separated + string, or a combination of both. This method outputs a single list of individual string values, + which can then be passed directly to resource processing actions. Empty strings are removed and + the final list is sorted. + + Args: + raw_list: List of strings. The raw densities or resource configuration filters. + + Returns: + List of strings extracted from the raw list. + """ + out_filters = [] + for item in raw_list: + if "," in item: + item_list = item.split(",") + for entry in item_list: + stripped_entry = entry.strip() + if stripped_entry: + out_filters.append(stripped_entry) + elif item: + out_filters.append(item) + return sorted(out_filters) + +def _package( + ctx, + out_r_src_jar = None, + out_r_txt = None, + out_symbols = None, + out_manifest = None, + out_proguard_cfg = None, + out_main_dex_proguard_cfg = None, + out_resource_files_zip = None, + out_file = None, + package_type = None, + java_package = None, + manifest = None, + assets = [], + assets_dir = None, + resource_files = [], + resource_configs = None, + densities = [], + application_id = None, + direct_resources_nodes = [], + transitive_resources_nodes = [], + transitive_manifests = [], + transitive_assets = [], + transitive_compiled_assets = [], + transitive_resource_files = [], + transitive_compiled_resources = [], + transitive_r_txts = [], + additional_apks_to_link_against = [], + nocompress_extensions = [], + proto_format = False, + version_name = None, + version_code = None, + android_jar = None, + aapt = None, + busybox = None, + host_javabase = None, + should_throw_on_conflict = True, # TODO: read this from allowlist at caller + debug = True): # TODO: we will set this to false in prod builds + """Packages the compiled Android Resources with AAPT. + + Args: + ctx: The context. + out_r_src_jar: A File. The R.java outputted by linking resources in a srcjar. + out_r_txt: A File. The resource IDs outputted by linking resources in text. + out_symbols: A File. The output zip containing compiled resources. + out_manifest: A File. The output processed manifest. + out_proguard_cfg: A File. The proguard config to be generated. + out_main_dex_proguard_cfg: A File. The main dex proguard config to be generated. + out_resource_files_zip: A File. The resource files zipped by linking resources. + out_file: A File. The Resource APK outputted by linking resources. + package_type: A string. The configuration type to use when packaging. + java_package: A string. The Java package for the generated R.java. + manifest: A File. The AndroidManifest.xml. + assets: sequence of Files. A list of Android assets files to be processed. + assets_dir: String. The name of the assets directory. + resource_files: A list of Files. The resource files. + resource_configs: A list of strings. The list of resource configuration + filters. + densities: A list of strings. The list of screen densities to filter for when + building the apk. + application_id: An optional string. The applicationId set in manifest values. + direct_resources_nodes: Depset of ResourcesNodeInfo providers. The set of + ResourcesNodeInfo from direct dependencies. + transitive_resources_nodes: Depset of ResourcesNodeInfo providers. The set + of ResourcesNodeInfo from transitive dependencies (not including directs). + transitive_manifests: List of Depsets. Depsets contain all transitive manifests. + transitive_assets: List of Depsets. Depsets contain all transitive assets. + transitive_compiled_assets: List of Depsets. Depsets contain all transitive + compiled_assets. + transitive_resource_files: List of Depsets. Depsets contain all transitive + resource files. + transitive_compiled_resources: List of Depsets. Depsets contain all transitive + compiled_resources. + transitive_r_txts: List of Depsets. Depsets contain all transitive R txt files. + additional_apks_to_link_against: A list of Files. Additional APKs to link + against. Optional. + nocompress_extensions: A list of strings. File extension to leave uncompressed + in the apk. + proto_format: Boolean, whether to generate the resource table in proto format. + version_name: A string. The version name to stamp the generated manifest with. Optional. + version_code: A string. The version code to stamp the generated manifest with. Optional. + android_jar: A File. The Android Jar. + aapt: A FilesToRunProvider. The AAPT executable. + busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable. + host_javabase: Target. The host javabase. + should_throw_on_conflict: A boolean. Determines whether an error should be thrown + when a resource conflict occurs. + debug: A boolean. Determines whether to enable debugging. + """ + if not manifest: + fail("No manifest given, the manifest is mandatory.") + + direct_data_flag = [] + direct_compiled_resources = [] + + output_files = [] + input_files = [] + transitive_input_files = [] + + args = ctx.actions.args() + args.use_param_file("@%s") + args.add("--tool", "AAPT2_PACKAGE") + args.add("--") + args.add("--aapt2", aapt.executable) + args.add_joined( + "--data", + transitive_resources_nodes, + map_each = _make_package_resources_flags, + join_with = ",", + ) + args.add_joined( + "--directData", + direct_resources_nodes, + map_each = _make_package_resources_flags, + join_with = ",", + ) + args.add_joined( + "--directAssets", + direct_resources_nodes, + map_each = _make_package_assets_flags, + join_with = "&", + omit_if_empty = True, + ) + args.add_joined( + "--assets", + transitive_resources_nodes, + map_each = _make_package_assets_flags, + join_with = "&", + omit_if_empty = True, + ) + transitive_input_files.extend(transitive_resource_files) + transitive_input_files.extend(transitive_assets) + transitive_input_files.extend(transitive_compiled_assets) + transitive_input_files.extend(transitive_compiled_resources) + transitive_input_files.extend(transitive_manifests) + transitive_input_files.extend(transitive_r_txts) + args.add( + "--primaryData", + _make_resources_flag( + manifest = manifest, + assets = assets, + assets_dir = assets_dir, + resource_files = resource_files, + ), + ) + input_files.append(manifest) + input_files.extend(resource_files) + input_files.extend(assets) + args.add("--androidJar", android_jar) + input_files.append(android_jar) + args.add("--rOutput", out_r_txt) + output_files.append(out_r_txt) + if out_symbols: + args.add("--symbolsOut", out_symbols) + output_files.append(out_symbols) + args.add("--srcJarOutput", out_r_src_jar) + output_files.append(out_r_src_jar) + if out_proguard_cfg: + args.add("--proguardOutput", out_proguard_cfg) + output_files.append(out_proguard_cfg) + if out_main_dex_proguard_cfg: + args.add("--mainDexProguardOutput", out_main_dex_proguard_cfg) + output_files.append(out_main_dex_proguard_cfg) + args.add("--manifestOutput", out_manifest) + output_files.append(out_manifest) + if out_resource_files_zip: + args.add("--resourcesOutput", out_resource_files_zip) + output_files.append(out_resource_files_zip) + if out_file: + args.add("--packagePath", out_file) + output_files.append(out_file) + args.add("--useAaptCruncher=no") # Unnecessary, used for AAPT1 only but added here to minimize diffs. + if package_type: + args.add("--packageType", package_type) + if debug: + args.add("--debug") + if should_throw_on_conflict: + args.add("--throwOnResourceConflict") + if resource_configs: + args.add_joined("--resourceConfigs", _extract_filters(resource_configs), join_with = ",") + if densities: + args.add_joined("--densities", _extract_filters(densities), join_with = ",") + if application_id: + args.add("--applicationId", application_id) + if additional_apks_to_link_against: + args.add_joined( + "--additionalApksToLinkAgainst", + additional_apks_to_link_against, + join_with = ",", + map_each = _path, + ) + input_files.extend(additional_apks_to_link_against) + if nocompress_extensions: + args.add_joined("--uncompressedExtensions", nocompress_extensions, join_with = ",") + if proto_format: + args.add("--resourceTableAsProto") + if version_name: + args.add("--versionName", version_name) + if version_code: + args.add("--versionCode", version_code) + args.add("--packageForR", java_package) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = busybox, + tools = [aapt], + arguments = [args], + inputs = depset(input_files, transitive = transitive_input_files), + outputs = output_files, + mnemonic = "PackageAndroidResources", + progress_message = "Packaging Android Resources in %s" % ctx.label, + ) + +def _parse( + ctx, + out_symbols = None, + assets = [], + assets_dir = None, + busybox = None, + host_javabase = None): + """Parses Android assets. + + Args: + ctx: The context. + out_symbols: A File. The output bin containing parsed assets. + assets: sequence of Files. A list of Android assets files to be processed. + assets_dir: String. The name of the assets directory. + busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable. + host_javabase: Target. The host javabase. + """ + args = ctx.actions.args() + args.use_param_file("@%s") + args.add("--tool", "PARSE") + args.add("--") + args.add( + "--primaryData", + _make_resources_flag( + assets = assets, + assets_dir = assets_dir, + ), + ) + args.add("--output", out_symbols) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = busybox, + arguments = [args], + inputs = assets, + outputs = [out_symbols], + mnemonic = "ParseAndroidResources", + progress_message = "Parsing Android Resources in %s" % out_symbols.short_path, + ) + +def _make_merge_assets_flags(resources_node): + assets = resources_node.assets.to_list() + if not (assets or resources_node.assets_dir): + return None + return _make_serialized_resources_flag( + assets = assets, + assets_dir = resources_node.assets_dir, + label = str(resources_node.label), + symbols = resources_node.assets_symbols, + ) + +def _merge_assets( + ctx, + out_assets_zip = None, + assets = [], + assets_dir = None, + symbols = None, + transitive_assets = [], + transitive_assets_symbols = [], + direct_resources_nodes = [], + transitive_resources_nodes = [], + busybox = None, + host_javabase = None): + """Merges Android assets. + + Args: + ctx: The context. + out_assets_zip: A File. + assets: sequence of Files. A list of Android assets files to be processed. + assets_dir: String. The name of the assets directory. + symbols: A File. The parsed assets. + transitive_assets: Sequence of Depsets. The list of transitive + assets from deps. + transitive_assets_symbols: Sequence of Depsets. The list of + transitive assets_symbols files from deps. + direct_resources_nodes: Sequence of ResourcesNodeInfo providers. The list + of ResourcesNodeInfo providers that are direct depencies. + transitive_resources_nodes: Sequence of ResourcesNodeInfo providers. The + list of ResourcesNodeInfo providers that are transitive depencies. + busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable. + host_javabase: Target. The host javabase. + """ + args = ctx.actions.args() + args.use_param_file("@%s") + args.add("--tool", "MERGE_ASSETS") + args.add("--") + args.add("--assetsOutput", out_assets_zip) + args.add( + "--primaryData", + _make_serialized_resources_flag( + assets = assets, + assets_dir = assets_dir, + label = str(ctx.label), + symbols = symbols, + ), + ) + args.add_joined( + "--directData", + direct_resources_nodes, + map_each = _make_merge_assets_flags, + join_with = "&", + ) + args.add_joined( + "--data", + transitive_resources_nodes, + map_each = _make_merge_assets_flags, + join_with = "&", + ) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = busybox, + arguments = [args], + inputs = depset( + assets + [symbols], + transitive = transitive_assets + transitive_assets_symbols, + ), + outputs = [out_assets_zip], + mnemonic = "MergeAndroidAssets", + progress_message = + "Merging Android Assets in %s" % out_assets_zip.short_path, + ) + +def _validate_and_link( + ctx, + out_r_src_jar = None, + out_r_txt = None, + out_file = None, + compiled_resources = None, + transitive_compiled_resources = depset(), + java_package = None, + manifest = None, + android_jar = None, + busybox = None, + host_javabase = None, + aapt = None): + """Links compiled Android Resources with AAPT. + + Args: + ctx: The context. + out_r_src_jar: A File. The R.java outputted by linking resources in a srcjar. + out_r_txt: A File. The resource IDs outputted by linking resources in text. + out_file: A File. The Resource APK outputted by linking resources. + compiled_resources: A File. The symbols.zip of compiled resources for + this target. + transitive_compiled_resources: Depset of Files. The symbols.zip of the + compiled resources from the transitive dependencies of this target. + java_package: A string. The Java package for the generated R.java. + manifest: A File. The AndroidManifest.xml. + android_jar: A File. The Android Jar. + busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable. + host_javabase: Target. The host javabase. + aapt: A FilesToRunProvider. The AAPT executable. + """ + output_files = [] + input_files = [android_jar] + transitive_input_files = [] + + # Retrieves the list of files at runtime when a directory is passed. + args = ctx.actions.args() + args.use_param_file("@%s") + args.add("--tool", "LINK_STATIC_LIBRARY") + args.add("--") + args.add("--aapt2", aapt.executable) + args.add("--libraries", android_jar) + if compiled_resources: + args.add("--compiled", compiled_resources) + input_files.append(compiled_resources) + args.add_joined( + "--compiledDep", + transitive_compiled_resources, + join_with = ":", + ) + transitive_input_files.append(transitive_compiled_resources) + args.add("--manifest", manifest) + input_files.append(manifest) + if java_package: + args.add("--packageForR", java_package) + args.add("--sourceJarOut", out_r_src_jar) + output_files.append(out_r_src_jar) + args.add("--rTxtOut", out_r_txt) + output_files.append(out_r_txt) + args.add("--staticLibraryOut", out_file) + output_files.append(out_file) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = busybox, + tools = [aapt], + arguments = [args], + inputs = depset(input_files, transitive = transitive_input_files), + outputs = output_files, + mnemonic = "LinkAndroidResources", + progress_message = + "Linking Android Resources in " + out_file.short_path, + ) + +def _compile( + ctx, + out_file = None, + assets = [], + assets_dir = None, + resource_files = [], + busybox = None, + aapt = None, + host_javabase = None): + """Compile and store resources in a single archive. + + Args: + ctx: The context. + out_file: File. The output zip containing compiled resources. + resource_files: A list of Files. The list of resource files or directories + assets: A list of Files. The list of assets files or directories + to process. + assets_dir: String. The name of the assets directory. + busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable. + aapt: AAPT. Tool for compiling resources. + host_javabase: Target. The host javabase. + """ + if not out_file: + fail("No output directory specified.") + + # Retrieves the list of files at runtime when a directory is passed. + args = ctx.actions.args() + args.use_param_file("@%s") + args.add("--tool", "COMPILE_LIBRARY_RESOURCES") + args.add("--") + args.add("--aapt2", aapt.executable) + args.add( + "--resources", + _make_resources_flag( + resource_files = resource_files, + assets = assets, + assets_dir = assets_dir, + ), + ) + args.add("--output", out_file) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = busybox, + tools = [aapt], + arguments = [args], + inputs = resource_files + assets, + outputs = [out_file], + mnemonic = "CompileAndroidResources", + progress_message = "Compiling Android Resources in %s" % out_file.short_path, + ) + +def _make_merge_compiled_flags(resources_node_info): + if not resources_node_info.compiled_resources: + return None + return _make_serialized_resources_flag( + label = str(resources_node_info.label), + symbols = resources_node_info.compiled_resources, + ) + +def _merge_compiled( + ctx, + out_class_jar = None, + out_manifest = None, + out_aapt2_r_txt = None, + java_package = None, + manifest = None, + compiled_resources = None, + direct_resources_nodes = [], + transitive_resources_nodes = [], + direct_compiled_resources = depset(), + transitive_compiled_resources = depset(), + android_jar = None, + busybox = None, + host_javabase = None): + """Merges the compile resources. + + Args: + ctx: The context. + out_class_jar: A File. The compiled R.java outputted by linking resources. + out_manifest: A File. The list of resource files or directories + out_aapt2_r_txt: A File. The resource IDs outputted by linking resources in text. + java_package: A string. The Java package for the generated R.java. + manifest: A File. The AndroidManifest.xml. + compiled_resources: A File. The symbols.zip of compiled resources for this target. + direct_resources_nodes: Sequence of ResourcesNodeInfo providers. The list + of ResourcesNodeInfo providers that are direct depencies. + transitive_resources_nodes: Sequence of ResourcesNodeInfo providers. The + list of ResourcesNodeInfo providers that are transitive depencies. + direct_compiled_resources: Depset of Files. A depset of symbols.zip of + compiled resources from direct dependencies. + transitive_compiled_resources: Depset of Files. A depset of symbols.zip of + compiled resources from transitive dependencies. + android_jar: A File. The Android Jar. + busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable. + host_javabase: Target. The host javabase. + """ + output_files = [] + input_files = [android_jar] + transitive_input_files = [] + + args = ctx.actions.args() + args.use_param_file("@%s") + args.add("--tool", "MERGE_COMPILED") + args.add("--") + args.add("--classJarOutput", out_class_jar) + output_files.append(out_class_jar) + args.add("--targetLabel", ctx.label) + args.add("--manifestOutput", out_manifest) + output_files.append(out_manifest) + args.add("--rTxtOut", out_aapt2_r_txt) + output_files.append(out_aapt2_r_txt) + args.add("--androidJar", android_jar) + args.add("--primaryManifest", manifest) + input_files.append(manifest) + if java_package: + args.add("--packageForR", java_package) + args.add( + "--primaryData", + _make_serialized_resources_flag( + label = str(ctx.label), + symbols = compiled_resources, + ), + ) + input_files.append(compiled_resources) + args.add_joined( + "--directData", + direct_resources_nodes, + map_each = _make_merge_compiled_flags, + join_with = "&", + ) + transitive_input_files.append(direct_compiled_resources) + if _ANDROID_RESOURCES_STRICT_DEPS in ctx.disabled_features: + args.add_joined( + "--data", + transitive_resources_nodes, + map_each = _make_merge_compiled_flags, + join_with = "&", + ) + transitive_input_files.append(transitive_compiled_resources) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = busybox, + arguments = [args], + inputs = depset(input_files, transitive = transitive_input_files), + outputs = output_files, + mnemonic = "StarlarkMergeCompiledAndroidResources", + progress_message = + "Merging compiled Android Resources in " + out_class_jar.short_path, + ) + +def _escape_mv(s): + """Escapes `:` and `,` in manifest values so they can be used as a busybox flag.""" + return s.replace(":", "\\:").replace(",", "\\,") + +def _owner_label(file): + return "//" + file.owner.package + ":" + file.owner.name + +# We need to remove the "/_migrated/" path segment from file paths in order for sorting to +# match the order of the native manifest merging action. +def _manifest_short_path(manifest): + return manifest.short_path.replace("/_migrated/", "/") + +def _mergee_manifests_flag(manifests): + ordered_manifests = sorted(manifests.to_list(), key = _manifest_short_path) + entries = [] + for manifest in ordered_manifests: + label = _owner_label(manifest).replace(":", "\\:") + entries.append((manifest.path + ":" + label).replace(",", "\\,")) + flag_entry = ",".join(entries) + if not flag_entry: + return None + return flag_entry + +def _merge_manifests( + ctx, + out_file = None, + out_log_file = None, + merge_type = "APPLICATION", + manifest = None, + mergee_manifests = depset(), + manifest_values = None, + java_package = None, + busybox = None, + host_javabase = None): + """Merge multiple AndroidManifest.xml files into a single one. + + Args: + ctx: The context. + out_file: A File. The output merged manifest. + out_log_file: A File. The output log from the merge tool. + merge_type: A string, either APPLICATION or LIBRARY. Type of merging. + manifest: A File. The primary AndroidManifest.xml. + mergee_manifests: A depset of Files. All transitive manifests to be merged. + manifest_values: A dictionary. Manifest values to substitute. + java_package: A string. Custom java package to insert in manifest package attribute. + busybox: A FilesToRunProvider. The ResourceProcessorBusyBox executable. + host_javabase: Target. The host javabase. + """ + if merge_type not in ["APPLICATION", "LIBRARY"]: + fail("Unexpected manifest merge type: " + merge_type) + + outputs = [out_file] + directs = [manifest] + transitives = [mergee_manifests] + + # Args for busybox + args = ctx.actions.args() + args.use_param_file("@%s", use_always = True) + args.add("--tool", "MERGE_MANIFEST") + args.add("--") + args.add("--manifest", manifest) + args.add_all( + "--mergeeManifests", + [mergee_manifests], + map_each = _mergee_manifests_flag, + ) + if manifest_values: + args.add( + "--manifestValues", + ",".join(["%s:%s" % (_escape_mv(k), _escape_mv(v)) for k, v in manifest_values.items()]), + ) + args.add("--mergeType", merge_type) + args.add("--customPackage", java_package) + args.add("--manifestOutput", out_file) + if out_log_file: + args.add("--log", out_log_file) + outputs.append(out_log_file) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = busybox, + arguments = [args], + inputs = depset(directs, transitive = transitives), + outputs = outputs, + mnemonic = "MergeManifests", + progress_message = "Merging Android Manifests in %s" % out_file.short_path, + ) + +def _process_databinding( + ctx, + out_databinding_info = None, + out_databinding_processed_resources = None, + databinding_resources_dirname = None, + resource_files = None, + java_package = None, + busybox = None, + host_javabase = None): + """Processes databinding for android_binary. + + Processes databinding declarations over resources, populates the databinding layout + info file, and generates new resources with databinding expressions stripped out. + + Args: + ctx: The context. + out_databinding_info: File. The output databinding layout info zip file. + out_databinding_processed_resources: List of Files. The generated databinding + processed resource files. + databinding_resources_dirname: String. The execution path to the directory where + the out_databinding_processed_resources are generated. + resource_files: List of Files. The resource files to be processed. + java_package: String. Java package for which java sources will be + generated. By default the package is inferred from the directory where + the BUILD file containing the rule is. + busybox: FilesToRunProvider. The ResourceBusyBox executable or + FilesToRunprovider + host_javabase: A Target. The host javabase. + """ + res_dirs = _get_unique_res_dirs(resource_files) + + args = ctx.actions.args() + args.add("--tool", "PROCESS_DATABINDING") + args.add("--") + args.add("--output_resource_directory", databinding_resources_dirname) + args.add_all(res_dirs, before_each = "--resource_root") + args.add("--dataBindingInfoOut", out_databinding_info) + args.add("--appId", java_package) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = busybox, + arguments = [args], + inputs = resource_files, + outputs = [out_databinding_info] + out_databinding_processed_resources, + mnemonic = "StarlarkProcessDatabinding", + progress_message = "Processing data binding", + ) + +def _make_generate_binay_r_flags(resources_node): + if not (resources_node.r_txt or resources_node.manifest): + return None + return ",".join( + [ + resources_node.r_txt.path if resources_node.r_txt else "", + resources_node.manifest.path if resources_node.manifest else "", + ], + ) + +def _generate_binary_r( + ctx, + out_class_jar = None, + r_txt = None, + manifest = None, + package_for_r = None, + final_fields = None, + resources_nodes = depset(), + transitive_r_txts = [], + transitive_manifests = [], + busybox = None, + host_javabase = None): + """Generate compiled resources class jar. + + Args: + ctx: The context. + out_class_jar: File. The output class jar file. + r_txt: File. The resource IDs outputted by linking resources in text. + manifest: File. The primary AndroidManifest.xml. + package_for_r: String. The Java package for the generated R class files. + final_fields: Bool. Whether fields get declared as final. + busybox: FilesToRunProvider. The ResourceBusyBox executable or + FilesToRunprovider + host_javabase: A Target. The host javabase. + """ + args = ctx.actions.args() + args.add("--tool", "GENERATE_BINARY_R") + args.add("--") + args.add("--primaryRTxt", r_txt) + args.add("--primaryManifest", manifest) + args.add("--packageForR", package_for_r) + args.add_all( + resources_nodes, + map_each = _make_generate_binay_r_flags, + before_each = "--library", + ) + if final_fields: + args.add("--finalFields") + else: + args.add("--nofinalFields") + + # TODO(b/154003916): support transitive "--library transitive_r_txt_path,transitive_manifest_path" flags + args.add("--classJarOutput", out_class_jar) + args.add("--targetLabel", str(ctx.label)) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = busybox, + arguments = [args], + inputs = depset([r_txt, manifest], transitive = transitive_r_txts + transitive_manifests), + outputs = [out_class_jar], + mnemonic = "StarlarkRClassGenerator", + progress_message = "Generating R classes", + ) + +def _make_aar( + ctx, + out_aar = None, + assets = [], + assets_dir = None, + resource_files = [], + class_jar = None, + r_txt = None, + manifest = None, + proguard_specs = [], + should_throw_on_conflict = False, + busybox = None, + host_javabase = None): + """Generate an android archive file. + + Args: + ctx: The context. + out_aar: File. The output AAR file. + assets: sequence of Files. A list of Android assets files to be processed. + assets_dir: String. The name of the assets directory. + resource_files: A list of Files. The resource files. + class_jar: File. The class jar file. + r_txt: File. The resource IDs outputted by linking resources in text. + manifest: File. The primary AndroidManifest.xml. + proguard_specs: List of File. The proguard spec files. + busybox: FilesToRunProvider. The ResourceBusyBox executable or + FilesToRunprovider + host_javabase: A Target. The host javabase. + should_throw_on_conflict: A boolean. Determines whether an error should be thrown + when a resource conflict occurs. + """ + args = ctx.actions.args() + args.add("--tool", "GENERATE_AAR") + args.add("--") + args.add( + "--mainData", + _make_resources_flag( + manifest = manifest, + assets = assets, + assets_dir = assets_dir, + resource_files = resource_files, + ), + ) + args.add("--manifest", manifest) + args.add("--rtxt", r_txt) + args.add("--classes", class_jar) + args.add("--aarOutput", out_aar) + args.add_all(proguard_specs, before_each = "--proguardSpec") + if should_throw_on_conflict: + args.add("--throwOnResourceConflict") + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = busybox, + arguments = [args], + inputs = ( + resource_files + + assets + + proguard_specs + + [r_txt, manifest, class_jar] + ), + outputs = [out_aar], + mnemonic = "StarlarkAARGenerator", + progress_message = "Generating AAR package for %s" % ctx.label, + ) + +busybox = struct( + compile = _compile, + merge_compiled = _merge_compiled, + validate_and_link = _validate_and_link, + merge_manifests = _merge_manifests, + package = _package, + parse = _parse, + merge_assets = _merge_assets, + make_resources_flag = _make_resources_flag, + process_databinding = _process_databinding, + generate_binary_r = _generate_binary_r, + make_aar = _make_aar, + + # Exposed for testing + mergee_manifests_flag = _mergee_manifests_flag, + get_unique_res_dirs = _get_unique_res_dirs, + sanitize_assets_dir = _sanitize_assets_dir, + extract_filters = _extract_filters, +) diff --git a/rules/common.bzl b/rules/common.bzl new file mode 100644 index 0000000..6e84559 --- /dev/null +++ b/rules/common.bzl @@ -0,0 +1,111 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel common library for the Android rules.""" + +load(":java.bzl", _java = "java") +load(":utils.bzl", "get_android_sdk", "get_android_toolchain", _log = "log") + +# TODO(ostonge): Remove once kotlin/jvm_library.internal.bzl +# is updated and released to use the java.resolve_package function +def _java_package(label, custom_package): + return _java.resolve_package_from_label(label, custom_package) + +# Validates that the packages listed under "deps" all have the given constraint. If a package +# does not have this attribute, an error is generated. +def _validate_constraints(targets, constraint): + for target in targets: + if JavaInfo in target: + if constraint not in java_common.get_constraints(target[JavaInfo]): + _log.error("%s: does not have constraint '%s'" % (target.label, constraint)) + +TARGET_DNE = "Target '%s' does not exist or is a file and is not allowed." + +def _check_rule(targets): + _validate_constraints(targets, "android") + +def _get_java_toolchain(ctx): + if not hasattr(ctx.attr, "_java_toolchain"): + _log.error("Missing _java_toolchain attr") + return ctx.attr._java_toolchain + +def _get_host_javabase(ctx): + if not hasattr(ctx.attr, "_host_javabase"): + _log.error("Missing _host_javabase attr") + return ctx.attr._host_javabase + +def _sign_apk(ctx, unsigned_apk, signed_apk, keystore = None, signing_keys = [], signing_lineage = None): + """Signs an apk. Usage of keystore is deprecated. Prefer using signing_keys.""" + inputs = [unsigned_apk] + signer_args = ctx.actions.args() + signer_args.add("sign") + + if signing_keys: + inputs.extend(signing_keys) + for i, key in enumerate(signing_keys): + if i > 0: + signer_args.add("--next-signer") + signer_args.add("--ks") + signer_args.add(key.path) + signer_args.add("--ks-pass") + signer_args.add("pass:android") + if signing_lineage: + inputs.append(signing_lineage) + signer_args.add("--lineage", signing_lineage.path) + elif keystore: + inputs.append(keystore) + signer_args.add("--ks", keystore.path) + signer_args.add("--ks-pass", "pass:android") + + signer_args.add("--v1-signing-enabled", ctx.fragments.android.apk_signing_method_v1) + signer_args.add("--v1-signer-name", "CERT") + signer_args.add("--v2-signing-enabled", ctx.fragments.android.apk_signing_method_v2) + signer_args.add("--out", signed_apk.path) + signer_args.add(unsigned_apk.path) + ctx.actions.run( + executable = get_android_sdk(ctx).apk_signer, + inputs = inputs, + outputs = [signed_apk], + arguments = [signer_args], + mnemonic = "ApkSignerTool", + progress_message = "Signing APK for %s" % unsigned_apk.path, + ) + return signed_apk + +def _filter_zip(ctx, in_zip, out_zip, filters = []): + """Creates a copy of a zip file with files that match filters.""" + args = ctx.actions.args() + args.add("-q") + args.add(in_zip.path) + args.add_all(filters) + args.add("--copy") + args.add("--out") + args.add(out_zip.path) + ctx.actions.run( + executable = get_android_toolchain(ctx).zip_tool.files_to_run, + arguments = [args], + inputs = [in_zip], + outputs = [out_zip], + mnemonic = "FilterZip", + progress_message = "Filtering %s" % in_zip.short_path, + ) + +common = struct( + check_rule = _check_rule, + get_host_javabase = _get_host_javabase, + get_java_toolchain = _get_java_toolchain, + filter_zip = _filter_zip, + java_package = _java_package, + sign_apk = _sign_apk, +) diff --git a/rules/data_binding.bzl b/rules/data_binding.bzl new file mode 100644 index 0000000..39923ec --- /dev/null +++ b/rules/data_binding.bzl @@ -0,0 +1,286 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel Android Data Binding.""" + +load(":utils.bzl", _utils = "utils") + +# Data Binding context attributes. +_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS = \ + "java_annotation_processor_additional_inputs" +_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS = \ + "java_annotation_processor_additional_outputs" +_JAVA_PLUGINS = "java_plugins" +_JAVA_SRCS = "java_srcs" +_JAVAC_OPTS = "javac_opts" +_PROVIDERS = "providers" + +DataBindingContextInfo = provider( + doc = "Contains data from processing Android Data Binding.", + fields = { + _JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS: ( + "Additional inputs required by the Java annotation processor." + ), + _JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS: ( + "Additional outputs produced by the Java annotation processor." + ), + _JAVA_PLUGINS: "Data Binding Java annotation processor", + _JAVA_SRCS: "Java sources required by the Java annotation processor.", + _JAVAC_OPTS: ( + "Additional Javac opts required by the Java annotation processor." + ), + _PROVIDERS: "The list of all providers to propagate.", + }, +) + +# Path used when resources have not been defined. +_NO_RESOURCES_PATH = "/tmp/no_resources" + +def _copy_annotation_file(ctx, output_dir, annotation_template): + annotation_out = ctx.actions.declare_file( + output_dir + "/android/databinding/layouts/DataBindingInfo.java", + ) + _utils.copy_file(ctx, annotation_template, annotation_out) + return annotation_out + +def _gen_sources(ctx, output_dir, java_package, deps, data_binding_exec): + layout_info = ctx.actions.declare_file(output_dir + "layout-info.zip") + class_info = ctx.actions.declare_file(output_dir + "class-info.zip") + srcjar = ctx.actions.declare_file(output_dir + "baseClassSrc.srcjar") + + args = ctx.actions.args() + args.add("-layoutInfoFiles", layout_info) + args.add("-package", java_package) + args.add("-classInfoOut", class_info) + args.add("-sourceOut", srcjar) + args.add("-zipSourceOutput", "true") + args.add("-useAndroidX", "false") + + class_infos = [] + for info in deps: + class_infos.extend(info.class_infos) + args.add_all(class_infos, before_each = "-dependencyClassInfoList") + + ctx.actions.run( + executable = data_binding_exec, + arguments = ["GEN_BASE_CLASSES", args], + inputs = class_infos + [layout_info], + outputs = [class_info, srcjar], + mnemonic = "GenerateDataBindingBaseClasses", + progress_message = ( + "GenerateDataBindingBaseClasses %s" % class_info.short_path + ), + ) + return srcjar, class_info, layout_info + +def _setup_dependent_lib_artifacts(ctx, output_dir, deps): + # DataBinding requires files in very specific locations. + # The following expand_template (copy actions) are moving the files + # to the correct locations. + dep_lib_artifacts = [] + for info in deps: + # Yes, DataBinding requires depsets iterations. + for artifact in (info.transitive_br_files.to_list() + + info.setter_stores + + info.class_infos): + # short_path might contain a parent directory reference if the + # databinding artifact is from an external repository (e.g. an aar + # from Maven). If that's the case, just remove the parent directory + # reference, otherwise the "dependent-lib-artifacts" directory will + # get removed by the "..". + path = artifact.short_path + if path.startswith("../"): + path = path[3:] + dep_lib_artifact = ctx.actions.declare_file( + output_dir + "dependent-lib-artifacts/" + path, + ) + + # Copy file to a location required by the DataBinding annotation + # processor. + # TODO(djwhang): Look into SymlinkAction. + if artifact.is_directory: + _utils.copy_dir(ctx, artifact, dep_lib_artifact) + else: + _utils.copy_file(ctx, artifact, dep_lib_artifact) + dep_lib_artifacts.append(dep_lib_artifact) + return dep_lib_artifacts + +def _get_javac_opts( + ctx, + java_package, + dependency_artifacts_dir, + aar_out_dir, + class_info_path, + layout_info_path, + deps): + java_packages = [] + for info in deps: + for label_and_java_package in info.label_and_java_packages: + java_packages.append(label_and_java_package.java_package) + + javac_opts = [] + javac_opts.append("-Aandroid.databinding.dependencyArtifactsDir=" + + dependency_artifacts_dir) + javac_opts.append("-Aandroid.databinding.aarOutDir=" + aar_out_dir) + javac_opts.append("-Aandroid.databinding.sdkDir=/not/used") + javac_opts.append("-Aandroid.databinding.artifactType=LIBRARY") + javac_opts.append("-Aandroid.databinding.exportClassListOutFile=" + + "/tmp/exported_classes") + javac_opts.append("-Aandroid.databinding.modulePackage=" + java_package) + javac_opts.append("-Aandroid.databinding.directDependencyPkgs=[%s]" % + ",".join(java_packages)) + + # The minimum Android SDK compatible with this rule. + # TODO(djwhang): This probably should be based on the actual min-sdk from + # the manifest, or an appropriate rule attribute. + javac_opts.append("-Aandroid.databinding.minApi=14") + javac_opts.append("-Aandroid.databinding.enableV2=1") + + javac_opts.append("-Aandroid.databinding.classLogDir=" + class_info_path) + javac_opts.append("-Aandroid.databinding.layoutInfoDir=" + layout_info_path) + return javac_opts + +def _process( + ctx, + resources_ctx = None, + defines_resources = False, + enable_data_binding = False, + java_package = None, + deps = [], + exports = [], + data_binding_exec = None, + data_binding_annotation_processor = None, + data_binding_annotation_template = None): + """Processes Android Data Binding. + + Args: + ctx: The context. + resources_ctx: The Android Resources context. + defines_resources: boolean. Determines whether resources were defined. + enable_data_binding: boolean. Determines whether Data Binding should be + enabled. + java_package: String. The Java package. + deps: sequence of DataBindingV2Info providers. A list of deps. Optional. + exports: sequence of DataBindingV2Info providers. A list of exports. + Optional. + data_binding_exec: The DataBinding executable. + data_binding_annotation_processor: JavaInfo. The JavaInfo for the + annotation processor. + data_binding_annotation_template: A file. Used to generate data binding + classes. + + Returns: + A DataBindingContextInfo provider. + """ + + # TODO(b/154513292): Clean up bad usages of context objects. + if resources_ctx: + defines_resources = resources_ctx.defines_resources + + # The Android Data Binding context object. + db_info = { + _JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS: [], + _JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS: [], + _JAVA_PLUGINS: [], + _JAVA_SRCS: [], + _JAVAC_OPTS: [], + _PROVIDERS: [], + } + + if not enable_data_binding: + db_info[_PROVIDERS] = [ + DataBindingV2Info( + databinding_v2_providers_in_deps = deps, + databinding_v2_providers_in_exports = exports, + ), + ] + return struct(**db_info) + + output_dir = "_migrated/databinding/%s/" % ctx.label.name + + db_info[_JAVA_SRCS].append(_copy_annotation_file( + ctx, + output_dir, + data_binding_annotation_template, + )) + db_info[_JAVA_PLUGINS].append(data_binding_annotation_processor) + + br_out = None + setter_store_out = None + class_info = None + layout_info = None + if defines_resources: + # Outputs of the Data Binding annotation processor. + br_out = ctx.actions.declare_file( + output_dir + "bin-files/%s-br.bin" % java_package, + ) + db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS].append(br_out) + setter_store_out = ctx.actions.declare_file( + output_dir + "bin-files/%s-setter_store.json" % java_package, + ) + db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS].append( + setter_store_out, + ) + + srcjar, class_info, layout_info = _gen_sources( + ctx, + output_dir, + java_package, + deps, + data_binding_exec, + ) + db_info[_JAVA_SRCS].append(srcjar) + db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS].append(class_info) + db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS].append( + layout_info, + ) + + dep_lib_artifacts = _setup_dependent_lib_artifacts(ctx, output_dir, deps) + db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS].extend( + dep_lib_artifacts, + ) + + db_info[_JAVAC_OPTS] = _get_javac_opts( + ctx, + java_package, + ( + br_out.path.rpartition(br_out.short_path)[0] + + ctx.label.package + + "/" + + output_dir + + "dependent-lib-artifacts" + ), + br_out.dirname, + class_info.path if class_info else _NO_RESOURCES_PATH, + layout_info.path if layout_info else _NO_RESOURCES_PATH, + deps, + ) + + db_info[_PROVIDERS] = [ + DataBindingV2Info( + setter_store_file = setter_store_out, + class_info_file = class_info, + br_file = br_out, + label = str(ctx.label), + java_package = java_package, + databinding_v2_providers_in_deps = deps, + databinding_v2_providers_in_exports = exports, + ), + ] + + return DataBindingContextInfo(**db_info) + +data_binding = struct( + process = _process, +) diff --git a/rules/data_binding_annotation_template.txt b/rules/data_binding_annotation_template.txt new file mode 100644 index 0000000..295397e --- /dev/null +++ b/rules/data_binding_annotation_template.txt @@ -0,0 +1,15 @@ +package android.databinding.layouts; + +import android.databinding.BindingBuildInfo; + +/** + * Template for the file that feeds data binding's annotation processor. The + * processor reads the values set here to generate .java files that link XML + * data binding declarations (from layoutInfoDir) to app code. + */ +@BindingBuildInfo( + buildId="not_used_here" // Adds incrementality, which Bazel already supports +) +public class DataBindingInfo { + /* This only exists for annotation processing. */ +} diff --git a/rules/flags/BUILD b/rules/flags/BUILD new file mode 100644 index 0000000..4895b09 --- /dev/null +++ b/rules/flags/BUILD @@ -0,0 +1,22 @@ +# Flags for Android rules and mobile-install + +load("@rules_android//rules/flags:flags.bzl", "flags") +load("@rules_android//rules/flags:flag_defs.bzl", "define_flags") +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + + +licenses(["notice"]) + +filegroup( + name = "all_files", + srcs = glob(["**"]), +) + +bzl_library( + name = "bzl", + srcs = glob(["*.bzl"]), +) + +define_flags() + +flags.FLAGS() diff --git a/rules/flags/flag_defs.bzl b/rules/flags/flag_defs.bzl new file mode 100644 index 0000000..cecb40a --- /dev/null +++ b/rules/flags/flag_defs.bzl @@ -0,0 +1,92 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Flag definitions.""" + +load("@rules_android//rules/flags:flags.bzl", "flags") + +def define_flags(): + flags.DEFINE_bool( + name = "android_enable_res_v3", + default = False, + description = "Enable Resource Processing Pipeline v3.", + ) + + flags.DEFINE_bool( + name = "use_direct_deploy", + default = False, + description = "Enable direct deployment.", + ) + + flags.DEFINE_int( + name = "num_dex_shards", + default = 16, + description = "Number of dex shards to use for mobile-install.", + ) + + flags.DEFINE_bool( + name = "use_custom_dex_shards", + default = False, + description = "Whether to use custom dex shard value for mobile-install.", + ) + + flags.DEFINE_bool_group( + name = "mi_v3", + default = True, + description = "Enable mobile-install v3.", + flags = [ + # TODO(b/160897244): resv3 temporarily disabled while Starlark + # resource processing is implemented and rolled out + # ":android_enable_res_v3", + ":use_custom_dex_shards", + ":use_direct_deploy", + ], + ) + + flags.DEFINE_bool_group( + name = "mi_dogfood", + default = False, + description = "Opt-in to mobile-install dogfood track.", + flags = [ + ], + ) + + flags.DEFINE_bool( + name = "enable_splits", + default = False, + description = "Build and install split apks if the device supports them.", + ) + + flags.DEFINE_bool( + name = "use_adb_root", + default = True, + description = "Restart adb with root permissions.", + ) + + flags.DEFINE_bool( + name = "mi_desugar_java8_libs", + default = False, + description = "Set True with --config=android_java8_libs", + ) + + flags.DEFINE_bool( + name = "debug", + default = False, + description = "", + ) + + flags.EXPOSE_native_bool( + name = "stamp", + description = "Accesses the native --stamp CLI flag", + ) diff --git a/rules/flags/flags.bzl b/rules/flags/flags.bzl new file mode 100644 index 0000000..e6e25a6 --- /dev/null +++ b/rules/flags/flags.bzl @@ -0,0 +1,255 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel Flags.""" + +load("@rules_android//rules:utils.bzl", "utils") + +_BoolFlagInfo = provider( + doc = "Provides information about a boolean flag", + fields = dict( + name = "flag name", + value = "flag value", + explicit = "whether value was set explicitly", + ), +) +_BoolFlagGroupInfo = provider( + doc = "Provides information about a boolean flag group", + fields = dict( + name = "group name", + value = "group value", + flags = "flag names that belong to this group", + ), +) +_IntFlagInfo = provider( + doc = "Provides information about an integer flag", + fields = dict( + name = "flag name", + value = "flag value", + ), +) +_NativeBoolFlagInfo = provider( + doc = "Provides information about a native boolean flag", + fields = dict( + name = "flag name, the name of the native flag being accessed.", + value = "flag value, derived from config_setting targets that access the value", + ), +) +FlagsInfo = provider( + doc = "Provides all flags", +) + +def _native_bool_impl(ctx): + return _NativeBoolFlagInfo( + name = ctx.label.name, + value = ctx.attr.value, + ) + +native_bool_flag = rule( + implementation = _native_bool_impl, + attrs = dict( + value = attr.bool(mandatory = True), + ), + provides = [_NativeBoolFlagInfo], +) + +def native_bool_flag_macro(name, description): + """Provides access to a native boolean flag from Starlark. + + Args: + name: The name of the native flag to access. + description: The description of the flag. + """ + native.config_setting( + name = name + "_on", + values = {name: "True"}, + ) + native.config_setting( + name = name + "_off", + values = {name: "False"}, + ) + native_bool_flag( + name = name, + value = select({ + (":" + name + "_on"): True, + (":" + name + "_off"): False, + }), + ) + +def _get_bool(v): + v = v.lower() + if v == "true": + return True + if v == "false": + return False + fail("Unknown bool: " + v) + +def _bool_impl(ctx): + if ctx.label.name in ctx.var: + value = _get_bool(ctx.var[ctx.label.name]) + return _BoolFlagInfo( + name = ctx.label.name, + value = value, + explicit = True, + ) + return _BoolFlagInfo( + name = ctx.label.name, + value = ctx.attr.default, + explicit = False, + ) + +bool_flag = rule( + implementation = _bool_impl, + attrs = dict( + default = attr.bool( + mandatory = True, + ), + description = attr.string( + mandatory = True, + ), + ), + provides = [_BoolFlagInfo], +) + +def _bool_group_impl(ctx): + if ctx.label.name in ctx.var: + value = _get_bool(ctx.var[ctx.label.name]) + return _BoolFlagGroupInfo( + name = ctx.label.name, + value = value, + flags = [f[_BoolFlagInfo].name for f in ctx.attr.flags], + ) + return _BoolFlagGroupInfo( + name = ctx.label.name, + value = ctx.attr.default, + flags = [f[_BoolFlagInfo].name for f in ctx.attr.flags], + ) + +bool_flag_group = rule( + implementation = _bool_group_impl, + attrs = dict( + default = attr.bool( + mandatory = True, + ), + description = attr.string( + mandatory = True, + ), + flags = attr.label_list( + mandatory = True, + providers = [_BoolFlagInfo], + ), + ), + provides = [_BoolFlagGroupInfo], +) + +def _int_impl(ctx): + if ctx.label.name in ctx.var: + value = int(ctx.var[ctx.label.name]) + else: + value = ctx.attr.default + return _IntFlagInfo( + name = ctx.label.name, + value = value, + ) + +int_flag = rule( + implementation = _int_impl, + attrs = dict( + default = attr.int( + mandatory = True, + ), + description = attr.string( + mandatory = True, + ), + ), + provides = [_IntFlagInfo], +) + +def _flags_impl_internal(bool_flags, bool_flag_groups, int_flags, native_bool_flags): + flags = dict() + + # For each group, set all flags to the group value + for fg in bool_flag_groups: + for f in fg.flags: + if f in flags: + fail("Flag '%s' referenced in multiple flag groups" % f) + flags[f] = fg.value + + # Set booleans + for b in bool_flags: + # Always set explicitly specified flags + if b.explicit: + flags[b.name] = b.value + # If not explicit, only set when not set by a group + + elif b.name not in flags: + flags[b.name] = b.value + + # Set ints + for i in int_flags: + flags[i.name] = i.value + + # Set native bool flags + for n in native_bool_flags: + if n.name in flags: + fail("Flag '%s' defined as both native and non-native flag type" % n.name) + flags[n.name] = n.value + + return FlagsInfo(**flags) + +def _flags_impl(ctx): + return _flags_impl_internal( + utils.collect_providers(_BoolFlagInfo, ctx.attr.targets), + utils.collect_providers(_BoolFlagGroupInfo, ctx.attr.targets), + utils.collect_providers(_IntFlagInfo, ctx.attr.targets), + utils.collect_providers(_NativeBoolFlagInfo, ctx.attr.targets), + ) + +flags_rule = rule( + implementation = _flags_impl, + attrs = dict( + targets = attr.label_list(), + ), +) + +def _flags_macro(): + flags_rule( + name = "flags", + targets = native.existing_rules().keys(), + visibility = ["//visibility:public"], + ) + +def _get_flags(ctx): + return ctx.attr._flags[FlagsInfo] + +flags = struct( + DEFINE_bool = bool_flag, + DEFINE_bool_group = bool_flag_group, + DEFINE_int = int_flag, + EXPOSE_native_bool = native_bool_flag_macro, + FLAGS = _flags_macro, + FlagsInfo = FlagsInfo, + get = _get_flags, +) + +exported_for_test = struct( + BoolFlagGroupInfo = _BoolFlagGroupInfo, + BoolFlagInfo = _BoolFlagInfo, + IntFlagInfo = _IntFlagInfo, + NativeBoolFlagInfo = _NativeBoolFlagInfo, + bool_impl = _bool_impl, + flags_impl_internal = _flags_impl_internal, + int_impl = _int_impl, + native_bool_flag_macro = native_bool_flag_macro, +) diff --git a/rules/idl.bzl b/rules/idl.bzl new file mode 100644 index 0000000..8dc52d3 --- /dev/null +++ b/rules/idl.bzl @@ -0,0 +1,264 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel Android IDL library for the Android rules.""" + +load(":java.bzl", _java = "java") +load(":path.bzl", _path = "path") +load(":utils.bzl", _log = "log") + +_AIDL_TOOLCHAIN_MISSING_ERROR = ( + "IDL sources provided without the Android IDL toolchain." +) + +_AIDL_JAVA_ROOT_UNDETERMINABLE_ERROR = ( + "Cannot determine java/javatests root for import %s." +) + +IDLContextInfo = provider( + doc = "Contains data from processing Android IDL.", + fields = dict( + idl_srcs = "List of IDL sources", + idl_import_root = "IDL import root", + idl_java_srcs = "List of IDL Java sources", + idl_deps = + "List of IDL targets required for Java compilation, Proguard, etc.", + providers = "The list of all providers to propagate.", + ), +) + +def _gen_java_from_idl( + ctx, + out_idl_java_src = None, + idl_src = None, + transitive_idl_import_roots = [], + transitive_idl_imports = [], + transitive_idl_preprocessed = [], + aidl = None, + aidl_lib = None, + aidl_framework = None): + args = ctx.actions.args() + args.add("-b") + args.add_all(transitive_idl_import_roots, format_each = "-I%s") + args.add(aidl_framework, format = "-p%s") + args.add_all(transitive_idl_preprocessed, format_each = "-p%s") + args.add(idl_src) + args.add(out_idl_java_src) + + ctx.actions.run( + executable = aidl, + arguments = [args], + inputs = depset( + [aidl_framework], + transitive = [ + aidl_lib.files, + transitive_idl_imports, + transitive_idl_preprocessed, + ], + ), + outputs = [out_idl_java_src], + mnemonic = "AndroidIDLGenerate", + progress_message = "Android IDL generation %s" % idl_src.path, + ) + +def _get_idl_import_root_path( + package, + idl_import_root, + idl_file_root_path): + package_path = _path.relative( + idl_file_root_path, + package, + ) + return _path.relative( + package_path, + idl_import_root, + ) + +def _collect_unique_idl_import_root_paths( + package, + idl_import_root, + idl_imports): + idl_import_roots = dict() + for idl_import in idl_imports: + idl_import_roots[_get_idl_import_root_path( + package, + idl_import_root, + idl_import.root.path, + )] = True + return sorted(idl_import_roots.keys()) + +def _collect_unique_java_roots(idl_imports): + idl_import_roots = dict() + for idl_import in idl_imports: + java_root = _java.root(idl_import.path) + if not java_root: + _log.error(_AIDL_JAVA_ROOT_UNDETERMINABLE_ERROR % idl_import.path) + idl_import_roots[java_root] = True + return sorted(idl_import_roots.keys()) + +def _determine_idl_import_roots( + package, + idl_import_root = None, + idl_imports = []): + if idl_import_root == None: + return _collect_unique_java_roots(idl_imports) + return _collect_unique_idl_import_root_paths( + package, + idl_import_root, + idl_imports, + ) + +def _process( + ctx, + idl_srcs = [], + idl_parcelables = [], + idl_import_root = None, + idl_preprocessed = [], + deps = [], + exports = [], + aidl = None, + aidl_lib = None, + aidl_framework = None): + """Processes Android IDL. + + Args: + ctx: The context. + idl_srcs: sequence of Files. A list of the aidl source files to be + processed into Java source files and then compiled. Optional. + idl_parcelables: sequence of Files. A list of Android IDL definitions to + supply as imports. These files will be made available as imports for any + android_library target that depends on this library, directly or via its + transitive closure, but will not be translated to Java or compiled. + + Only .aidl files that correspond directly to .java sources in this library + should be included (e.g. custom implementations of Parcelable), otherwise + idl_srcs should be used. + + These files must be placed appropriately for the aidl compiler to find + them. See the description of idl_import_root for information about what + this means. Optional. + idl_import_root: string. Package-relative path to the root of the java + package tree containing idl sources included in this library. This path + will be used as the import root when processing idl sources that depend on + this library. + + When idl_import_root is specified, both idl_parcelables and idl_srcs must + be at the path specified by the java package of the object they represent + under idl_import_root. When idl_import_root is not specified, both + idl_parcelables and idl_srcs must be at the path specified by their + package under a Java root. Optional. + idl_preprocessed: sequence of Files. A list of preprocessed Android IDL + definitions to supply as imports. These files will be made available as + imports for any android_library target that depends on this library, + directly or via its transitive closure, but will not be translated to + Java or compiled. + + Only preprocessed .aidl files that correspond directly to .java sources + in this library should be included (e.g. custom implementations of + Parcelable), otherwise use idl_srcs for Android IDL definitions that + need to be translated to Java interfaces and use idl_parcelable for + non-preprcessed AIDL files. Optional. + deps: sequence of Targets. A list of dependencies. Optional. + exports: sequence of Targets. A list of exports. Optional. + aidl: Target. A target pointing to the aidl executable to be used for + Java code generation from *.idl source files. Optional, unless idl_srcs + are supplied. + aidl_lib: Target. A target pointing to the aidl_lib library required + during Java compilation when Java code is generated from idl sources. + Optional, unless idl_srcs are supplied. + aidl_framework: Target. A target pointing to the aidl framework. Optional, + unless idl_srcs are supplied. + + Returns: + A IDLContextInfo provider. + """ + if idl_srcs and not (aidl and aidl_lib and aidl_framework): + _log.error(_AIDL_TOOLCHAIN_MISSING_ERROR) + + transitive_idl_import_roots = [] + transitive_idl_imports = [] + transitive_idl_preprocessed = [] + for dep in deps + exports: + transitive_idl_import_roots.append(dep.transitive_idl_import_roots) + transitive_idl_imports.append(dep.transitive_idl_imports) + transitive_idl_preprocessed.append(dep.transitive_idl_preprocessed) + + idl_java_srcs = [] + for idl_src in idl_srcs: + idl_java_src = ctx.actions.declare_file( + ctx.label.name + "_aidl/" + idl_src.path.replace(".aidl", ".java"), + ) + idl_java_srcs.append(idl_java_src) + _gen_java_from_idl( + ctx, + out_idl_java_src = idl_java_src, + idl_src = idl_src, + transitive_idl_import_roots = depset( + _determine_idl_import_roots( + ctx.label.package, + idl_import_root, + idl_parcelables + idl_srcs, + ), + transitive = transitive_idl_import_roots, + order = "preorder", + ), + transitive_idl_imports = depset( + idl_parcelables + idl_srcs, + transitive = transitive_idl_imports, + order = "preorder", + ), + transitive_idl_preprocessed = depset( + transitive = transitive_idl_preprocessed, + ), + aidl = aidl, + aidl_lib = aidl_lib, + aidl_framework = aidl_framework, + ) + + return IDLContextInfo( + idl_srcs = idl_srcs, + idl_import_root = idl_import_root, + idl_java_srcs = idl_java_srcs, + idl_deps = [aidl_lib] if idl_java_srcs else [], + providers = [ + # TODO(b/146216105): Make this a Starlark provider. + AndroidIdlInfo( + depset( + _determine_idl_import_roots( + ctx.label.package, + idl_import_root, + idl_parcelables + idl_srcs + idl_preprocessed, + ), + transitive = transitive_idl_import_roots, + order = "preorder", + ), + depset( + idl_parcelables + idl_srcs + idl_preprocessed, + transitive = transitive_idl_imports, + order = "preorder", + ), + depset(), # TODO(b/146216105): Delete this field once in Starlark. + depset(idl_preprocessed, transitive = transitive_idl_preprocessed), + ), + ], + ) + +idl = struct( + process = _process, +) + +# Visible for testing. +testing = struct( + get_idl_import_root_path = _get_idl_import_root_path, +) diff --git a/rules/intellij.bzl b/rules/intellij.bzl new file mode 100644 index 0000000..c870b1b --- /dev/null +++ b/rules/intellij.bzl @@ -0,0 +1,165 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Common methods for use by the IntelliJ Aspect.""" + +load(":java.bzl", _java = "java") +load(":utils.bzl", _utils = "utils") + +def _extract_idl_jars( + ctx, + idl_java_srcs = [], + jar = None, + manifest_proto = None, + out_srcjar = None, + out_jar = None, + idlclass = None, + host_javabase = None): + """Extracts the idl class and src jars.""" + args = ctx.actions.args() + args.add("--class_jar", jar) + args.add("--manifest_proto", manifest_proto) + args.add("--output_class_jar", out_jar) + args.add("--output_source_jar", out_srcjar) + args.add("--temp_dir", out_jar.dirname) + args.add_all(idl_java_srcs) + + _java.run( + ctx = ctx, + host_javabase = host_javabase, + executable = idlclass, + arguments = [args], + inputs = idl_java_srcs + [jar, manifest_proto], + outputs = [out_srcjar, out_jar], + mnemonic = "AndroidIdlJars", + progress_message = "Building idl jars %s" % out_jar.path, + ) + +def _make_android_ide_info( + ctx, + idl_ctx = None, + resources_ctx = None, + defines_resources = False, + java_package = None, + manifest = None, + merged_manifest = None, + resources_apk = None, + idl_import_root = None, + idl_srcs = [], + idl_java_srcs = [], + java_info = None, + r_jar = None, + signed_apk = None, + aar = None, + apks_under_test = [], + native_libs = dict(), + idlclass = None, + host_javabase = None): + # TODO(b/154513292): Clean up bad usages of context objects. + if idl_ctx: + idl_import_root = idl_ctx.idl_import_root + idl_srcs = idl_ctx.idl_srcs + idl_java_srcs = idl_ctx.idl_java_srcs + if resources_ctx: + defines_resources = resources_ctx.defines_resources + merged_manifest = resources_ctx.merged_manifest + resources_apk = resources_ctx.resources_apk + + if not defines_resources: + java_package = None + merged_manifest = None + + # Extracts idl related classes from the jar and creates a src jar + # for the idl generated java. + idl_jar = None + idl_srcjar = None + + # TODO(djwhang): JavaInfo.outputs.jar.manifest_proto is not created by + # Kotlin compile. Determine if this is the same manifest_proto produced + # by turbine, this could be pulled during annotation processing. + jar = _utils.only(java_info.outputs.jars) + if idl_java_srcs and jar.manifest_proto: + idl_jar = ctx.actions.declare_file("lib%s-idl.jar" % ctx.label.name) + idl_srcjar = \ + ctx.actions.declare_file("lib%s-idl.srcjar" % ctx.label.name) + + jar = _utils.only(java_info.outputs.jars) + _extract_idl_jars( + ctx, + idl_java_srcs = idl_java_srcs, + jar = jar.class_jar, + manifest_proto = jar.manifest_proto, + out_jar = idl_jar, + out_srcjar = idl_srcjar, + idlclass = idlclass, + host_javabase = host_javabase, + ) + + return AndroidIdeInfo( + java_package, + manifest, + merged_manifest, + idl_import_root, + idl_srcs, + idl_java_srcs, + idl_srcjar, + idl_jar, + defines_resources, + r_jar, + resources_apk, + signed_apk, + aar, + apks_under_test, + native_libs, + ) + +def _make_legacy_android_provider(android_ide_info): + # Create the ClassJar "object" for the target.android.idl.output field. + if android_ide_info.idl_class_jar: + idl_class_jar = struct( + class_jar = android_ide_info.idl_class_jar, + ijar = None, + source_jar = android_ide_info.idl_source_jar, + ) + else: + idl_class_jar = None + + return struct( + aar = android_ide_info.aar, + apk = android_ide_info.signed_apk, + apks_under_test = android_ide_info.apks_under_test, + defines_resources = android_ide_info.defines_android_resources, + idl = struct( + import_root = android_ide_info.idl_import_root, + sources = android_ide_info.idl_srcs, + generated_java_files = android_ide_info.idl_generated_java_files, + output = idl_class_jar, + ), + java_package = android_ide_info.java_package, + manifest = android_ide_info.manifest, + merged_manifest = android_ide_info.generated_manifest, + native_libs = android_ide_info.native_libs, + resource_apk = android_ide_info.resource_apk, + resource_jar = android_ide_info.resource_jar, + ) + +intellij = struct( + make_android_ide_info = _make_android_ide_info, + make_legacy_android_provider = _make_legacy_android_provider, +) + +# Only visible for testing. +testing = struct( + extract_idl_jars = _extract_idl_jars, +) diff --git a/rules/java.bzl b/rules/java.bzl new file mode 100644 index 0000000..7b23b35 --- /dev/null +++ b/rules/java.bzl @@ -0,0 +1,447 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel Java APIs for the Android rules.""" + +load(":path.bzl", _path = "path") +load(":utils.bzl", "log") + +_ANDROID_CONSTRAINT_MISSING_ERROR = ( + "A list of constraints provided without the 'android' constraint." +) + +def _segment_idx(path_segments): + """Finds the index of the segment in the path that preceeds the source root. + + Args: + path_segments: A list of strings, where each string is the segment of a + filesystem path. + + Returns: + An index to the path segment that represents the Java segment or -1 if + none found. + """ + if _path.is_absolute(path_segments[0]): + log.error("path must not be absolute: %s" % _path.join(path_segments)) + + root_idx = -1 + for idx, segment in enumerate(path_segments): + if segment in ["java", "javatests", "src", "testsrc"]: + root_idx = idx + break + if root_idx < 0: + return root_idx + + is_src = path_segments[root_idx] == "src" + check_maven_idx = root_idx if is_src else -1 + if root_idx == 0 or is_src: + # Check for a nested root directory. + for idx in range(root_idx + 1, len(path_segments) - 2): + segment = path_segments[idx] + if segment == "src" or (is_src and segment in ["java", "javatests"]): + next_segment = path_segments[idx + 1] + if next_segment in ["com", "org", "net"]: + root_idx = idx + elif segment == "src": + check_maven_idx = idx + break + + if check_maven_idx >= 0 and check_maven_idx + 2 < len(path_segments): + next_segment = path_segments[check_maven_idx + 1] + if next_segment in ["main", "test"]: + next_segment = path_segments[check_maven_idx + 2] + if next_segment in ["java", "resources"]: + root_idx = check_maven_idx + 2 + return root_idx + +def _resolve_package(path): + """Determines the Java package name from the given path. + + Examples: + "{workspace}/java/foo/bar/wiz" -> "foo.bar.wiz" + "{workspace}/javatests/foo/bar/wiz" -> "foo.bar.wiz" + + Args: + path: A string, representing a file path. + + Returns: + A string representing a Java package name or None if could not be + determined. + """ + path_segments = _path.split(path.partition(":")[0]) + java_idx = _segment_idx(path_segments) + if java_idx < 0: + return None + else: + return ".".join(path_segments[java_idx + 1:]) + +def _resolve_package_from_label( + label, + custom_package = None, + fallback = True): + """Resolves the Java package from a Label. + + When no legal Java package can be resolved from the label, None will be + returned unless fallback is specified. + + When a fallback is requested, a not safe for Java compilation package will + be returned. The fallback value will be derrived by taking the label.package + and replacing all path separators with ".". + """ + if custom_package: + return custom_package + + # For backwards compatibility, also include directories + # from the label's name + # Ex: "//foo/bar:java/com/google/baz" is a legal one and + # results in "com.google" + label_path = _path.join( + [label.package] + + _path.split(label.name)[:-1], + ) + java_package = _resolve_package(label_path) + + if java_package != None: # "" is a valid result. + return java_package + + if fallback: + return label.package.replace("/", ".") + + return None + +def _root(path): + """Determines the Java root from the given path. + + Examples: + "{workspace}/java/foo/bar/wiz" -> "{workspace}/java" + "{workspace}/javatests/foo/bar/wiz" -> "{workspace}/javatests" + "java/foo/bar/wiz" -> "java" + "javatests/foo/bar/wiz" -> "javatests" + + Args: + path: A string, representing a file path. + + Returns: + A string representing the Java root path or None if could not be + determined. + """ + path_segments = _path.split(path.partition(":")[0]) + java_idx = _segment_idx(path_segments) + if java_idx < 0: + return None + else: + return _path.join(path_segments[0:java_idx + 1]) + +def _check_for_invalid_java_package(java_package): + return "-" in java_package or len(java_package.split(".")) < 2 + +def _invalid_java_package(custom_package, java_package): + """Checks if the given java package is invalid. + + Only checks if either custom_package or java_package contains the + illegal character "-" or if they are composed of only one word. + Only checks java_package if custom_package is an empty string or None. + + Args: + custom_package: string. Java package given as an attribute to a rule to override + the java_package. + java_package: string. Java package inferred from the directory where the BUILD + containing the rule is. + + Returns: + A boolean. True if custom_package or java_package contains "-" or is only one word. + Only checks java_package if custom_package is an empty string or None. + """ + return ( + (custom_package and _check_for_invalid_java_package(custom_package)) or + (not custom_package and _check_for_invalid_java_package(java_package)) + ) + +# The Android specific Java compile. +def _compile_android( + ctx, + output_jar, + output_srcjar = None, + srcs = [], + resources = [], + javac_opts = [], + r_java = None, + deps = [], + exports = [], + plugins = [], + exported_plugins = [], + annotation_processor_additional_outputs = [], + annotation_processor_additional_inputs = [], + enable_deps_without_srcs = False, + neverlink = False, + constraints = ["android"], + strict_deps = "Error", + java_toolchain = None): + """Compiles the Java and IDL sources for Android. + + Args: + ctx: The context. + output_jar: File. The artifact to place the compilation unit. + output_srcjar: File. The artifact to place the sources of the compilation + unit. Optional. + srcs: sequence of Files. A list of files and jars to be compiled. + resources: sequence of Files. Will be added to the output jar - see + java_library.resources. Optional. + javac_opts: sequence of strings. A list of the desired javac options. + Optional. + r_java: JavaInfo. The R.jar dependency. Optional. + deps: sequence of JavaInfo providers. A list of dependencies. Optional. + exports: sequence of JavaInfo providers. A list of exports. Optional. + plugins: sequence of JavaInfo providers. A list of plugins. Optional. + exported_plugins: sequence of JavaInfo providers. A list of exported + plugins. Optional. + annotation_processor_additional_outputs: sequence of Files. A list of + files produced by an annotation processor. + annotation_processor_additional_inputs: sequence of Files. A list of + files consumed by an annotation processor. + enable_deps_without_srcs: Enables the behavior from b/14473160. + neverlink: Bool. Makes the compiled unit a compile-time only dependency. + constraints: sequence of Strings. A list of constraints, to constrain the + target. Optional. By default []. + strict_deps: string. A string that specifies how to handle strict deps. + Possible values: 'OFF', 'ERROR','WARN' and 'DEFAULT'. For more details + see https://docs.bazel.build/versions/master/user-manual.html#flag--strict_java_deps. + By default 'ERROR'. + java_toolchain: The java_toolchain Target. + host_javabase: The host_javabase Target. + + Returns: + A JavaInfo provider representing the Java compilation. + """ + if "android" not in constraints: + log.error(_ANDROID_CONSTRAINT_MISSING_ERROR) + + if not srcs: + if deps and enable_deps_without_srcs: + # TODO(b/122039567): Produces a JavaInfo that exports the deps, but + # not the plugins. To reproduce the "deps without srcs" bug, + # b/14473160, behavior in Starlark. + exports = exports + [ + android_common.enable_implicit_sourceless_deps_exports_compatibility(dep) + for dep in deps + ] + if not exports: + # Add a "no-op JavaInfo" to propagate the exported_plugins when + # deps or exports have not been specified by the target and + # additionally forces java_common.compile method to create the + # empty output jar and srcjar when srcs have not been specified. + noop_java_info = java_common.merge([]) + exports = exports + [noop_java_info] + + r_java_info = [r_java] if r_java else [] + + java_info = _compile( + ctx, + output_jar, + output_srcjar = output_srcjar, + srcs = srcs, + resources = resources, + javac_opts = javac_opts, + deps = r_java_info + deps, + # In native, the JavaInfo exposes two Jars as compile-time deps, the + # compiled sources and the Android R.java jars. To simulate this + # behavior, the JavaInfo of the R.jar is also exported. + exports = r_java_info + exports, + plugins = plugins, + exported_plugins = exported_plugins, + annotation_processor_additional_outputs = ( + annotation_processor_additional_outputs + ), + annotation_processor_additional_inputs = ( + annotation_processor_additional_inputs + ), + neverlink = neverlink, + constraints = constraints, + strict_deps = strict_deps, + java_toolchain = java_toolchain, + ) + return java_info + +def _compile( + ctx, + output_jar, + output_srcjar = None, + srcs = [], + resources = [], + javac_opts = [], + deps = [], + exports = [], + plugins = [], + exported_plugins = [], + annotation_processor_additional_outputs = [], + annotation_processor_additional_inputs = [], + neverlink = False, + constraints = [], + strict_deps = "Error", + java_toolchain = None): + """Compiles the Java and IDL sources for Android. + + Args: + ctx: The context. + output_jar: File. The artifact to place the compilation unit. + output_srcjar: File. The artifact to place the sources of the compilation + unit. Optional. + srcs: sequence of Files. A list of files and jars to be compiled. + resources: sequence of Files. Will be added to the output jar - see + java_library.resources. Optional. + javac_opts: sequence of strings. A list of the desired javac options. + Optional. + deps: sequence of JavaInfo providers. A list of dependencies. Optional. + exports: sequence of JavaInfo providers. A list of exports. Optional. + plugins: sequence of JavaInfo providers. A list of plugins. Optional. + exported_plugins: sequence of JavaInfo providers. A list of exported + plugins. Optional. + annotation_processor_additional_outputs: sequence of Files. A list of + files produced by an annotation processor. + annotation_processor_additional_inputs: sequence of Files. A list of + files consumed by an annotation processor. + resources: sequence of Files. Will be added to the output jar - see + java_library.resources. Optional. + neverlink: Bool. Makes the compiled unit a compile-time only dependency. + constraints: sequence of Strings. A list of constraints, to constrain the + target. Optional. By default []. + strict_deps: string. A string that specifies how to handle strict deps. + Possible values: 'OFF', 'ERROR','WARN' and 'DEFAULT'. For more details + see https://docs.bazel.build/versions/master/user-manual.html#flag--strict_java_deps. + By default 'ERROR'. + java_toolchain: The java_toolchain Target. + host_javabase: The host_javabase Target. + + Returns: + A JavaInfo provider representing the Java compilation. + """ + + # Split javac opts. + opts = [] + for opt in javac_opts: + opts.extend(opt.split(" ")) + + # Separate the sources *.java from *.srcjar. + source_files = [] + source_jars = [] + for src in srcs: + if src.path.endswith(".srcjar"): + source_jars.append(src) + else: + source_files.append(src) + + return java_common.compile( + ctx, + output = output_jar, + output_source_jar = output_srcjar, + source_files = source_files, + source_jars = source_jars, + resources = resources, + javac_opts = opts, + deps = deps, + exports = exports, + plugins = plugins, + exported_plugins = exported_plugins, + annotation_processor_additional_outputs = ( + annotation_processor_additional_outputs + ), + annotation_processor_additional_inputs = ( + annotation_processor_additional_inputs + ), + neverlink = neverlink, + strict_deps = strict_deps, + java_toolchain = java_toolchain[java_common.JavaToolchainInfo], + ) + +def _singlejar( + ctx, + inputs, + output, + mnemonic = "SingleJar", + progress_message = "Merge into a single jar.", + exclude_build_data = False, + java_toolchain = None): + args = ctx.actions.args() + args.add("--output") + args.add(output) + args.add("--compression") + args.add("--normalize") + if exclude_build_data: + args.add("--exclude_build_data") + args.add("--warn_duplicate_resources") + if inputs: + args.add("--sources") + args.add_all(inputs) + + ctx.actions.run( + executable = java_toolchain.java_toolchain.single_jar, + arguments = [args], + inputs = inputs, + outputs = [output], + mnemonic = mnemonic, + progress_message = progress_message, + ) + +def _run( + ctx, + host_javabase, + **args): + """Run a java binary + + Args: + ctx: The context. + host_javabase: Target. The host_javabase. + **args: Additional arguments to pass to ctx.actions.run(). Some will get modified. + """ + + if type(ctx) != "ctx": + fail("Expected type ctx for argument ctx, got %s" % type(ctx)) + + if type(host_javabase) != "Target": + fail("Expected type Target for argument host_javabase, got %s" % type(host_javabase)) + + # executable should be a File or a FilesToRunProvider + jar = args.get("executable") + if type(jar) == "FilesToRunProvider": + jar = jar.executable + elif type(jar) != "File": + fail("Expected type File or FilesToRunProvider for argument executable, got %s" % type(jar)) + + java_runtime = host_javabase[java_common.JavaRuntimeInfo] + args["executable"] = java_runtime.java_executable_exec_path + + # inputs can be a list or a depset of File + inputs = args.get("inputs", default = []) + if type(inputs) == type([]): + args["inputs"] = depset(direct = inputs + [jar], transitive = [java_runtime.files]) + else: # inputs is a depset + args["inputs"] = depset(direct = [jar], transitive = [inputs, java_runtime.files]) + + jar_args = ctx.actions.args() + jar_args.add("-jar", jar) + + args["arguments"] = [jar_args] + args.get("arguments", default = []) + + ctx.actions.run(**args) + +java = struct( + compile = _compile, + compile_android = _compile_android, + resolve_package = _resolve_package, + resolve_package_from_label = _resolve_package_from_label, + root = _root, + invalid_java_package = _invalid_java_package, + run = _run, + singlejar = _singlejar, +) diff --git a/rules/migration_tag_DONOTUSE.bzl b/rules/migration_tag_DONOTUSE.bzl new file mode 100644 index 0000000..539aca9 --- /dev/null +++ b/rules/migration_tag_DONOTUSE.bzl @@ -0,0 +1,25 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel component for the Android Skylark Migration.""" + +_MIGRATION_TAG = "__ANDROID_RULES_MIGRATION__" +_TAG_ATTR = "tags" + +def add_migration_tag(attrs): + if _TAG_ATTR in attrs and attrs[_TAG_ATTR] != None: + attrs[_TAG_ATTR] = attrs[_TAG_ATTR] + [_MIGRATION_TAG] + else: + attrs[_TAG_ATTR] = [_MIGRATION_TAG] + return attrs diff --git a/rules/path.bzl b/rules/path.bzl new file mode 100644 index 0000000..28d18f1 --- /dev/null +++ b/rules/path.bzl @@ -0,0 +1,102 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel Path APIs for the Android rules.""" + +# TODO(djwhang): Get the path separator in a platform agnostic manner. +_PATH_SEP = "/" +_TEST_SRCDIR = "${TEST_SRCDIR}" + +def _is_absolute(path): + # TODO(djwhang): This is not cross platform safe. Windows absolute paths + # do not start with "//", rather "C:\". + return path.startswith(_PATH_SEP) + +def _split(path): + return path.split(_PATH_SEP) + +def _join(path_segments): + return _PATH_SEP.join(path_segments) + +def _normalize_path(path, posix = False): + return _PATH_SEP.join( + _normalize_path_fragments( + path.split(_PATH_SEP), + posix = posix, + ), + ) + +def _normalize_path_fragments(path_fragments, posix = False): + normalized_path_fragments = [] + for idx, fragment in enumerate(path_fragments): + if not fragment and idx > 0: + continue + if fragment == ".": + continue + if fragment == ".." and not posix: + if normalized_path_fragments: + last = normalized_path_fragments.pop() + if last == ".." or last == "": + normalized_path_fragments.append(last) + else: + continue + normalized_path_fragments.append(fragment) + if len(normalized_path_fragments) == 1 and not normalized_path_fragments[0]: + normalized_path_fragments.append("") + return normalized_path_fragments + +def _relative_path(path1, path2): + if not path1 or _is_absolute(path2): + return path2 + + path1_fragments = _normalize_path_fragments(_split(path1)) + path2_fragments = _normalize_path_fragments(_split(path2)) + path1_idx = len(path1_fragments) # index move backwards + path2_idx = -1 + for idx, fragment in enumerate(path2_fragments): + if fragment == "..": + path1_idx -= 1 + else: + path2_idx = idx + break + + relative_path_fragments = [] + if path1_idx >= 0: + relative_path_fragments.extend(path1_fragments[:path1_idx]) + if path2_idx >= 0: + relative_path_fragments.extend(path2_fragments[path2_idx:]) + return _join(_normalize_path_fragments(relative_path_fragments)) + +def _make_test_srcdir_path(ctx, *path_fragments): + """Creates a filepath relative to TEST_SRCDIR. + + Args: + ctx: Starlark context. + *path_fragments: Directories/file to join into a single path. + Returns: + A filepath that's spearated by the host's filepath separator. + """ + fragments = [_TEST_SRCDIR, ctx.workspace_name] + for path_fragment in path_fragments: + fragments += _normalize_path_fragments(_split(path_fragment)) + return _join(fragments) + +path = struct( + is_absolute = _is_absolute, + join = _join, + normalize = _normalize_path, + relative = _relative_path, + split = _split, + make_test_srcdir_path = _make_test_srcdir_path, +) diff --git a/rules/platforms/BUILD b/rules/platforms/BUILD new file mode 100644 index 0000000..778c849 --- /dev/null +++ b/rules/platforms/BUILD @@ -0,0 +1,33 @@ +package(default_visibility = ["//visibility:public"]) + +platform( + name = "armeabi_v7a", + constraint_values = [ + "@platforms//cpu:armv7", + "@platforms//os:android", + ], +) + +platform( + name = "arm64-v8a", + constraint_values = [ + "@platforms//cpu:arm64", + "@platforms//os:android", + ], +) + +platform( + name = "x86", + constraint_values = [ + "@platforms//cpu:x86_32", + "@platforms//os:android", + ], +) + +platform( + name = "x86_64", + constraint_values = [ + "@platforms//cpu:x86_64", + "@platforms//os:android", + ], +) diff --git a/rules/processing_pipeline.bzl b/rules/processing_pipeline.bzl new file mode 100644 index 0000000..6ba2ae7 --- /dev/null +++ b/rules/processing_pipeline.bzl @@ -0,0 +1,161 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Common implementation for processing pipelines.""" + +PROVIDERS = "providers" +VALIDATION_OUTPUTS = "validation_outputs" + +# TODO(djwhang): When a provider type can be retrieved from a Starlark provider +# ProviderInfo is necessary. Once this is possible, processor methods can have a +# uniform method signature foo(ctx, target_ctx) where we can pull the provider +# off the target_ctx using the provider type. +# +# Yes, this effectively leads to producing a build rule like system within a +# build rule, rather than resorting to rule based composition. +ProviderInfo = provider( + "Stores metadata about the actual Starlark provider returned.", + fields = dict( + name = "The type of the provider", + value = "The actual provider", + runfiles = "Runfiles to pass to the DefaultInfo provider", + ), +) + +_ProcessingPipelineInfo = provider( + "Stores functions that forms a rule's implementation.", + fields = dict( + processors = "Ordered dictionary of processing functions.", + finalize = "Function to form the final providers to propagate.", + ), +) + +def _make_processing_pipeline(processors = dict(), finalize = None): + """Creates the combined processing pipeline. + + Args: + processors: Ordered dictionary of processing functions. + finalize: Function to form the final providers to propagate. + + Returns: + A _ProcessingPipelineInfo provider. + """ + return _ProcessingPipelineInfo( + processors = processors, + finalize = finalize, + ) + +def _run(ctx, java_package, processing_pipeline): + """Runs the processing pipeline and populates the target context. + + Args: + ctx: The context. + java_package: The java package resolved from the target's path + or the custom_package attr. + processing_pipeline: The _ProcessingPipelineInfo provider for this target. + + Returns: + The output of the _ProcessingPipelineInfo.finalize function. + """ + target_ctx = dict( + java_package = java_package, + providers = [], + validation_outputs = [], + runfiles = ctx.runfiles(), + ) + + for execute in processing_pipeline.processors.values(): + info = execute(ctx, **target_ctx) + if info: + if info.name in target_ctx: + fail("%s provider already registered in target context" % info.name) + target_ctx[info.name] = info.value + target_ctx[PROVIDERS].extend(getattr(info.value, PROVIDERS, [])) + target_ctx[VALIDATION_OUTPUTS].extend(getattr(info.value, VALIDATION_OUTPUTS, [])) + if hasattr(info, "runfiles") and info.runfiles: + target_ctx["runfiles"] = target_ctx["runfiles"].merge(info.runfiles) + + return processing_pipeline.finalize(ctx, **target_ctx) + +def _prepend(processors, **new_processors): + """Prepends processors in a given processing pipeline. + + Args: + processors: The dictionary representing the processing pipeline. + **new_processors: The processors to add where the key represents the + name of the processor and value is the function pointer to the new + processor. + + Returns: + A dictionary which represents the new processing pipeline. + """ + updated_processors = dict() + for name, processor in new_processors.items(): + updated_processors[name] = processor + + for key in processors.keys(): + updated_processors[key] = processors[key] + + return updated_processors + +def _append(processors, **new_processors): + """Appends processors in a given processing pipeline. + + Args: + processors: The dictionary representing the processing pipeline. + **new_processors: The processors to append where the key represents the + name of the processor and value is the function pointer to the new + processor. + + Returns: + A dictionary which represents the new processing pipeline. + """ + updated_processors = dict(processors) + for name, processor in new_processors.items(): + updated_processors[name] = processor + + return updated_processors + +def _replace(processors, **new_processors): + """Replace processors in a given processing pipeline. + + Args: + processors: The dictionary representing the processing pipeline. + **new_processors: The processors to override where the key represents the + name of the processor and value is the function pointer to the new + processor. + + Returns: + A dictionary which represents the new processing pipeline. + """ + updated_processors = dict(processors) + for name, processor in new_processors.items(): + if name not in processors: + fail("Error, %s not found, unable to override." % name) + + # NOTE: Overwriting an existing value does not break iteration order. + # However, if a new processor is being added that needs to be injected + # between other processors, the processing pipeline dictionary will need + # to be recreated. + updated_processors[name] = processor + + return updated_processors + +processing_pipeline = struct( + make_processing_pipeline = _make_processing_pipeline, + run = _run, + prepend = _prepend, + append = _append, + replace = _replace, +) diff --git a/rules/proguard.bzl b/rules/proguard.bzl new file mode 100644 index 0000000..837d622 --- /dev/null +++ b/rules/proguard.bzl @@ -0,0 +1,110 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel Android Proguard library for the Android rules.""" + +_ProguardContextInfo = provider( + doc = "Contains data from processing Proguard specs.", + fields = dict( + proguard_configs = "The direct proguard configs", + transitive_proguard_configs = + "The proguard configs within the transitive closure of the target", + providers = "The list of all providers to propagate.", + ), +) + +def _validate_proguard_spec( + ctx, + out_validated_proguard_spec, + proguard_spec, + proguard_allowlister): + args = ctx.actions.args() + args.add("--path", proguard_spec) + args.add("--output", out_validated_proguard_spec) + + ctx.actions.run( + executable = proguard_allowlister, + arguments = [args], + inputs = [proguard_spec], + outputs = [out_validated_proguard_spec], + mnemonic = "ValidateProguard", + progress_message = ( + "Validating proguard configuration %s" % proguard_spec.short_path + ), + ) + +def _process( + ctx, + proguard_configs = [], + proguard_spec_providers = [], + proguard_allowlister = None): + """Processes Proguard Specs + + Args: + ctx: The context. + proguard_configs: sequence of Files. A list of proguard config files to be + processed. Optional. + proguard_spec_providers: sequence of ProguardSpecProvider providers. A + list of providers from the dependencies, exports, plugins, + exported_plugins, etc. Optional. + proguard_allowlister: The proguard_allowlister exeutable provider. + + Returns: + A _ProguardContextInfo provider. + """ + + # TODO(djwhang): Look to see if this can be just a validation action and the + # proguard_spec provided by the rule can be propagated. + validated_proguard_configs = [] + for proguard_spec in proguard_configs: + validated_proguard_spec = ctx.actions.declare_file( + "validated_proguard/%s/%s_valid" % + (ctx.label.name, proguard_spec.path), + ) + _validate_proguard_spec( + ctx, + validated_proguard_spec, + proguard_spec, + proguard_allowlister, + ) + validated_proguard_configs.append(validated_proguard_spec) + + transitive_validated_proguard_configs = [] + for info in proguard_spec_providers: + transitive_validated_proguard_configs.append(info.specs) + + transitive_proguard_configs = depset( + validated_proguard_configs, + transitive = transitive_validated_proguard_configs, + order = "preorder", + ) + return _ProguardContextInfo( + proguard_configs = proguard_configs, + transitive_proguard_configs = transitive_proguard_configs, + providers = [ + ProguardSpecProvider(transitive_proguard_configs), + # TODO(b/152659272): Remove this once the android_archive rule is + # able to process a transitive closure of deps to produce an aar. + AndroidProguardInfo(proguard_configs), + ], + ) + +proguard = struct( + process = _process, +) + +testing = struct( + validate_proguard_spec = _validate_proguard_spec, + ProguardContextInfo = _ProguardContextInfo, +) diff --git a/rules/providers.bzl b/rules/providers.bzl new file mode 100644 index 0000000..fd92708 --- /dev/null +++ b/rules/providers.bzl @@ -0,0 +1,118 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel providers for Android rules.""" + + + +AndroidAppsInfo = provider( + doc = "Provides information about app to install.", + fields = dict( + apps = "List of app provider artifacts.", + ), +) + + + + + + + + +AndroidJavaInfo = provider( + doc = "Provides outputs for the Android Java Compilation", + fields = dict( + aidl = "AndroidIdlInfo", + aide = "AndroidIdeInfo", + java = "JavaInfo", + ), +) + +AndroidFilteredJdepsInfo = provider( + doc = "Provides a filtered jdeps proto.", + fields = dict( + jdeps = "Filtered jdeps", + ), +) + + +StarlarkApkInfo = provider( + doc = "Provides APK outputs of a rule.", + fields = dict( + keystore = "Keystore used to sign the APK. Deprecated, prefer signing_keys.", + signing_keys = "List of keys used to sign the APK", + signing_lineage = "Optional sigining lineage file", + signed_apk = "Signed APK", + unsigned_apk = "Unsigned APK", + ), +) + +ResourcesNodeInfo = provider( + doc = "Provides information for building ResourceProcessorBusyBox flags", + fields = dict( + label = "A label, the target's label", + + # Assets related fields + assets = "A depset of files, assets files of the target", + assets_dir = "A string, the name of the assets directory", + assets_symbols = "A file, the merged assets", + compiled_assets = "A file, the compiled assets", + + # Resource related fields + resource_files = "A depset of files, resource files of the target", + compiled_resources = "A file, the compiled resources", + r_txt = "A file, the R.txt file", + manifest = "A file, the AndroidManifest.xml", + # TODO(ostonge): Add the manifest if it's exported, otherwise leave empty + exports_manifest = "Boolean, whether the manifest is exported", + ), +) + +StarlarkAndroidResourcesInfo = provider( + doc = "Provides information about direct and transitive resources", + fields = dict( + direct_resources_nodes = "Depset of ResourcesNodeInfo providers, can contain multiple providers due to exports", + transitive_resources_nodes = "Depset of transitive ResourcesNodeInfo providers, not including directs", + transitive_assets = "Depset of transitive assets files", + transitive_assets_symbols = "Depset of transitive merged assets", + transitive_compiled_assets = "Depset of transitive compiled assets", + direct_compiled_resources = "Depset of direct compiled_resources, can contain multiple files due to exports", + transitive_compiled_resources = "Depset of transitive compiled resources", + transitive_manifests = "Depset of transitive manifests", + transitive_r_txts = "Depset of transitive R.txt files", + transitive_resource_files = "Depset of transitive resource files", + ), +) + +AndroidLintRulesInfo = provider( + doc = "Provides extra lint rules to use with AndroidLint.", + fields = dict( + lint_jar = "A file, a lint jar found in an aar.", + ), +) + + + +FailureInfo = provider( + fields = dict( + error = "Error message", + ), +) + +AndroidBundleInfo = provider( + doc = "Provides .aab outputs from a rule.", + fields = dict( + unsigned_aab = "File, the unsigned .aab", + ), +) diff --git a/rules/res_v3_dummy_AndroidManifest.xml b/rules/res_v3_dummy_AndroidManifest.xml new file mode 100644 index 0000000..8072ee0 --- /dev/null +++ b/rules/res_v3_dummy_AndroidManifest.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest /> diff --git a/rules/res_v3_dummy_R.txt b/rules/res_v3_dummy_R.txt new file mode 100644 index 0000000..2b3d8b7 --- /dev/null +++ b/rules/res_v3_dummy_R.txt @@ -0,0 +1 @@ +int string fake 0x00000000 diff --git a/rules/resources.bzl b/rules/resources.bzl new file mode 100644 index 0000000..386196d --- /dev/null +++ b/rules/resources.bzl @@ -0,0 +1,1638 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Bazel Android Resources.""" + +load(":attrs.bzl", _attrs = "attrs") +load(":busybox.bzl", _busybox = "busybox") +load(":common.bzl", _common = "common") +load(":java.bzl", _java = "java") +load(":path.bzl", _path = "path") +load( + ":providers.bzl", + "ResourcesNodeInfo", + "StarlarkAndroidResourcesInfo", +) +load( + ":utils.bzl", + "utils", + _compilation_mode = "compilation_mode", + _log = "log", +) + +_RESOURCE_FOLDER_TYPES = [ + "anim", + "animator", + "color", + "drawable", + "font", + "interpolator", + "layout", + "menu", + "mipmap", + "navigation", + "values", + "xml", + "raw", + "transition", +] + +_RESOURCE_QUALIFIER_SEP = "-" + +_MANIFEST_MISSING_ERROR = ( + "In target %s, manifest attribute is required when resource_files or " + + "assets are defined." +) + +_ASSET_DEFINITION_ERROR = ( + "In target %s, the assets and assets_dir attributes should be either " + + "both empty or non-empty." +) + +_JAVA_PACKAGE_MISSING_ERROR = ( + "In target %s, a java package is required when stamping " + + "the manifest." +) + +_INCORRECT_RESOURCE_LAYOUT_ERROR = ( + "'%s' is not in the expected resource directory structure of " + + "<resource directory>/{%s}/<file>" % (",").join(_RESOURCE_FOLDER_TYPES) +) + +# Keys for manifest_values +_VERSION_NAME = "versionName" +_VERSION_CODE = "versionCode" + +# Resources context attributes. +_ASSETS_PROVIDER = "assets_provider" +_DEFINES_RESOURCES = "defines_resources" +_DIRECT_ANDROID_RESOURCES = "direct_android_resources" +_MERGED_MANIFEST = "merged_manifest" +_PROVIDERS = "providers" +_R_JAVA = "r_java" +_RESOURCES_APK = "resources_apk" +_VALIDATION_RESULTS = "validation_results" +_VALIDATION_OUTPUTS = "validation_outputs" +_RESOURCES_PROVIDER = "resources_provider" +_STARLARK_PROCESSED_MANIFEST = "starlark_processed_manifest" +_STARLARK_R_TXT = "starlark_r_txt" +_STARLARK_PROCESSED_RESOURCES = "starlark_processed_resources" + +_ResourcesProcessContextInfo = provider( + "Resources context object", + fields = { + _DEFINES_RESOURCES: "If local resources were defined.", + _DIRECT_ANDROID_RESOURCES: "Direct android resources.", + _MERGED_MANIFEST: "Merged manifest.", + _PROVIDERS: "The list of all providers to propagate.", + _R_JAVA: "JavaInfo for R.jar.", + _RESOURCES_APK: "ResourcesApk.", + _VALIDATION_RESULTS: "List of validation results.", + _VALIDATION_OUTPUTS: "List of outputs given to OutputGroupInfo _validation group", + + # TODO(djwhang): The android_library aar generation requires direct + # access to providers. Remove once aar is its own rule. + _ASSETS_PROVIDER: "AndroidAssetsInfo provider.", + _RESOURCES_PROVIDER: "AndroidResourcesInfo provider.", + _STARLARK_PROCESSED_MANIFEST: "The processed manifest from the starlark resource processing pipeline.", + _STARLARK_R_TXT: "The R.txt from the starlark resource processing pipeline.", + _STARLARK_PROCESSED_RESOURCES: "The processed resources from the starlark processing pipeline.", + }, +) + +# Packaged resources context attributes. +_PACKAGED_FINAL_MANIFEST = "processed_manifest" +_PACKAGED_RESOURCE_APK = "resources_apk" +_PACKAGED_CLASS_JAR = "class_jar" +_PACKAGED_VALIDATION_RESULT = "validation_result" + +_ResourcesPackageContextInfo = provider( + "Packaged resources context object", + fields = { + _PACKAGED_FINAL_MANIFEST: "Final processed manifest.", + _PACKAGED_RESOURCE_APK: "ResourceApk.", + _PACKAGED_CLASS_JAR: "R class jar.", + _PACKAGED_VALIDATION_RESULT: "Validation result.", + _R_JAVA: "JavaInfo for R.jar", + _PROVIDERS: "The list of all providers to propagate.", + }, +) + +def _generate_dummy_manifest( + ctx, + out_manifest = None, + java_package = None, + min_sdk_version = None): + content = """<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="%s">""" % java_package + + if min_sdk_version: + content = content + """ + <uses-sdk android:minSdkVersion="%s" />""" % min_sdk_version + + content = content + """ + <application> + </application> +</manifest>""" + + ctx.actions.write( + output = out_manifest, + content = content, + ) + +def _add_g3itr( + ctx, + manifest = None, + out_manifest = None, + xsltproc = None, + instrument_xslt = None): + """Adds Google3InstrumentationTestRunner instrumentation element to the manifest. + + Element is only added if the manifest contains an instrumentation element with + name "android.test.InstrumentationTestRunner". The added element's name attr is + "com.google.android.apps.common.testing.testrunner.Google3InstrumentationTestRunner". + + Args: + ctx: The context. + manifest: File. The AndroidManifest.xml file. + out_manifest: File. The transformed AndroidManifest.xml. + xsltproc: FilesToRunProvider. The xsltproc executable or + FilesToRunProvider. + instrument_xslt: File. The add_g3itr.xslt file describing the xslt + transformation to apply. + """ + args = ctx.actions.args() + args.add("--nonet") + args.add("--novalid") + args.add("-o", out_manifest) + args.add(instrument_xslt) + args.add(manifest) + + ctx.actions.run( + executable = xsltproc, + arguments = [args], + inputs = [manifest, instrument_xslt], + outputs = [out_manifest], + mnemonic = "AddG3ITRStarlark", + progress_message = "Adding G3ITR to test manifest for %s" % ctx.label, + ) + +def _get_legacy_mergee_manifests(resources_infos): + all_dependencies = depset( + transitive = [ + ri.direct_android_resources + for ri in resources_infos + ] + [ + ri.transitive_android_resources + for ri in resources_infos + ], + ) + + mergee_manifests = [] + for dep in all_dependencies.to_list(): + if dep.to_provider.manifest.exports_manifest: + mergee_manifests.append(dep.to_provider.manifest.manifest) + + return depset(mergee_manifests) + +def _legacy_mergee_manifest(manifest): + sort_key = manifest.short_path + "#" + return sort_key + "--mergee=" + manifest.path + +def _legacy_merge_manifests( + ctx, + out_merged_manifest = None, + manifest = None, + mergee_manifests = None, + legacy_merger = None): + """Merges manifests with the legacy manifest merger." + + This should not be called with empty mergee_manifests. + + Args: + ctx: The context. + out_merged_manifest: File. The merged AndroidManifest.xml. + manifest: File. The AndroidManifest.xml. + mergee_manifests: A sequence of Files. All transitive manifests to be merged. + legacy_merger: A FilesToRunProvider. The legacy manifest merger executable. + """ + args = ctx.actions.args() + args.use_param_file("%s", use_always = True) + args.set_param_file_format("multiline") + args.add("--merger=%s" % manifest.path) + args.add("--exclude_permission=all") + args.add("--output=%s" % out_merged_manifest.path) + + manifest_params = ctx.actions.declare_file(ctx.label.name + "/legacy_merger.params") + manifest_args = ctx.actions.args() + manifest_args.use_param_file("%s", use_always = True) + manifest_args.set_param_file_format("multiline") + manifest_args.add_joined(mergee_manifests, map_each = _legacy_mergee_manifest, join_with = "\n") + ctx.actions.run_shell( + command = """ +# Sorts the mergee manifests by path and combines with other busybox args. +set -e +SORTED=`sort $1 | sed 's/^.*#//'` +cat $2 > $3 +echo "$SORTED" >> $3 +""", + arguments = [manifest_args, args, manifest_params.path], + outputs = [manifest_params], + ) + args = ctx.actions.args() + args.add(manifest_params, format = "--flagfile=%s") + + ctx.actions.run( + executable = legacy_merger, + arguments = [args], + inputs = depset([manifest, manifest_params], transitive = [mergee_manifests]), + outputs = [out_merged_manifest], + mnemonic = "StarlarkLegacyAndroidManifestMerger", + progress_message = "Merging Android Manifests", + ) + +def _make_databinding_outputs( + ctx, + resource_files): + """Helper method to create arguments for the process_databinding busybox tool. + + Declares databinding-processed resource files that are generated by the + PROCESS_DATABINDING busybox tool, which must be declared underneath an output + resources directory and namespaced by their paths. The busybox takes the + output directory exec path and generates the underlying resource files. + + Args: + ctx: The context. + resource_files: List of Files. The android resource files to be processed by + _process_databinding. + + Returns: + A tuple containing the list of declared databinding processed resource files and the + output resource directory path expected by the busybox. The path is a full path. + """ + + # TODO(b/160907203): Clean up databinding_rel_path. We capitalize "Databinding" here to avoid + # conflicting with native artifact file names. This is changed back to "databinding" during + # process_starlark so that compiled resources exactly match those of the native resource + # processing pipeline. Even a single character mismatch in the file names causes selected + # resources to differ in the final APK. + databinding_rel_path = _path.join(["Databinding-processed-resources", ctx.label.name]) + databinding_processed_resources = [ + ctx.actions.declare_file(_path.join([databinding_rel_path, f.path])) + for f in resource_files + ] + databinding_resources_dirname = _path.join([ + ctx.bin_dir.path, + ctx.label.package, + databinding_rel_path, + ]) + return databinding_processed_resources, databinding_resources_dirname + +def _fix_databinding_compiled_resources( + ctx, + out_compiled_resources = None, + compiled_resources = None, + zip_tool = None): + """Fix compiled resources to match those produced by the native pipeline. + + Changes "Databinding" to "databinding" in each compiled resource .flat file name and header. + + Args: + ctx: The context. + out_compiled_resources: File. The modified compiled_resources output. + compiled_resources: File. The compiled_resources zip. + """ + ctx.actions.run_shell( + outputs = [out_compiled_resources], + inputs = [compiled_resources], + tools = [zip_tool], + arguments = [compiled_resources.path, out_compiled_resources.path, zip_tool.executable.path], + command = """#!/bin/bash +set -e + +IN_DIR=$(mktemp -d) +OUT_DIR=$(mktemp -d) +CUR_PWD=$(pwd) + +if zipinfo -t "$1"; then + ORDERED_LIST=`(unzip -l "$1" | sed -e '1,3d' | head -n -2 | tr -s " " | cut -d " " -f5)` + + unzip -q "$1" -d "$IN_DIR" + + # Iterate through the ordered list, change "Databinding" to "databinding" in the file header + # and file name and zip the files with the right comment + for FILE in $ORDERED_LIST; do + cd "$IN_DIR" + if [ -f "$FILE" ]; then + sed -i 's/Databinding\\-processed\\-resources/databinding\\-processed\\-resources/g' "$FILE" + NEW_NAME=`echo "$FILE" | sed 's/Databinding\\-processed\\-resources/databinding\\-processed\\-resources/g' | sed 's#'"$IN_DIR"'/##g'` + mkdir -p `dirname "$OUT_DIR/$NEW_NAME"` && touch "$OUT_DIR/$NEW_NAME" + cp -p "$FILE" "$OUT_DIR/$NEW_NAME" + + PATH_SEGMENTS=(`echo ${FILE} | tr '/' ' '`) + BASE_PATH_SEGMENT="${PATH_SEGMENTS[0]}" + COMMENT= + if [ "${BASE_PATH_SEGMENT}" == "generated" ]; then + COMMENT="generated" + elif [ "${BASE_PATH_SEGMENT}" == "default" ]; then + COMMENT="default" + fi + + cd "$OUT_DIR" + "$CUR_PWD/$3" -jt -X -0 -q -r -c "$CUR_PWD/$2" $NEW_NAME <<EOM +${COMMENT} +EOM + fi + done + + cd "$CUR_PWD" + touch -r "$1" "$2" +else + cp -p "$1" "$2" +fi + """, + ) + +def _is_resource_shrinking_enabled( + shrink_resources, + use_android_resource_shrinking): + if shrink_resources == _attrs.tristate.auto: + return use_android_resource_shrinking + return shrink_resources == _attrs.tristate.yes + +def _should_shrink_resource_cycles( + use_android_resource_cycle_shrinking, + resource_shrinking_enabled): + if use_android_resource_cycle_shrinking and not resource_shrinking_enabled: + fail("resource cycle shrinking can only be enabled when resource shrinking is enabled") + return use_android_resource_cycle_shrinking + +def _filter_multi_cpu_configuration_targets( + targets): + """Filter out duplicate split-configured targets. + + This method simulates logic in the native rule where if a label_list attribute has + split-configuration but is requested in target mode, only targets from the first architecture + are returned. Without this filtering there are duplicate targets if multiple CPU configurations + are specified on the command line. This is the case with deps in the packaging step of + android_binary. + + Args: + targets: A list of Target objects. + + Returns: + A list of Target objects with duplicates removed. + """ + seen_labels = {} + filtered_targets = [] + for t in targets: + if t.label in seen_labels: + continue + seen_labels[t.label] = True + filtered_targets.append(t) + return filtered_targets + +def _package( + ctx, + assets = [], + assets_dir = None, + deps = [], + manifest = None, + manifest_values = None, + instruments = None, + resource_configs = None, + densities = [], + resource_files = [], + nocompress_extensions = [], + java_package = None, + compilation_mode = _compilation_mode.FASTBUILD, + shrink_resources = None, + use_android_resource_shrinking = None, + use_android_resource_cycle_shrinking = None, + use_legacy_manifest_merger = False, + should_throw_on_conflict = True, + enable_data_binding = False, + enable_manifest_merging = True, + aapt = None, + android_jar = None, + legacy_merger = None, + xsltproc = None, + instrument_xslt = None, + busybox = None, + host_javabase = None): + """Package resources for top-level rules. + + Args: + ctx: The context. + assets: sequence of Files. A list of assets to be packaged. All files be + under the assets_dir directory in the corresponding package. + assets_dir: String. A string giving the path to the files in assets. The + pair assets and assets_dir describe packaged assets and either both + parameters should be provided or none of them. + deps: sequence of Targets. The list of other libraries targets to link + against. + manifest: File. The input top-level AndroidManifest.xml. + manifest_values: String dictionary. Manifest values to substitute. + instruments: Optional target. The value of the "instruments" attr if set. + resource_configs: sequence of Strings. A list of resource_configuration_filters + to apply. + densities: sequence of Strings. A list of densities to filter for when building + the apk. + resource_files: sequence of Files. A list of Android resource files + to be processed. + nocompress_extensions: sequence of Strings. File extension to leave uncompressed + in the apk. + java_package: String. Java package for which java sources will be + generated. By default the package is inferred from the directory where + the BUILD file containing the rule is. + compilation_mode: String. A string that represents compilation mode. The + list of expected values are as follows: dbg, fastbuild, opt. + shrink_resources: Tristate. Whether resource shrinking is enabled by the rule. + use_android_resource_shrinking: Bool. Flag that controls the default value for + shrink_resources if the tristate value is auto (-1). + use_android_resource_cycle_shrinking: Bool. Flag that enables more shrinking of + code and resources by instructing AAPT2 to emit conditional Proguard keep rules. + use_legacy_manifest_merger: A boolean. Whether to use the legacy manifest merger + instead of the android manifest merger. + should_throw_on_conflict: A boolean. Determines whether an error should be thrown + when a resource conflict occurs. + enable_data_binding: boolean. If true, processesing the data binding + expressions in layout resources included through the resource_files + parameter is enabled. Without this setting, data binding expressions + produce build failures. + enable_manifest_merging: boolean. If true, manifest merging will be performed. + aapt: FilesToRunProvider. The aapt executable or FilesToRunProvider. + android_jar: File. The Android jar. + legacy_merger: FilesToRunProvider. The legacy manifest merger executable. + xsltproc: FilesToRunProvider. The xsltproc executable or + FilesToRunProvider. + instrument_xslt: File. The add_g3itr.xslt file describing the xslt + transformation to apply. + busybox: FilesToRunProvider. The ResourceBusyBox executable or + FilesToRunprovider + host_javabase: A Target. The host javabase. + + Returns: + A ResourcesPackageContextInfo containing packaged resource artifacts and + providers. + """ + _validate_resources(resource_files) + + # Filtering is necessary if a build is requested with multiple CPU configurations. + deps = _filter_multi_cpu_configuration_targets(deps) + + packaged_resources_ctx = { + _PROVIDERS: [], + } + + g3itr_manifest = manifest + + if xsltproc or instrument_xslt: + g3itr_manifest = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "add_g3itr/AndroidManifest.xml", + ) + _add_g3itr( + ctx, + out_manifest = g3itr_manifest, + manifest = manifest, + xsltproc = xsltproc, + instrument_xslt = instrument_xslt, + ) + + direct_resources_nodes = [] + transitive_resources_nodes = [] + transitive_assets = [] + transitive_assets_symbols = [] + transitive_compiled_assets = [] + transitive_resource_files = [] + transitive_compiled_resources = [] + transitive_manifests = [] + transitive_r_txts = [] + for dep in utils.collect_providers(StarlarkAndroidResourcesInfo, deps): + direct_resources_nodes.append(dep.direct_resources_nodes) + transitive_resources_nodes.append(dep.transitive_resources_nodes) + transitive_assets.append(dep.transitive_assets) + transitive_assets_symbols.append(dep.transitive_assets_symbols) + transitive_compiled_assets.append(dep.transitive_compiled_assets) + transitive_resource_files.append(dep.transitive_resource_files) + transitive_compiled_resources.append(dep.transitive_compiled_resources) + transitive_manifests.append(dep.transitive_manifests) + transitive_r_txts.append(dep.transitive_r_txts) + + mergee_manifests = depset([ + node_info.manifest + for node_info in depset(transitive = transitive_resources_nodes + direct_resources_nodes).to_list() + if node_info.exports_manifest + ]) + + # TODO(b/156763506): Add analysis tests to verify logic around when manifest merging is configured. + # TODO(b/154153771): Run the android merger if mergee_manifests or manifest values are present. + merged_manifest = g3itr_manifest + if enable_manifest_merging and (manifest_values or mergee_manifests): + if use_legacy_manifest_merger: + # Legacy manifest merger only runs if mergee manifests are present + if mergee_manifests: + merged_manifest = ctx.actions.declare_file( + "_migrated/_merged/" + ctx.label.name + "/AndroidManifest.xml", + ) + _legacy_merge_manifests( + ctx, + out_merged_manifest = merged_manifest, + manifest = g3itr_manifest, + mergee_manifests = mergee_manifests, + legacy_merger = legacy_merger, + ) + else: + merged_manifest = ctx.actions.declare_file( + "_migrated/_merged/" + ctx.label.name + "/AndroidManifest.xml", + ) + _busybox.merge_manifests( + ctx, + out_file = merged_manifest, + out_log_file = ctx.actions.declare_file( + "_migrated/_merged/" + ctx.label.name + "/manifest_merger_log.txt", + ), + manifest = g3itr_manifest, + mergee_manifests = mergee_manifests, + manifest_values = manifest_values, + merge_type = "APPLICATION", + java_package = java_package, + busybox = busybox, + host_javabase = host_javabase, + ) + + processed_resources = resource_files + databinding_info = None + if enable_data_binding: + databinding_info = ctx.actions.declare_file("_migrated/databinding/" + ctx.label.name + "/layout-info.zip") + processed_resources, resources_dirname = _make_databinding_outputs( + ctx, + resource_files, + ) + _busybox.process_databinding( + ctx, + out_databinding_info = databinding_info, + out_databinding_processed_resources = processed_resources, + databinding_resources_dirname = resources_dirname, + resource_files = resource_files, + java_package = java_package, + busybox = busybox, + host_javabase = host_javabase, + ) + + resource_apk = ctx.actions.declare_file(ctx.label.name + "_migrated/.ap_") + r_java = ctx.actions.declare_file("_migrated/" + ctx.label.name + ".srcjar") + r_txt = ctx.actions.declare_file(ctx.label.name + "_migrated/_symbols/R.txt") + processed_manifest = ctx.actions.declare_file(ctx.label.name + "_migrated/_processed_manifest/AndroidManifest.xml") + proguard_cfg = ctx.actions.declare_file( + "_migrated/proguard/%s/_%s_proguard.cfg" % (ctx.label.name, ctx.label.name), + ) + main_dex_proguard_cfg = ctx.actions.declare_file( + "_migrated/proguard/%s/main_dex_%s_proguard.cfg" % + (ctx.label.name, ctx.label.name), + ) + resource_files_zip = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_files/resource_files.zip", + ) + _busybox.package( + ctx, + out_file = resource_apk, + out_r_src_jar = r_java, + out_r_txt = r_txt, + out_symbols = ctx.actions.declare_file("_migrated/" + ctx.label.name + "_symbols/merged.bin"), + out_manifest = processed_manifest, + out_proguard_cfg = proguard_cfg, + out_main_dex_proguard_cfg = main_dex_proguard_cfg, + out_resource_files_zip = resource_files_zip, + application_id = manifest_values.get("applicationId", None), + manifest = merged_manifest, + assets = assets, + assets_dir = assets_dir, + resource_files = processed_resources, + direct_resources_nodes = + depset(transitive = direct_resources_nodes, order = "preorder"), + transitive_resources_nodes = + depset(transitive = transitive_resources_nodes, order = "preorder"), + transitive_assets = transitive_assets, + transitive_compiled_assets = transitive_compiled_assets, + transitive_resource_files = transitive_resource_files, + transitive_compiled_resources = transitive_compiled_resources, + transitive_manifests = transitive_manifests, + transitive_r_txts = transitive_r_txts, + resource_configs = resource_configs, + densities = densities, + nocompress_extensions = nocompress_extensions, + java_package = java_package, + version_name = manifest_values[_VERSION_NAME] if _VERSION_NAME in manifest_values else None, + version_code = manifest_values[_VERSION_CODE] if _VERSION_CODE in manifest_values else None, + android_jar = android_jar, + aapt = aapt, + busybox = busybox, + host_javabase = host_javabase, + debug = compilation_mode != _compilation_mode.OPT, + should_throw_on_conflict = should_throw_on_conflict, + ) + packaged_resources_ctx[_PACKAGED_FINAL_MANIFEST] = processed_manifest + packaged_resources_ctx[_PACKAGED_RESOURCE_APK] = resource_apk + packaged_resources_ctx[_PACKAGED_VALIDATION_RESULT] = resource_files_zip + + resource_shrinking_enabled = _is_resource_shrinking_enabled( + shrink_resources, + use_android_resource_shrinking, + ) + shrink_resource_cycles = _should_shrink_resource_cycles( + use_android_resource_cycle_shrinking, + resource_shrinking_enabled, + ) + + # Fix class jar name because some tests depend on {label_name}_resources.jar being the suffix of + # the path, with _RESOURCES_DO_NOT_USE removed from the label name. + _RESOURCES_SUFFIX = "_RESOURCES_DO_NOT_USE" + class_jar_name = ctx.label.name + "_migrated/_resources.jar" + if ctx.label.name.endswith(_RESOURCES_SUFFIX): + label_name = ctx.label.name[:-len(_RESOURCES_SUFFIX)] + class_jar_name = ctx.label.name + "_migrated/" + label_name + "_resources.jar" + + class_jar = ctx.actions.declare_file(class_jar_name) + _busybox.generate_binary_r( + ctx, + out_class_jar = class_jar, + r_txt = r_txt, + manifest = processed_manifest, + package_for_r = java_package, + final_fields = not shrink_resource_cycles and not instruments, + resources_nodes = depset(transitive = direct_resources_nodes + transitive_resources_nodes), + transitive_r_txts = transitive_r_txts, + transitive_manifests = transitive_manifests, + busybox = busybox, + host_javabase = host_javabase, + ) + packaged_resources_ctx[_PACKAGED_CLASS_JAR] = class_jar + + java_info = JavaInfo( + output_jar = class_jar, + compile_jar = class_jar, + source_jar = r_java, + ) + + packaged_resources_ctx[_R_JAVA] = java_info + + packaged_resources_ctx[_PROVIDERS].append(AndroidApplicationResourceInfo( + resource_apk = resource_apk, + resource_java_src_jar = r_java, + resource_java_class_jar = class_jar, + manifest = processed_manifest, + resource_proguard_config = proguard_cfg, + main_dex_proguard_config = main_dex_proguard_cfg, + r_txt = r_txt, + resources_zip = resource_files_zip, + databinding_info = databinding_info, + )) + return _ResourcesPackageContextInfo(**packaged_resources_ctx) + +def _liteparse(ctx, out_r_pb, resource_files, android_kit): + """Creates an R.pb which contains the resource ids gotten from a light parse. + + Args: + ctx: The context. + out_r_pb: File. The R.pb output file. + resource_files: List of Files. The list of resource files. + android_kit: FilesToRunProvider. The Android Kit executable or + FilesToRunProvider. + """ + args = ctx.actions.args() + args.use_param_file(param_file_arg = "--flagfile=%s", use_always = True) + args.set_param_file_format("multiline") + args.add_joined("--res_files", resource_files, join_with = ",") + args.add("--out", out_r_pb) + + ctx.actions.run( + executable = android_kit, + arguments = ["liteparse", args], + inputs = resource_files, + outputs = [out_r_pb], + mnemonic = "ResLiteParse", + progress_message = "Lite parse Android Resources %s" % ctx.label, + ) + +def _fastr(ctx, r_pbs, package, manifest, android_kit): + """Create R.srcjar from the given R.pb files in the transitive closure. + + Args: + ctx: The context. + r_pbs: Transitive set of resource pbs. + package: The package name of the compile-time R.java. + manifest: File. The AndroidManifest.xml file. + android_kit: FilesToRunProvider. The Android Kit executable or + FilesToRunProvider. + + Returns: + The output R source jar artifact. + """ + inputs = r_pbs + r_srcjar = ctx.actions.declare_file(ctx.label.name + "/resources/R-fastr.srcjar") + args = ctx.actions.args() + args.use_param_file(param_file_arg = "--flagfile=%s", use_always = True) + args.set_param_file_format("multiline") + args.add("-rJavaOutput", r_srcjar) + if package: + args.add("-packageForR", package) + else: + args.add("-manifest", manifest) + inputs = depset([manifest], transitive = [inputs]) + args.add_joined("-resourcePbs", r_pbs, join_with = ",") + + ctx.actions.run( + executable = android_kit, + arguments = ["rstub", args], + inputs = inputs, + outputs = [r_srcjar], + mnemonic = "CompileTimeR", + progress_message = "Generating compile-time R %s" % r_srcjar.short_path, + ) + return r_srcjar + +def _compile( + ctx, + out_compiled_resources = None, + out_r_pb = None, + resource_files = [], + aapt = None, + android_kit = None, + busybox = None, + host_javabase = None): + """Compile Android Resources processing pipeline. + + Args: + ctx: The context. + out_compiled_resources: File. The compiled resources output file. + out_r_pb: File. The R.pb output file. + resource_files: A list of Files. The resource files can be directories. + aapt: FilesToRunProvider. The aapt executable or FilesToRunProvider. + android_kit: FilesToRunProvider. The android_kit executable or + FilesToRunProvider. + busybox: FilesToRunProvider. The ResourceBusyBox executable or + FilesToRunprovider + host_javabase: A Target. The host javabase. + """ + _liteparse(ctx, out_r_pb, resource_files, android_kit) + _busybox.compile( + ctx, + out_file = out_compiled_resources, + resource_files = resource_files, + aapt = aapt, + busybox = busybox, + host_javabase = host_javabase, + ) + +def _make_aar( + ctx, + assets = [], + assets_dir = None, + resource_files = [], + class_jar = None, + r_txt = None, + manifest = None, + proguard_specs = [], + busybox = None, + host_javabase = None): + """Generate an android archive file. + + Args: + ctx: The context. + assets: sequence of Files. A list of Android assets files to be processed. + assets_dir: String. The name of the assets directory. + resource_files: A list of Files. The resource files. + class_jar: File. The class jar file. + r_txt: File. The resource IDs outputted by linking resources in text. + manifest: File. The primary AndroidManifest.xml. + proguard_specs: List of File. The proguard spec files. + busybox: FilesToRunProvider. The ResourceBusyBox executable or + FilesToRunprovider + host_javabase: A Target. The host javabase. + + Returns: + The output aar artifact. + """ + aar = ctx.actions.declare_file(ctx.label.name + ".aar") + _busybox.make_aar( + ctx, + out_aar = aar, + assets = assets, + assets_dir = assets_dir, + resource_files = resource_files, + class_jar = class_jar, + r_txt = r_txt, + manifest = manifest, + proguard_specs = proguard_specs, + busybox = busybox, + host_javabase = host_javabase, + ) + return aar + +def _validate(ctx, manifest, defined_assets, defined_assets_dir): + if ((defined_assets and not defined_assets_dir) or + (not defined_assets and defined_assets_dir)): + _log.error(_ASSET_DEFINITION_ERROR % ctx.label) + + if not manifest: + _log.error(_MANIFEST_MISSING_ERROR % ctx.label) + +def _make_direct_assets_transitive(assets_info): + return AndroidAssetsInfo( + assets_info.label, + assets_info.validation_result, + depset([]), # direct_parsed_assets + depset( + transitive = [ + assets_info.direct_parsed_assets, + assets_info.transitive_parsed_assets, + ], + order = "preorder", + ), + assets_info.assets, + assets_info.symbols, + assets_info.compiled_symbols, + ) + +def _make_direct_resources_transitive(resources_info): + return AndroidResourcesInfo( + resources_info.label, + resources_info.manifest, + resources_info.compiletime_r_txt, + # NB: the ordering of "direct" and "transitive" is inconsistent with that used for + # AndroidAssetsInfo. + depset( + transitive = [ + # Ordering is inconsistent here too: + # https://github.com/bazelbuild/bazel/blob/82c7f48b4628ebbec18123afdbed701bbaa605e2/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java#L158 + resources_info.transitive_android_resources, + resources_info.direct_android_resources, + ], + order = "preorder", + ), + depset([]), # direct_android_resources + resources_info.transitive_resources, + resources_info.transitive_manifests, + resources_info.transitive_aapt2_r_txt, + resources_info.transitive_symbols_bin, + resources_info.transitive_compiled_symbols, + resources_info.transitive_static_lib, + resources_info.transitive_r_txt, + validation_artifacts = resources_info.validation_artifacts, + ) + +def _export_assets(assets_info, exports): + all_providers = [assets_info] + utils.collect_providers(AndroidAssetsInfo, exports) + return AndroidAssetsInfo( + assets_info.label, + assets_info.validation_result, + direct_parsed_assets = utils.join_depsets(all_providers, "direct_parsed_assets", order = "preorder"), + transitive_parsed_assets = utils.join_depsets(all_providers, "transitive_parsed_assets", order = "preorder"), + transitive_assets = utils.join_depsets(all_providers, "assets", order = "preorder"), + transitive_symbols = utils.join_depsets(all_providers, "symbols", order = "preorder"), + transitive_compiled_symbols = utils.join_depsets(all_providers, "compiled_symbols", order = "preorder"), + ) + +def _export_resources(resources_info, exports): + all_providers = [resources_info] + utils.collect_providers(AndroidResourcesInfo, exports) + return AndroidResourcesInfo( + resources_info.label, + resources_info.manifest, + resources_info.compiletime_r_txt, + **{attr: utils.join_depsets(all_providers, attr, order = "preorder") for attr in [ + "transitive_android_resources", + "direct_android_resources", + "transitive_resources", + "transitive_manifests", + "transitive_aapt2_r_txt", + "transitive_symbols_bin", + "transitive_compiled_symbols", + "transitive_static_lib", + "transitive_r_txt", + "validation_artifacts", + ]} + ) + +def _validate_resources(resource_files = None): + for resource_file in resource_files: + path_segments = resource_file.path.split("/") + if len(path_segments) < 3: + fail(_INCORRECT_RESOURCE_LAYOUT_ERROR % resource_file) + + # Check the resource directory type if the resource file is not a Fileset. + if not resource_file.is_directory: + # The resource directory is presumed to be the second directory from the end. + # Resource directories can have multiple qualifiers, each one separated with a dash. + res_type = path_segments[-2].partition(_RESOURCE_QUALIFIER_SEP)[0] + if res_type not in _RESOURCE_FOLDER_TYPES: + fail(_INCORRECT_RESOURCE_LAYOUT_ERROR % resource_file) + +def _process_starlark( + ctx, + java_package = None, + manifest = None, + defined_assets = False, + assets = None, + defined_assets_dir = False, + assets_dir = None, + exports_manifest = False, + stamp_manifest = True, + deps = [], + exports = [], + resource_files = None, + neverlink = False, + enable_data_binding = False, + android_test_migration = False, + fix_resource_transitivity = False, + aapt = None, + android_jar = None, + android_kit = None, + busybox = None, + java_toolchain = None, + host_javabase = None, + instrument_xslt = None, + xsltproc = None, + zip_tool = None): + """Processes Android Resources. + + Args: + ctx: The rules context. + java_package: string. Java package for which java sources will be + generated. By default the package is inferred from the directory where + the BUILD file containing the rule is. + manifest: File. The AndroidManifest.xml file. + defined_assets: Bool. Signifies that the assets attribute was set, even + if the value is an empty list. + assets: sequence of Files. A list of Android assets files to be processed. + defined_assets_dir: Bool. Signifies that the assets dir attribute was set, + even if the value is an empty string. + assets_dir: String. The name of the assets directory. + exports_manifest: boolean. Whether to export manifest entries to the + android_binary targets that depend on this target. + NOTE: "uses-permissions" attributes are never exported. + stamp_manifest: boolean. Whether to stamp the manifest with the java + package of the target. If True, java_package needs to be passed to + the function. + deps: sequence of Targets. The list of other libraries targets to link + against. + exports: sequence of Targets. The closure of all rules reached via exports + attributes are considered direct dependencies of any rule that directly + depends on the target with exports. The exports are not direct deps of + the rule they belong to (TODO(b/144134042): make this so). + resource_files: sequence of Files. A list of Android resource files to be + processed. + neverlink: boolean. Only use this library for compilation and not runtime. + The outputs of a rule marked as neverlink will not be used in .apk + creation. Useful if the library will be provided by the runtime + environment during execution. + enable_data_binding: boolean. If true, processesing the data binding + expressions in layout resources included through the resource_files + parameter is enabled. Without this setting, data binding expressions + produce build failures. + android_test_migration: boolean. If true, the target is part of the android + test to android instrumentation test migration and should not propagate + any Android Resource providers. + fix_resource_transitivity: Whether to ensure that transitive resources are + correctly marked as transitive. + aapt: FilesToRunProvider. The aapt executable or FilesToRunProvider. + android_jar: File. The android Jar. + android_kit: FilesToRunProvider. The android_kit executable or + FilesToRunProvider. + busybox: FilesToRunProvider. The ResourceBusyBox executable or + FilesToRunprovider + java_toolchain: The java_toolchain Target. + host_javabase: Target. The host javabase. + instrument_xslt: File. The xslt transform to apply g3itr. + xsltproc: FilesToRunProvider. The xsltproc executable or FilesToRunProvider. + zip_tool: FilesToRunProvider. The zip tool executable or FilesToRunProvider. + + Returns: + A dict containing _ResourcesProcessContextInfo provider fields. + """ + if (xsltproc and not instrument_xslt) or (not xsltproc and instrument_xslt): + fail( + "Error, both instrument_xslt and xsltproc need to be " + + "specified or not, got:\nxlstproc = %s\ninstrument_xslt = %s" % + (xsltproc, instrument_xslt), + ) + + _validate_resources(resource_files) + + defines_resources = bool( + manifest or + resource_files or + defined_assets or + defined_assets_dir or + exports_manifest, + ) + + # TODO(djwhang): Clean up the difference between neverlink the attribute used + # by Java compilation and resources neverlink. + resources_neverlink = ( + neverlink and ( + defines_resources or + ctx.fragments.android.fixed_resource_neverlinking + ) + ) + + resources_ctx = { + _RESOURCES_APK: None, + _PROVIDERS: [], + # TODO(b/156530953): Move the validation result to the validation_outputs list when we are + # done rolling out Starlark resources processing + _VALIDATION_RESULTS: [], + _DEFINES_RESOURCES: defines_resources, + _R_JAVA: None, + _MERGED_MANIFEST: None, + _STARLARK_PROCESSED_MANIFEST: None, + _STARLARK_R_TXT: None, + _STARLARK_PROCESSED_RESOURCES: [], + } + + if resource_files and not manifest: + _log.error(_MANIFEST_MISSING_ERROR % ctx.label) + + if stamp_manifest and not java_package: + _log.error(_JAVA_PACKAGE_MISSING_ERROR % ctx.label) + + direct_resources_nodes = [] + transitive_resources_nodes = [] + transitive_assets = [] + transitive_assets_symbols = [] + transitive_compiled_assets = [] + direct_compiled_resources = [] + transitive_compiled_resources = [] + transitive_resources_files = [] + transitive_manifests = [] + transitive_r_txts = [] + + for dep in utils.collect_providers(StarlarkAndroidResourcesInfo, deps): + direct_resources_nodes.append(dep.direct_resources_nodes) + transitive_resources_nodes.append(dep.transitive_resources_nodes) + transitive_assets.append(dep.transitive_assets) + transitive_assets_symbols.append(dep.transitive_assets_symbols) + transitive_compiled_assets.append(dep.transitive_compiled_assets) + direct_compiled_resources.append(dep.direct_compiled_resources) + transitive_compiled_resources.append(dep.transitive_compiled_resources) + transitive_resources_files.append(dep.transitive_resource_files) + transitive_manifests.append(dep.transitive_manifests) + transitive_r_txts.append(dep.transitive_r_txts) + + exports_direct_resources_nodes = [] + exports_transitive_resources_nodes = [] + exports_transitive_assets = [] + exports_transitive_assets_symbols = [] + exports_transitive_compiled_assets = [] + exports_direct_compiled_resources = [] + exports_transitive_compiled_resources = [] + exports_transitive_resources_files = [] + exports_transitive_manifests = [] + exports_transitive_r_txts = [] + for dep in utils.collect_providers(StarlarkAndroidResourcesInfo, exports): + exports_direct_resources_nodes.append(dep.direct_resources_nodes) + exports_transitive_resources_nodes.append(dep.transitive_resources_nodes) + exports_transitive_assets.append(dep.transitive_assets) + exports_transitive_assets_symbols.append(dep.transitive_assets_symbols) + exports_transitive_compiled_assets.append(dep.transitive_compiled_assets) + exports_direct_compiled_resources.append(dep.direct_compiled_resources) + exports_transitive_compiled_resources.append(dep.transitive_compiled_resources) + exports_transitive_resources_files.append(dep.transitive_resource_files) + exports_transitive_manifests.append(dep.transitive_manifests) + exports_transitive_r_txts.append(dep.transitive_r_txts) + + # TODO(b/144134042): Don't merge exports; exports are not deps. + direct_resources_nodes.extend(exports_direct_resources_nodes) + transitive_resources_nodes.extend(exports_transitive_resources_nodes) + transitive_assets.extend(exports_transitive_assets) + transitive_assets_symbols.extend(exports_transitive_assets_symbols) + transitive_compiled_assets.extend(exports_transitive_compiled_assets) + direct_compiled_resources.extend(exports_direct_compiled_resources) + transitive_compiled_resources.extend(exports_transitive_compiled_resources) + transitive_resources_files.extend(exports_transitive_resources_files) + transitive_manifests.extend(exports_transitive_manifests) + transitive_r_txts.extend(exports_transitive_r_txts) + + compiled_assets = None + parsed_assets = None + compiled_resources = None + out_aapt2_r_txt = None + r_txt = None + processed_resources = resource_files + processed_manifest = None + if not defines_resources: + if aapt: + # Generate an empty manifest with the right package + generated_manifest = ctx.actions.declare_file( + "_migrated/_generated/" + ctx.label.name + "/AndroidManifest.xml", + ) + _generate_dummy_manifest( + ctx, + generated_manifest, + java_package if java_package else ctx.label.package.replace("/", "."), + ) + r_txt = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_symbols/R.txt", + ) + out_manifest = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_processed_manifest/AndroidManifest.xml", + ) + _busybox.package( + ctx, + out_r_src_jar = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + ".srcjar", + ), + out_r_txt = r_txt, + out_manifest = out_manifest, + manifest = generated_manifest, + assets = assets, + assets_dir = assets_dir, + resource_files = resource_files, + direct_resources_nodes = + depset(transitive = direct_resources_nodes, order = "preorder"), + transitive_resources_nodes = + depset(transitive = transitive_resources_nodes, order = "preorder"), + transitive_assets = transitive_assets, + transitive_compiled_assets = transitive_compiled_assets, + transitive_resource_files = transitive_resources_files, + transitive_compiled_resources = transitive_compiled_resources, + transitive_manifests = transitive_manifests, + transitive_r_txts = transitive_r_txts, + package_type = "LIBRARY", + java_package = java_package, + android_jar = android_jar, + aapt = aapt, + busybox = busybox, + host_javabase = host_javabase, + should_throw_on_conflict = False, + ) + resources_ctx[_STARLARK_PROCESSED_MANIFEST] = out_manifest + resources_ctx[_STARLARK_R_TXT] = r_txt + resources_ctx[_STARLARK_PROCESSED_RESOURCES] = resource_files + + else: + if stamp_manifest: + stamped_manifest = ctx.actions.declare_file( + "_migrated/_renamed/" + ctx.label.name + "/AndroidManifest.xml", + ) + _busybox.merge_manifests( + ctx, + out_file = stamped_manifest, + manifest = manifest, + merge_type = "LIBRARY", + java_package = java_package, + busybox = busybox, + host_javabase = host_javabase, + ) + manifest = stamped_manifest + + if instrument_xslt: + g3itr_manifest = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_g3itr_manifest/AndroidManifest.xml", + ) + _add_g3itr( + ctx, + out_manifest = g3itr_manifest, + manifest = manifest, + xsltproc = xsltproc, + instrument_xslt = instrument_xslt, + ) + manifest = g3itr_manifest + + parsed_assets = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_symbols/assets.bin", + ) + _busybox.parse( + ctx, + out_symbols = parsed_assets, + assets = assets, + assets_dir = assets_dir, + busybox = busybox, + host_javabase = host_javabase, + ) + merged_assets = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_files/assets.zip", + ) + _busybox.merge_assets( + ctx, + out_assets_zip = merged_assets, + assets = assets, + assets_dir = assets_dir, + symbols = parsed_assets, + direct_resources_nodes = depset( + transitive = direct_resources_nodes, + order = "preorder", + ), + transitive_resources_nodes = depset( + transitive = transitive_resources_nodes, + order = "preorder", + ), + transitive_assets = transitive_assets, + transitive_assets_symbols = transitive_assets_symbols, + busybox = busybox, + host_javabase = host_javabase, + ) + resources_ctx[_VALIDATION_RESULTS].append(merged_assets) + + if assets: + compiled_assets = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_symbols/assets.zip", + ) + _busybox.compile( + ctx, + out_file = compiled_assets, + assets = assets, + assets_dir = assets_dir, + aapt = aapt, + busybox = busybox, + host_javabase = host_javabase, + ) + + if enable_data_binding: + out_databinding_info = ctx.actions.declare_file( + "_migrated/databinding/" + ctx.label.name + "/layout-info.zip", + ) + processed_resources, resources_dirname = _make_databinding_outputs( + ctx, + resource_files, + ) + _busybox.process_databinding( + ctx, + out_databinding_info = out_databinding_info, + out_databinding_processed_resources = processed_resources, + databinding_resources_dirname = resources_dirname, + resource_files = resource_files, + java_package = java_package, + busybox = busybox, + host_javabase = host_javabase, + ) + + compiled_resources = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_symbols/symbols.zip", + ) + _busybox.compile( + ctx, + out_file = compiled_resources, + resource_files = processed_resources, + aapt = aapt, + busybox = busybox, + host_javabase = host_javabase, + ) + + # TODO(b/160907203): Remove this fix once the native resource processing pipeline is turned off. + if enable_data_binding: + fixed_compiled_resources = ctx.actions.declare_file( + "_migrated/fixed/" + ctx.label.name + "_symbols/symbols.zip", + ) + _fix_databinding_compiled_resources( + ctx, + out_compiled_resources = fixed_compiled_resources, + compiled_resources = compiled_resources, + zip_tool = zip_tool, + ) + compiled_resources = fixed_compiled_resources + + out_class_jar = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_resources.jar", + ) + processed_manifest = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_processed_manifest/AndroidManifest.xml", + ) + out_aapt2_r_txt = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_symbols/R.aapt2.txt", + ) + _busybox.merge_compiled( + ctx, + out_class_jar = out_class_jar, + out_manifest = processed_manifest, + out_aapt2_r_txt = out_aapt2_r_txt, + java_package = java_package, + manifest = manifest, + compiled_resources = compiled_resources, + direct_resources_nodes = + depset(transitive = direct_resources_nodes, order = "preorder"), + transitive_resources_nodes = depset( + transitive = transitive_resources_nodes, + order = "preorder", + ), + direct_compiled_resources = depset( + transitive = direct_compiled_resources, + order = "preorder", + ), + transitive_compiled_resources = depset( + transitive = transitive_compiled_resources, + order = "preorder", + ), + android_jar = android_jar, + busybox = busybox, + host_javabase = host_javabase, + ) + resources_ctx[_MERGED_MANIFEST] = processed_manifest + + apk = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_files/library.ap_", + ) + r_java = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + ".srcjar", + ) + r_txt = ctx.actions.declare_file( + "_migrated/" + ctx.label.name + "_symbols/R.txt", + ) + _busybox.validate_and_link( + ctx, + out_r_src_jar = r_java, + out_r_txt = r_txt, + out_file = apk, + compiled_resources = compiled_resources, + transitive_compiled_resources = depset( + transitive = transitive_compiled_resources, + order = "preorder", + ), + java_package = java_package, + manifest = processed_manifest, + android_jar = android_jar, + aapt = aapt, + busybox = busybox, + host_javabase = host_javabase, + ) + resources_ctx[_RESOURCES_APK] = apk + + java_info = JavaInfo( + output_jar = out_class_jar, + compile_jar = out_class_jar, + source_jar = r_java, + ) + + resources_ctx[_R_JAVA] = java_info + + # In a normal build, the outputs of _busybox.validate_and_link are unused. However we need + # this action to run to support resource visibility checks. + resources_ctx[_VALIDATION_RESULTS].append(r_txt) + + # Needed for AAR generation. The Starlark resource processing pipeline uses the aapt2_r_txt file, + # which is why we can't use the StarlarkAndroidResourcesInfo provider when generating the aar. + resources_ctx[_STARLARK_PROCESSED_MANIFEST] = processed_manifest + resources_ctx[_STARLARK_R_TXT] = r_txt + resources_ctx[_STARLARK_PROCESSED_RESOURCES] = processed_resources + + # TODO(b/117338320): Transitive lists defined here are incorrect; direct should come + # before transitive, and the order should be topological order instead of preorder. + # However, some applications may depend on this incorrect order. + if defines_resources: + transitive_resources_nodes = transitive_resources_nodes + direct_resources_nodes + direct_resources_nodes = [] + transitive_compiled_resources = transitive_compiled_resources + direct_compiled_resources + direct_compiled_resources = [] + else: + if fix_resource_transitivity: + transitive_resources_nodes = transitive_resources_nodes + direct_resources_nodes + direct_resources_nodes = [] + transitive_compiled_resources = transitive_compiled_resources + direct_compiled_resources + direct_compiled_resources = [] + + # TODO(b/144163743): If the resource transitivity fix is disabled and resources-related + # inputs are missing, we implicitly export deps here. This legacy behavior must exist in the + # Starlark resource processing pipeline until we can clean up the depot. + + # TODO(b/159916013): Audit neverlink behavior. Some processing can likely be skipped if the target is neverlink. + # TODO(b/69668042): Don't propagate exported providers/artifacts. Exports should respect neverlink. + if resources_neverlink: + resources_ctx[_PROVIDERS].append(StarlarkAndroidResourcesInfo( + direct_resources_nodes = depset( + transitive = exports_direct_resources_nodes, + order = "preorder", + ), + transitive_resources_nodes = depset( + transitive = exports_transitive_resources_nodes, + order = "preorder", + ), + transitive_assets = depset( + transitive = exports_transitive_assets, + order = "preorder", + ), + transitive_assets_symbols = depset( + transitive = exports_transitive_assets_symbols, + order = "preorder", + ), + transitive_compiled_assets = depset( + transitive = exports_transitive_compiled_assets, + order = "preorder", + ), + transitive_resource_files = depset( + transitive = exports_transitive_resources_files, + order = "preorder", + ), + direct_compiled_resources = depset( + transitive = exports_direct_compiled_resources, + order = "preorder", + ), + transitive_compiled_resources = depset( + transitive = exports_transitive_compiled_resources, + order = "preorder", + ), + transitive_manifests = depset( + [processed_manifest] if processed_manifest else [], + transitive = exports_transitive_manifests, + order = "preorder", + ), + transitive_r_txts = depset( + [out_aapt2_r_txt] if out_aapt2_r_txt else [], + transitive = exports_transitive_r_txts, + order = "preorder", + ), + )) + else: + # Depsets are ordered below to match the order in the legacy native rules. + resources_ctx[_PROVIDERS].append(StarlarkAndroidResourcesInfo( + direct_resources_nodes = depset( + [ResourcesNodeInfo( + label = ctx.label, + assets = depset(assets), + assets_dir = assets_dir, + assets_symbols = parsed_assets, + compiled_assets = compiled_assets, + resource_files = depset(processed_resources), + compiled_resources = compiled_resources, + r_txt = out_aapt2_r_txt, + manifest = processed_manifest, + exports_manifest = exports_manifest, + )] if defines_resources else [], + transitive = direct_resources_nodes + exports_direct_resources_nodes, + order = "preorder", + ), + transitive_resources_nodes = depset( + transitive = transitive_resources_nodes + exports_transitive_resources_nodes, + order = "preorder", + ), + transitive_assets = depset( + assets, + transitive = transitive_assets + exports_transitive_assets, + order = "preorder", + ), + transitive_assets_symbols = depset( + [parsed_assets] if parsed_assets else [], + transitive = transitive_assets_symbols + exports_transitive_assets_symbols, + order = "preorder", + ), + transitive_compiled_assets = depset( + [compiled_assets] if compiled_assets else [], + transitive = transitive_compiled_assets + exports_transitive_compiled_assets, + order = "preorder", + ), + transitive_resource_files = depset( + processed_resources, + transitive = transitive_resources_files + exports_transitive_resources_files, + order = "preorder", + ), + direct_compiled_resources = depset( + [compiled_resources] if compiled_resources else [], + transitive = direct_compiled_resources + exports_direct_compiled_resources, + order = "preorder", + ), + transitive_compiled_resources = depset( + [compiled_resources] if compiled_resources else [], + transitive = transitive_compiled_resources + exports_transitive_compiled_resources, + order = "preorder", + ), + transitive_manifests = depset( + [processed_manifest] if processed_manifest else [], + transitive = transitive_manifests + exports_transitive_manifests, + order = "preorder", + ), + transitive_r_txts = depset( + [out_aapt2_r_txt] if out_aapt2_r_txt else [], + transitive = transitive_r_txts + exports_transitive_r_txts, + order = "preorder", + ), + )) + + # Do not collect resources and R.java for test apk + if android_test_migration: + resources_ctx[_R_JAVA] = None + resources_ctx[_PROVIDERS] = [] + + # TODO(b/69552500): In the Starlark Android Rules, the R compile time + # JavaInfo is added as a runtime dependency to the JavaInfo. Stop + # adding the R.jar as a runtime dependency. + resources_ctx[_PROVIDERS].append( + AndroidLibraryResourceClassJarProvider( + depset( + (resources_ctx[_R_JAVA].runtime_output_jars if resources_ctx[_R_JAVA] else []), + transitive = [ + p.jars + for p in utils.collect_providers( + AndroidLibraryResourceClassJarProvider, + deps, + exports, + ) + ], + order = "preorder", + ), + ), + ) + + return resources_ctx + + +def _process( + ctx, + manifest = None, + resource_files = None, + defined_assets = False, + assets = None, + defined_assets_dir = False, + assets_dir = None, + exports_manifest = False, + java_package = None, + custom_package = None, + neverlink = False, + enable_data_binding = False, + deps = [], + exports = [], + android_jar = None, + android_kit = None, + aapt = None, + busybox = None, + xsltproc = None, + instrument_xslt = None, + java_toolchain = None, + host_javabase = None, + enable_res_v3 = False, + res_v3_dummy_manifest = None, + res_v3_dummy_r_txt = None, + fix_resource_transitivity = False, + fix_export_exporting = False, + android_test_migration = False, + zip_tool = None): + out_ctx = _process_starlark( + ctx, + java_package = java_package, + manifest = manifest, + defined_assets = defined_assets, + # TODO(b/159937795): When the Starlark Resources Processing pipeline is + # default and the native version is no longer used, remove the depset + # creation and directly pass through ctx.files.assets to this method. + assets = + depset(transitive = [target.files for target in assets]).to_list(), + defined_assets_dir = defined_assets_dir, + assets_dir = assets_dir, + exports_manifest = exports_manifest, + stamp_manifest = True if java_package else False, + deps = deps, + exports = exports, + resource_files = depset(transitive = [target.files for target in resource_files]).to_list(), + enable_data_binding = enable_data_binding, + fix_resource_transitivity = fix_resource_transitivity, + neverlink = neverlink, + android_test_migration = android_test_migration, + android_jar = android_jar, + aapt = aapt, + android_kit = android_kit, + busybox = busybox, + instrument_xslt = instrument_xslt, + xsltproc = xsltproc, + java_toolchain = java_toolchain, + host_javabase = host_javabase, + zip_tool = zip_tool, + ) + + + if _VALIDATION_OUTPUTS not in out_ctx: + out_ctx[_VALIDATION_OUTPUTS] = [] + + return _ResourcesProcessContextInfo(**out_ctx) + +resources = struct( + process = _process, + process_starlark = _process_starlark, + package = _package, + make_aar = _make_aar, + + # Exposed for mobile-install + compile = _compile, + legacy_merge_manifests = _legacy_merge_manifests, + + # Exposed for android_local_test and android_library + generate_dummy_manifest = _generate_dummy_manifest, +) + +testing = struct( + add_g3itr = _add_g3itr, + filter_multi_cpu_configuration_targets = _filter_multi_cpu_configuration_targets, + get_legacy_mergee_manifests = _get_legacy_mergee_manifests, + make_databinding_outputs = _make_databinding_outputs, + ResourcesPackageContextInfo = _ResourcesPackageContextInfo, + ResourcesProcessContextInfo = _ResourcesProcessContextInfo, +) diff --git a/rules/robolectric_properties_template.txt b/rules/robolectric_properties_template.txt new file mode 100644 index 0000000..d05a28c --- /dev/null +++ b/rules/robolectric_properties_template.txt @@ -0,0 +1,5 @@ +android_merged_manifest=%android_merged_manifest% +android_merged_resources=%android_merged_resources% +android_merged_assets=%android_merged_assets% +android_custom_package=%android_custom_package% +android_resource_apk=%android_resource_apk% diff --git a/rules/rules.bzl b/rules/rules.bzl new file mode 100644 index 0000000..e849d72 --- /dev/null +++ b/rules/rules.bzl @@ -0,0 +1,129 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Skylark rules for building Android apps.""" + +load( + "//rules/aar_import:rule.bzl", + _aar_import = "aar_import", +) + +#load( +# ":apk_import.bzl", +# _apk_import = "apk_import", +#) + +load( + ":android_binary.bzl", + _android_binary = "android_binary", +) + +# load( +# ":android_device.bzl", +# _android_device = "android_device", +# ) +# load( +# ":android_device_script_fixture.bzl", +# _android_device_script_fixture = "android_device_script_fixture", +# ) +# load( +# ":android_host_service_fixture.bzl", +# _android_host_service_fixture = "android_host_service_fixture", +# ) +# load( +# ":android_instrumentation_test.bzl", +# _android_instrumentation_test = "android_instrumentation_test", +# ) + +load( + "//rules/android_library:rule.bzl", + _android_library = "android_library_macro", +) + +# load( +# ":android_local_test.bzl", +# _android_local_test = "android_local_test", +# ) + +load( + ":android_ndk_repository.bzl", + _android_ndk_repository = "android_ndk_repository", +) +load( + ":android_sdk.bzl", + _android_sdk = "android_sdk", +) +load( + ":android_sdk_repository.bzl", + _android_sdk_repository = "android_sdk_repository", +) +load( + ":android_tools_defaults_jar.bzl", + _android_tools_defaults_jar = "android_tools_defaults_jar", +) + +# Current version. Tools may check this to determine compatibility. +RULES_ANDROID_VERSION = "0.1.0" + +aar_import = _aar_import + +"""https://docs.bazel.build/versions/master/be/android.html#android_apk_to_bundle""" + +android_binary = _android_binary + +"""https://docs.bazel.build/versions/master/be/android.html#android_binary""" + +#android_device = _android_device + +"""https://docs.bazel.build/versions/master/be/android.html#android_device""" + +#android_device_script_fixture = _android_device_script_fixture + +"""https://docs.bazel.build/versions/master/be/android.html#android_host_service_fixture""" + +#android_host_service_fixture = _android_host_service_fixture + +"""https://docs.bazel.build/versions/master/be/android.html#android_device_script_fixture""" + +#android_instrumentation_test = _android_instrumentation_test + +"""https://docs.bazel.build/versions/master/be/android.html#android_instrumentation_test""" + +android_library = _android_library + +"""https://docs.bazel.build/versions/master/be/android.html#android_library""" + +#android_local_test = _android_local_test + +"""https://docs.bazel.build/versions/master/be/android.html#android_local_test""" + +android_ndk_repository = _android_ndk_repository + +"""https://docs.bazel.build/versions/master/be/android.html#android_ndk_repository""" + +android_sdk = _android_sdk + +"""https://docs.bazel.build/versions/master/be/android.html#android_sdk""" + +android_sdk_repository = _android_sdk_repository + +"""https://docs.bazel.build/versions/master/be/android.html#android_sdk_repository""" + +android_tools_defaults_jar = _android_tools_defaults_jar + +"""https://docs.bazel.build/versions/master/be/android.html#android_tools_defaults_jar""" + +#apk_import = _apk_import +# +#"""https://docs.bazel.build/versions/master/be/android.html#apk_import""" diff --git a/rules/toolchains/emulator/BUILD b/rules/toolchains/emulator/BUILD new file mode 100644 index 0000000..a02375a --- /dev/null +++ b/rules/toolchains/emulator/BUILD @@ -0,0 +1,27 @@ +# Description: +# Defines an emulator toolchain so that the emulator used for android_device +# can be configured at build-time. + +load(":toolchain.bzl", "emulator_toolchain") + +package(default_visibility = ["//visibility:public"]) + +# By convention, toolchain_type targets are named "toolchain_type" +# and distinguished by their package path. +toolchain_type( + name = "toolchain_type", +) + +emulator_toolchain( + name = "emulator_default", + emulator = "@androidsdk//:emulator", + emulator_deps = [ + "@androidsdk//:emulator_shared_libs", + ], +) + +toolchain( + name = "emulator_default_toolchain", + toolchain = ":emulator_default", + toolchain_type = ":toolchain_type", +) diff --git a/rules/toolchains/emulator/toolchain.bzl b/rules/toolchains/emulator/toolchain.bzl new file mode 100644 index 0000000..61bfb77 --- /dev/null +++ b/rules/toolchains/emulator/toolchain.bzl @@ -0,0 +1,59 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Defines the emulator_toolchain rule to allow configuring emulator binaries to use.""" + +EmulatorInfo = provider( + doc = "Information used to launch a specific version of the emulator.", + fields = { + "emulator": "A label for the emulator launcher executable at stable version.", + "emulator_deps": "Additional files required to launch the stable version of emulator.", + "emulator_suffix": "An optional path suffix used to find emulator binary under the emulator label path", + }, +) + +def _emulator_toolchain_impl(ctx): + toolchain_info = platform_common.ToolchainInfo( + info = EmulatorInfo( + emulator = ctx.attr.emulator, + emulator_deps = ctx.attr.emulator_deps, + emulator_suffix = ctx.attr.emulator_suffix, + ), + ) + return [toolchain_info] + +emulator_toolchain = rule( + implementation = _emulator_toolchain_impl, + attrs = { + "emulator": attr.label( + allow_files = True, + cfg = "host", + mandatory = True, + ), + "emulator_deps": attr.label_list( + allow_files = True, + cfg = "host", + ), + "emulator_head": attr.label( + allow_files = True, + cfg = "host", + ), + "emulator_head_deps": attr.label_list( + allow_files = True, + cfg = "host", + ), + "emulator_suffix": attr.string(default = ""), + "emulator_head_suffix": attr.string(default = ""), + }, +) diff --git a/rules/utils.bzl b/rules/utils.bzl new file mode 100644 index 0000000..76a0fd2 --- /dev/null +++ b/rules/utils.bzl @@ -0,0 +1,451 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Utilities for the Android rules.""" + +load(":providers.bzl", "FailureInfo") + +_CUU = "\033[A" +_EL = "\033[K" +_DEFAULT = "\033[0m" +_BOLD = "\033[1m" +_RED = "\033[31m" +_GREEN = "\033[32m" +_MAGENTA = "\033[35m" +_ERASE_PREV_LINE = "\n" + _CUU + _EL + +_INFO = _ERASE_PREV_LINE + _GREEN + "INFO: " + _DEFAULT + "%s" +_WARNING = _ERASE_PREV_LINE + _MAGENTA + "WARNING: " + _DEFAULT + "%s" +_ERROR = _ERASE_PREV_LINE + _BOLD + _RED + "ERROR: " + _DEFAULT + "%s" + +_WORD_CHARS = { + "A": True, + "B": True, + "C": True, + "D": True, + "E": True, + "F": True, + "G": True, + "H": True, + "I": True, + "J": True, + "K": True, + "L": True, + "M": True, + "N": True, + "O": True, + "P": True, + "Q": True, + "R": True, + "S": True, + "T": True, + "U": True, + "V": True, + "W": True, + "X": True, + "Y": True, + "Z": True, + "a": True, + "b": True, + "c": True, + "d": True, + "e": True, + "f": True, + "g": True, + "h": True, + "i": True, + "j": True, + "k": True, + "l": True, + "m": True, + "n": True, + "o": True, + "p": True, + "q": True, + "r": True, + "s": True, + "t": True, + "u": True, + "v": True, + "w": True, + "x": True, + "y": True, + "z": True, + "0": True, + "1": True, + "2": True, + "3": True, + "4": True, + "5": True, + "6": True, + "7": True, + "8": True, + "9": True, + "_": True, +} + +_HEX_CHAR = { + 0x0: "0", + 0x1: "1", + 0x2: "2", + 0x3: "3", + 0x4: "4", + 0x5: "5", + 0x6: "6", + 0x7: "7", + 0x8: "8", + 0x9: "9", + 0xA: "A", + 0xB: "B", + 0xC: "C", + 0xD: "D", + 0xE: "E", + 0xF: "F", +} + +_JAVA_RESERVED = { + "abstract": True, + "assert": True, + "boolean": True, + "break": True, + "byte": True, + "case": True, + "catch": True, + "char": True, + "class": True, + "const": True, + "continue": True, + "default": True, + "do": True, + "double": True, + "else": True, + "enum": True, + "extends": True, + "final": True, + "finally": True, + "float": True, + "for": True, + "goto": True, + "if": True, + "implements": True, + "import": True, + "instanceof": True, + "int": True, + "interface": True, + "long": True, + "native": True, + "new": True, + "package": True, + "private": True, + "protected": True, + "public": True, + "return": True, + "short": True, + "static": True, + "strictfp": True, + "super": True, + "switch": True, + "synchronized": True, + "this": True, + "throw": True, + "throws": True, + "transient": True, + "try": True, + "void": True, + "volatile": True, + "while": True, + "true": True, + "false": True, + "null": True, +} + +def _collect_providers(provider, *all_deps): + """Collects the requested providers from the given list of deps.""" + providers = [] + for deps in all_deps: + for dep in deps: + if provider in dep: + providers.append(dep[provider]) + return providers + +def _join_depsets(providers, attr, order = "default"): + """Returns a merged depset using 'attr' from each provider in 'providers'.""" + return depset(transitive = [getattr(p, attr) for p in providers], order = order) + +def _first(collection): + """Returns the first item in the collection.""" + for i in collection: + return i + return _error("The collection is empty.") + +def _only(collection): + """Returns the only item in the collection.""" + if len(collection) != 1: + _error("Expected one element, has %s." % len(collection)) + return _first(collection) + +def _copy_file(ctx, src, dest): + if src.is_directory or dest.is_directory: + fail("Cannot use copy_file with directories") + ctx.actions.run_shell( + command = "cp --reflink=auto $1 $2", + arguments = [src.path, dest.path], + inputs = [src], + outputs = [dest], + mnemonic = "CopyFile", + progress_message = "Copy %s to %s" % (src.short_path, dest.short_path), + ) + +def _copy_dir(ctx, src, dest): + if not src.is_directory: + fail("copy_dir src must be a directory") + ctx.actions.run_shell( + command = "cp -r --reflink=auto $1 $2", + arguments = [src.path, dest.path], + inputs = [src], + outputs = [dest], + mnemonic = "CopyDir", + progress_message = "Copy %s to %s" % (src.short_path, dest.short_path), + ) + +def _info(msg): + """Print info.""" + print(_INFO % msg) + +def _warn(msg): + """Print warning.""" + print(_WARNING % msg) + +def _debug(msg): + """Print debug.""" + print("\n%s" % msg) + +def _error(msg): + """Print error and fail.""" + fail(_ERASE_PREV_LINE + _CUU + _ERASE_PREV_LINE + _CUU + _ERROR % msg) + +def _expand_var(config_vars, value): + """Expands make variables of the form $(SOME_VAR_NAME) for a single value. + + "$$(SOME_VAR_NAME)" is escaped to a literal value of "$(SOME_VAR_NAME)" instead of being + expanded. + + Args: + config_vars: String dictionary which maps config variables to their expanded values. + value: The string to apply substitutions to. + + Returns: + The string value with substitutions applied. + """ + parts = value.split("$(") + replacement = parts[0] + last_char = replacement[-1] if replacement else "" + for part in parts[1:]: + var_end = part.find(")") + if last_char == "$": + # If "$$(..." is found, treat it as "$(..." + replacement += "(" + part + elif var_end == -1 or part[:var_end] not in config_vars: + replacement += "$(" + part + else: + replacement += config_vars[part[:var_end]] + part[var_end + 1:] + last_char = replacement[-1] if replacement else "" + return replacement + +def _expand_make_vars(ctx, vals): + """Expands make variables of the form $(SOME_VAR_NAME). + + Args: + ctx: The rules context. + vals: Dictionary. Values of the form $(...) will be replaced. + + Returns: + A dictionary containing vals.keys() and the expanded values. + """ + res = {} + for k, v in vals.items(): + res[k] = _expand_var(ctx.var, v) + return res + +def _get_runfiles(ctx, attrs): + runfiles = ctx.runfiles() + for attr in attrs: + executable = attr[DefaultInfo].files_to_run.executable + if executable: + runfiles = runfiles.merge(ctx.runfiles([executable])) + runfiles = runfiles.merge( + ctx.runfiles( + # Wrap DefaultInfo.files in depset to strip ordering. + transitive_files = depset( + transitive = [attr[DefaultInfo].files], + ), + ), + ) + runfiles = runfiles.merge(attr[DefaultInfo].default_runfiles) + return runfiles + +def _sanitize_string(s, replacement = ""): + """Sanitizes a string by replacing all non-word characters. + + This matches the \\w regex character class [A_Za-z0-9_]. + + Args: + s: String to sanitize. + replacement: Replacement for all non-word characters. Optional. + + Returns: + The original string with all non-word characters replaced. + """ + return "".join([s[i] if s[i] in _WORD_CHARS else replacement for i in range(len(s))]) + +def _hex(n, pad = True): + """Convert an integer number to an uppercase hexadecimal string. + + Args: + n: Integer number. + pad: Optional. Pad the result to 8 characters with leading zeroes. Default = True. + + Returns: + Return a representation of an integer number as a hexadecimal string. + """ + hex_str = "" + for _ in range(8): + r = n % 16 + n = n // 16 + hex_str = _HEX_CHAR[r] + hex_str + if pad: + return hex_str + else: + return hex_str.lstrip("0") + +def _sanitize_java_package(pkg): + return ".".join(["xxx" if p in _JAVA_RESERVED else p for p in pkg.split(".")]) + +def _check_for_failures(label, *all_deps): + """Collects FailureInfo providers from the given list of deps and fails if there's at least one.""" + failure_infos = _collect_providers(FailureInfo, *all_deps) + if failure_infos: + error = "in label '%s':" % label + for failure_info in failure_infos: + error += "\n\t" + failure_info.error + _error(error) + +def _run_validation( + ctx, + validation_out, + executable, + outputs = [], + tools = [], + **args): + """Creates an action that runs an executable as a validation. + + Note: When the validation executable fails, it should return a non-zero + value to signify a validation failure. + + Args: + ctx: The context. + validation_out: A File. The output of the executable is piped to the + file. This artifact should then be propagated to "validations" in the + OutputGroupInfo. + executable: See ctx.actions.run#executable. + outputs: See ctx.actions.run#outputs. + tools: See ctx.actions.run#tools. + **args: Remaining args are directly propagated to ctx.actions.run_shell. + See ctx.actions.run_shell for further documentation. + """ + exec_type = type(executable) + exec_bin = None + exec_bin_path = None + if exec_type == "FilesToRunProvider": + exec_bin = executable.executable + exec_bin_path = exec_bin.path + elif exec_type == "File": + exec_bin = executable + exec_bin_path = exec_bin.path + elif exec_type == type(""): + exec_bin_path = executable + else: + fail( + "Error, executable should be a File, FilesToRunProvider or a " + + "string that represents a path to a tool, got: %s" % exec_type, + ) + + ctx.actions.run_shell( + command = """#!/bin/bash +set -eu +set -o pipefail # Returns the executables failure code, if it fails. + +EXECUTABLE={executable} +VALIDATION_OUT={validation_out} + +"${{EXECUTABLE}}" $@ 2>&1 | tee -a "${{VALIDATION_OUT}}" +""".format( + executable = exec_bin_path, + validation_out = validation_out.path, + ), + tools = tools + ([exec_bin] if exec_bin else []), + outputs = [validation_out] + outputs, + **args + ) + +def get_android_toolchain(ctx): + return ctx.toolchains["@rules_android//toolchains/android:toolchain_type"] + +def get_android_sdk(ctx): + if hasattr(ctx.fragments.android, "incompatible_use_toolchain_resolution") and ctx.fragments.android.incompatible_use_toolchain_resolution: + return ctx.toolchains["@rules_android//toolchains/android_sdk:toolchain_type"].android_sdk_info + else: + return ctx.attr._android_sdk[AndroidSdkInfo] + +def _get_compilation_mode(ctx): + """Retrieves the compilation mode from the context. + + Returns: + A string that represents the compilation mode. + """ + return ctx.var["COMPILATION_MODE"] + +compilation_mode = struct( + DBG = "dbg", + FASTBUILD = "fastbuild", + OPT = "opt", + get = _get_compilation_mode, +) + +utils = struct( + check_for_failures = _check_for_failures, + collect_providers = _collect_providers, + copy_file = _copy_file, + copy_dir = _copy_dir, + expand_make_vars = _expand_make_vars, + first = _first, + get_runfiles = _get_runfiles, + join_depsets = _join_depsets, + only = _only, + run_validation = _run_validation, + sanitize_string = _sanitize_string, + sanitize_java_package = _sanitize_java_package, + hex = _hex, +) + +log = struct( + debug = _debug, + error = _error, + info = _info, + warn = _warn, +) + +testing = struct( + expand_var = _expand_var, +) diff --git a/test/rules/resources/BUILD b/test/rules/resources/BUILD new file mode 100644 index 0000000..e9ef118 --- /dev/null +++ b/test/rules/resources/BUILD @@ -0,0 +1,4 @@ +# Used in android_binary_internal resources diff test +exports_files( + ["test_stub_script.sh"], +) diff --git a/toolchains/android/BUILD b/toolchains/android/BUILD new file mode 100644 index 0000000..6c731a9 --- /dev/null +++ b/toolchains/android/BUILD @@ -0,0 +1,52 @@ +# Description: +# Defines the Android toolchain. + +load(":toolchain.bzl", "android_toolchain") +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + +licenses(["notice"]) + +filegroup( + name = "all_files", + srcs = glob(["**"]), +) + +# Android Toolchain Type +toolchain_type(name = "toolchain_type") + +# Default Android Toolchain +android_toolchain( + name = "android_default", + visibility = ["//visibility:public"], +) + +toolchain( + name = "android_default_toolchain", + toolchain = ":android_default", + toolchain_type = ":toolchain_type", +) + +bzl_library( + name = "bzl", + srcs = glob(["*.bzl"]), +) + +genrule( + name = "gen_unzip", + outs = ["unzip.sh"], + cmd = """cat > $@ <<EOF +unzip \\$$@ +EOF +""", + executable = True, +) + +sh_binary( + name = "zip", + srcs = [":zip.sh"], +) + +sh_binary( + name = "unzip", + srcs = [":unzip.sh"], +) diff --git a/toolchains/android/toolchain.bzl b/toolchains/android/toolchain.bzl new file mode 100644 index 0000000..b356447 --- /dev/null +++ b/toolchains/android/toolchain.bzl @@ -0,0 +1,167 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Android toolchain.""" + +_ATTRS = dict( + aapt2 = attr.label( + allow_files = True, + default = "@androidsdk//:aapt2_binary", + ), + aar_embedded_jars_extractor = attr.label( + allow_files = True, + cfg = "host", + default = "@bazel_tools//tools/android:aar_embedded_jars_extractor", + executable = True, + ), + aar_native_libs_zip_creator = attr.label( + allow_files = True, + cfg = "host", + default = "@bazel_tools//tools/android:aar_native_libs_zip_creator", + executable = True, + ), + aar_resources_extractor = attr.label( + allow_files = True, + cfg = "host", + default = "@bazel_tools//tools/android:aar_resources_extractor", + executable = True, + ), + adb = attr.label( + allow_files = True, + cfg = "host", + default = "@androidsdk//:platform-tools/adb", + executable = True, + ), + add_g3itr_xslt = attr.label( + cfg = "host", + default = Label("//tools/android/xslt:add_g3itr.xslt"), + allow_files = True, + ), + android_kit = attr.label( + allow_files = True, + cfg = "host", + default = "@androidsdk//:fail", # TODO: "//src/tools/ak", needs Go + executable = True, + ), + android_resources_busybox = attr.label( + allow_files = True, + cfg = "host", + default = "@bazel_tools//src/tools/android/java/com/google/devtools/build/android:ResourceProcessorBusyBox_deploy.jar", + executable = True, + ), + apk_to_bundle_tool = attr.label( + allow_files = True, + cfg = "host", + default = "@androidsdk//:fail", + executable = True, + ), + bundletool = attr.label( + allow_files = True, + cfg = "host", + default = "@androidsdk//:fail", + executable = True, + ), + data_binding_annotation_processor = attr.label( + cfg = "host", + default = "@//tools/android:compiler_annotation_processor", # TODO: processor rules should be moved into rules_android + ), + data_binding_annotation_template = attr.label( + default = "//rules:data_binding_annotation_template.txt", + allow_files = True, + ), + data_binding_exec = attr.label( + cfg = "host", + default = "@bazel_tools//tools/android:databinding_exec", + executable = True, + ), + desugar_java8_extra_bootclasspath = attr.label( + allow_files = True, + cfg = "host", + default = "@bazel_tools//tools/android:desugar_java8_extra_bootclasspath", + executable = True, + ), + idlclass = attr.label( + allow_files = True, + cfg = "host", + default = "@bazel_tools//tools/android:IdlClass", # _deploy.jar? + executable = True, + ), + import_deps_checker = attr.label( + allow_files = True, + cfg = "host", + default = "@android_tools//:ImportDepsChecker_deploy.jar", + executable = True, + ), + jacocorunner = attr.label( + default = "@androidsdk//:fail", + ), + java_stub = attr.label( + allow_files = True, + # used in android_local_test + default = "@androidsdk//:fail", # TODO: java_stub_template.txt gets embedded in bazel's jar, need a copy in @bazel_tools or similar + ), + jdeps_tool = attr.label( + allow_files = True, + cfg = "host", + # used in android_local_test + default = "@androidsdk//:fail", # TODO: "//src/tools/jdeps", needs Go + executable = True, + ), + proguard_allowlister = attr.label( + cfg = "host", + default = "@bazel_tools//tools/jdk:proguard_whitelister", + executable = True, + ), + res_v3_dummy_manifest = attr.label( + allow_files = True, + default = "//rules:res_v3_dummy_AndroidManifest.xml", + ), + res_v3_dummy_r_txt = attr.label( + allow_files = True, + default = "//rules:res_v3_dummy_R.txt", + ), + robolectric_template = attr.label( + allow_files = True, + default = "//rules:robolectric_properties_template.txt", + ), + testsupport = attr.label( + default = "@androidsdk//:fail", + ), + unzip_tool = attr.label( + cfg = "host", + default = "//toolchains/android:unzip", + executable = True, + ), + xsltproc_tool = attr.label( + cfg = "host", + default = Label("//tools/android/xslt:xslt"), + allow_files = True, + executable = True, + ), + zip_tool = attr.label( + cfg = "host", + default = "//toolchains/android:zip", + executable = True, + ), +) + +def _impl(ctx): + return [platform_common.ToolchainInfo( + **{name: getattr(ctx.attr, name) for name in _ATTRS.keys()} + )] + +android_toolchain = rule( + implementation = _impl, + attrs = _ATTRS, +) diff --git a/toolchains/android/zip.sh b/toolchains/android/zip.sh new file mode 100755 index 0000000..5d0f18b --- /dev/null +++ b/toolchains/android/zip.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +args=() +for arg in "$@"; do + if [[ ! "$arg" == "-jt" ]]; then + args+=( "$arg" ) + fi +done + +zip ${args[@]} diff --git a/toolchains/android_sdk/BUILD b/toolchains/android_sdk/BUILD new file mode 100644 index 0000000..10e40ca --- /dev/null +++ b/toolchains/android_sdk/BUILD @@ -0,0 +1,27 @@ +# Description: +# Defines the Android SDK toolchain. + +licenses(["notice"]) + +filegroup( + name = "all_files", + srcs = glob(["**"]), +) + +# Android SDK Toolchain Type +toolchain_type(name = "toolchain_type") + +toolchain( + name = "android_sdk_tools", + exec_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:linux", + ], + # TODO(b/175833893): This causes the toolchain to not be selected, so + # disable for now. + #target_compatible_with = [ + # "@bazel_tools//platforms:android", + #], + toolchain = "@androidsdk//:sdk", + toolchain_type = ":toolchain_type", +) diff --git a/toolchains/emulator/BUILD b/toolchains/emulator/BUILD new file mode 100644 index 0000000..a02375a --- /dev/null +++ b/toolchains/emulator/BUILD @@ -0,0 +1,27 @@ +# Description: +# Defines an emulator toolchain so that the emulator used for android_device +# can be configured at build-time. + +load(":toolchain.bzl", "emulator_toolchain") + +package(default_visibility = ["//visibility:public"]) + +# By convention, toolchain_type targets are named "toolchain_type" +# and distinguished by their package path. +toolchain_type( + name = "toolchain_type", +) + +emulator_toolchain( + name = "emulator_default", + emulator = "@androidsdk//:emulator", + emulator_deps = [ + "@androidsdk//:emulator_shared_libs", + ], +) + +toolchain( + name = "emulator_default_toolchain", + toolchain = ":emulator_default", + toolchain_type = ":toolchain_type", +) diff --git a/tools/android/BUILD b/tools/android/BUILD new file mode 100644 index 0000000..c0f554c --- /dev/null +++ b/tools/android/BUILD @@ -0,0 +1,13 @@ +load(":defs.bzl", "android_jar") + +android_jar( + name = "android_jar", + visibility = ["//visibility:public"], +) + +# TODO(b/175833857): This is a stub, should remove. +alias( + name = "merge_manifests", + actual = "@androidsdk//:fail", + visibility = ["//visibility:public"], +) diff --git a/tools/android/defs.bzl b/tools/android/defs.bzl new file mode 100644 index 0000000..6aa1896 --- /dev/null +++ b/tools/android/defs.bzl @@ -0,0 +1,27 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A rule that returns android.jar from the current android sdk.""" + +def _android_jar_impl(ctx): + return DefaultInfo( + files = depset([ctx.attr._sdk[AndroidSdkInfo].android_jar]), + ) + +android_jar = rule( + implementation = _android_jar_impl, + attrs = { + "_sdk": attr.label(default = "@androidsdk//:sdk"), + }, +) diff --git a/tools/android/xslt/BUILD b/tools/android/xslt/BUILD new file mode 100644 index 0000000..b9a60b0 --- /dev/null +++ b/tools/android/xslt/BUILD @@ -0,0 +1,7 @@ +exports_files(["add_g3itr.xslt"]) + +sh_binary( + name = "xslt", + srcs = ["xslt.sh"], + visibility = ["//visibility:public"], +) diff --git a/tools/android/xslt/add_g3itr.xslt b/tools/android/xslt/add_g3itr.xslt new file mode 100644 index 0000000..9ce9a1e --- /dev/null +++ b/tools/android/xslt/add_g3itr.xslt @@ -0,0 +1,7 @@ +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:template match="@*|node()"> + <xsl:copy> + <xsl:apply-templates select="@*|node()"/> + </xsl:copy> + </xsl:template> +</xsl:stylesheet>
\ No newline at end of file diff --git a/tools/android/xslt/xslt.sh b/tools/android/xslt/xslt.sh new file mode 100755 index 0000000..fef6235 --- /dev/null +++ b/tools/android/xslt/xslt.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# noop +cp $6 $4 diff --git a/tools/jdk/BUILD b/tools/jdk/BUILD new file mode 100644 index 0000000..c688d1a --- /dev/null +++ b/tools/jdk/BUILD @@ -0,0 +1,11 @@ +load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain") + +default_java_toolchain( + name = "toolchain_android_only", + bootclasspath = [ + "//tools/android:android_jar", + # TODO(b/175805830): Add this only when desugaring is enabled. + "@bazel_tools//tools/android:desugar_java8_extra_bootclasspath", + ], + visibility = ["//visibility:public"], +) |