| # 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 AAPT Commands.""" |
| |
| load( |
| "//rules:utils.bzl", |
| "ANDROID_TOOLCHAIN_TYPE", |
| ) |
| |
| def _link( |
| ctx, |
| out_r_java, |
| out_resource_apk, |
| manifest = None, |
| java_package = None, |
| assets = depset([]), |
| assets_dirs = [], |
| compiled_resources = depset([]), |
| config_filters = [], |
| make_r_java_ids_non_final = False, |
| compatible_with_resource_shrinking = True, |
| enable_debug = False, |
| enable_static_lib = False, |
| android_jar = None, |
| aapt = None): |
| """Links compiled Android Resources with AAPT. |
| |
| Args: |
| ctx: The context. |
| out_r_java: A File. The R.java outputted by linking resources. |
| out_resource_apk: A File. The Resource APK outputted by linking resources. |
| manifest: A File. The AndroidManifest.xml. |
| java_package: A string. The Java package for the generated R.java. |
| assets: A list of Files. The list of assets from the transitive closure of |
| the project. |
| assets_dirs: A list of strings. The list of asset directories in the |
| transitive closure of the project. |
| compiled_resources: List of intermediate compiled android resource files. |
| config_filters: A list of Strings. The configuration filters. |
| make_r_java_ids_non_final: A bool. Makes the R.java produced from linkin |
| have non-final values. |
| compatible_with_resource_shrinking: A bool. When enabled produces the |
| output in proto format which is a requirement for resource shrinking. |
| enable_debug: A bool. Enable debugging |
| enable_static_lib: A bool. Enable static lib. |
| android_jar: A File. The Android Jar. |
| aapt: A FilesToRunProvider. The AAPT executable. |
| """ |
| |
| # Output the list of resources in reverse topological order. |
| resources_param = ctx.actions.declare_file( |
| out_r_java.basename + ".params", |
| sibling = out_r_java, |
| ) |
| args = ctx.actions.args() |
| args.use_param_file("%s", use_always = True) |
| args.set_param_file_format("multiline") |
| args.add_all(compiled_resources, expand_directories = True) |
| ctx.actions.run_shell( |
| command = """ |
| # Reverses the set of inputs that have been topologically ordered to utilize the |
| # overlay/override semantics of aapt2. |
| set -e |
| |
| echo $(tac $1) > $2 |
| """, |
| arguments = [args, resources_param.path], |
| outputs = [resources_param], |
| inputs = compiled_resources, |
| ) |
| |
| args = ctx.actions.args() |
| args.add("link") |
| if enable_static_lib: |
| args.add("--static-lib") |
| args.add("--no-version-vectors") |
| args.add("--no-static-lib-packages") # Turn off namespaced resource |
| |
| args.add("--manifest", manifest) |
| args.add("--auto-add-overlay") # Enables resource redefinition and merging |
| args.add("--override-styles-instead-of-overlaying") # mimic AAPT1. |
| if make_r_java_ids_non_final: |
| args.add("--non-final-ids") |
| if compatible_with_resource_shrinking: |
| args.add("--proto-format") |
| if enable_debug: |
| args.add("--debug-mode") |
| args.add("--custom-package", java_package) |
| args.add("-I", android_jar) |
| args.add_all(assets_dirs, before_each = "-A") |
| args.add("-R", resources_param, format = "@%s") |
| args.add("-0", ".apk") |
| args.add_joined("-c", config_filters, join_with = ",", omit_if_empty = True) |
| args.add("--java", out_r_java.path.rpartition(java_package.replace(".", "/"))[0]) |
| args.add("-o", out_resource_apk) |
| |
| ctx.actions.run( |
| executable = aapt, |
| arguments = [args], |
| inputs = depset( |
| [android_jar, resources_param] + |
| ([manifest] if manifest else []), |
| transitive = [assets, compiled_resources], |
| ), |
| outputs = [out_resource_apk, out_r_java], |
| mnemonic = "LinkAndroidResources", |
| progress_message = "ResV3 Linking Android Resources to %s" % out_resource_apk.short_path, |
| toolchain = ANDROID_TOOLCHAIN_TYPE, |
| ) |
| |
| def _compile( |
| ctx, |
| out_dir, |
| resource_files, |
| aapt): |
| """Compile and store resources in a single archive. |
| |
| Args: |
| ctx: The context. |
| out_dir: File. A file to store the output. |
| resource_files: A list of Files. The list of resource files or directories |
| to process. |
| aapt: AAPT. Tool for compiling resources. |
| """ |
| if not out_dir: |
| fail("No output directory specified.") |
| if not out_dir.is_directory: |
| fail("Output directory is not a directory artifact.") |
| if not resource_files: |
| fail("No resource files given.") |
| |
| # Retrieves the list of files at runtime when a directory is passed. |
| args = ctx.actions.args() |
| args.add_all(resource_files, expand_directories = True) |
| |
| ctx.actions.run_shell( |
| command = """ |
| set -e |
| |
| AAPT=%s |
| OUT_DIR=%s |
| RESOURCE_FILES=$@ |
| |
| i=0 |
| declare -A out_dir_map |
| for f in ${RESOURCE_FILES}; do |
| res_dir="$(dirname $(dirname ${f}))" |
| if [ -z "${out_dir_map[${res_dir}]}" ]; then |
| out_dir="${OUT_DIR}/$((++i))" |
| mkdir -p ${out_dir} |
| out_dir_map[${res_dir}]="${out_dir}" |
| fi |
| # Outputs from multiple directories can overwrite the outputs. As we do not |
| # control the outputs for now store each in its own sub directory which will be |
| # captured by the over_dir. |
| # TODO(b/139757260): Re-evaluate this one compile per file or multiple and zip |
| # merge. |
| "${AAPT}" compile --legacy "${f}" -o "${out_dir_map[${res_dir}]}" |
| done |
| """ % (aapt.executable.path, out_dir.path), |
| tools = [aapt], |
| arguments = [args], |
| inputs = resource_files, |
| outputs = [out_dir], |
| mnemonic = "CompileAndroidResources", |
| progress_message = "ResV3 Compiling Android Resources in %s" % out_dir, |
| toolchain = ANDROID_TOOLCHAIN_TYPE, |
| ) |
| |
| def _convert( |
| ctx, |
| out = None, |
| input = None, |
| to_proto = False, |
| aapt = None): |
| args = ctx.actions.args() |
| args.add("convert") |
| args.add("--output-format", ("proto" if to_proto else "binary")) |
| args.add("-o", out) |
| args.add(input) |
| |
| ctx.actions.run( |
| executable = aapt, |
| arguments = [args], |
| inputs = [input], |
| outputs = [out], |
| mnemonic = "AaptConvert", |
| progress_message = "ResV3 Convert to %s" % out.short_path, |
| toolchain = ANDROID_TOOLCHAIN_TYPE, |
| ) |
| |
| aapt = struct( |
| link = _link, |
| compile = _compile, |
| convert = _convert, |
| ) |