blob: 284d89ad94130d6ccfb6731b00a9a69ae25e3026 [file] [log] [blame]
# 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."""
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,
)
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,
)
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,
)
aapt = struct(
link = _link,
compile = _compile,
convert = _convert,
)