blob: 161882ae518a7f0570ca414f11fa712e7a897247 [file] [log] [blame]
# 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 Bundletool Commands."""
load(":java.bzl", _java = "java")
_density_mapping = {
"ldpi": 120,
"mdpi": 160,
"hdpi": 240,
"xhdpi": 320,
"xxhdpi": 480,
"xxxhdpi": 640,
"tvdpi": 213,
}
def _proto_apk_to_module(
ctx,
out = None,
proto_apk = None,
zip = None,
unzip = None):
# TODO(timpeut): rewrite this as a standalone golang tool
ctx.actions.run_shell(
command = """
set -e
IN_DIR=$(mktemp -d)
OUT_DIR=$(mktemp -d)
CUR_PWD=$(pwd)
UNZIP=%s
ZIP=%s
INPUT=%s
OUTPUT=%s
"${UNZIP}" -qq "${INPUT}" -d "${IN_DIR}"
cd "${IN_DIR}"
if [ -f resources.pb ]; then
mv resources.pb "${OUT_DIR}/"
fi
if [ -f AndroidManifest.xml ]; then
mkdir "${OUT_DIR}/manifest"
mv AndroidManifest.xml "${OUT_DIR}/manifest/"
fi
NUM_DEX=`ls -1 *.dex 2>/dev/null | wc -l`
if [ $NUM_DEX != 0 ]; then
mkdir "${OUT_DIR}/dex"
mv *.dex "${OUT_DIR}/dex/"
fi
if [ -d res ]; then
mv res "${OUT_DIR}/res"
fi
if [ -d assets ]; then
mv assets "${OUT_DIR}/"
fi
if [ -d lib ]; then
mv lib "${OUT_DIR}/"
fi
UNKNOWN=`ls -1 * 2>/dev/null | wc -l`
if [ $UNKNOWN != 0 ]; then
mkdir "${OUT_DIR}/root"
mv * "${OUT_DIR}/root/"
fi
cd "${OUT_DIR}"
"${CUR_PWD}/${ZIP}" "${CUR_PWD}/${OUTPUT}" -Drq0 .
""" % (
unzip.executable.path,
zip.executable.path,
proto_apk.path,
out.path,
),
tools = [zip, unzip],
arguments = [],
inputs = [proto_apk],
outputs = [out],
mnemonic = "Rebundle",
progress_message = "Rebundle to %s" % out.short_path,
)
def _build(
ctx,
out = None,
modules = [],
config = None,
metadata = dict(),
bundletool = None,
host_javabase = None):
args = ctx.actions.args()
args.add("build-bundle")
args.add("--output", out)
if modules:
args.add_joined("--modules", modules, join_with = ",")
if config:
args.add("--config", config)
for path, f in metadata.items():
args.add("--metadata-file", "%s:%s" % (path, f.path))
_java.run(
ctx = ctx,
host_javabase = host_javabase,
executable = bundletool,
arguments = [args],
inputs = (
modules +
([config] if config else []) +
metadata.values()
),
outputs = [out],
mnemonic = "BuildBundle",
progress_message = "Building bundle %s" % out.short_path,
)
def _extract_config(
ctx,
out = None,
aab = None,
bundletool = None,
host_javabase = None):
# Need to execute as a shell script as the tool outputs to stdout
cmd = """
set -e
contents=`%s -jar %s dump config --bundle %s`
echo "$contents" > %s
""" % (
host_javabase[java_common.JavaRuntimeInfo].java_executable_exec_path,
bundletool.executable.path,
aab.path,
out.path,
)
ctx.actions.run_shell(
inputs = [aab],
outputs = [out],
tools = depset([bundletool.executable], transitive = [host_javabase[java_common.JavaRuntimeInfo].files]),
mnemonic = "ExtractBundleConfig",
progress_message = "Extract bundle config to %s" % out.short_path,
command = cmd,
)
def _extract_manifest(
ctx,
out = None,
aab = None,
module = None,
xpath = None,
bundletool = None,
host_javabase = None):
# Need to execute as a shell script as the tool outputs to stdout
extra_flags = []
if module:
extra_flags.append("--module " + module)
if xpath:
extra_flags.append("--xpath " + xpath)
cmd = """
set -e
contents=`%s -jar %s dump manifest --bundle %s %s`
echo "$contents" > %s
""" % (
host_javabase[java_common.JavaRuntimeInfo].java_executable_exec_path,
bundletool.executable.path,
aab.path,
" ".join(extra_flags),
out.path,
)
ctx.actions.run_shell(
inputs = [aab],
outputs = [out],
tools = depset([bundletool.executable], transitive = [host_javabase[java_common.JavaRuntimeInfo].files]),
mnemonic = "ExtractBundleManifest",
progress_message = "Extract bundle manifest to %s" % out.short_path,
command = cmd,
)
def _bundle_to_apks(
ctx,
out = None,
bundle = None,
universal = False,
device_spec = None,
keystore = None,
modules = None,
aapt2 = None,
bundletool = None,
host_javabase = None):
inputs = [bundle]
args = ctx.actions.args()
args.add("build-apks")
args.add("--output", out)
args.add("--bundle", bundle)
args.add("--aapt2", aapt2.executable.path)
if universal:
args.add("--mode=universal")
if keystore:
args.add("--ks", keystore.path)
args.add("--ks-pass", "pass:android")
args.add("--ks-key-alias", "AndroidDebugKey")
inputs.append(keystore)
if device_spec:
args.add("--device-spec", device_spec)
inputs.append(device_spec)
if modules:
args.add_joined("--modules", modules, join_with = ",")
_java.run(
ctx = ctx,
host_javabase = host_javabase,
executable = bundletool,
arguments = [args],
inputs = inputs,
outputs = [out],
tools = [aapt2],
mnemonic = "BundleToApks",
progress_message = "Converting bundle to .apks: %s" % out.short_path,
)
def _build_device_json(
ctx,
out,
abis,
locales,
density,
sdk_version):
json_content = json.encode(struct(
supportedAbis = abis,
supportedLocales = locales,
screenDensity = _density_mapping[density],
sdkVersion = int(sdk_version),
))
ctx.actions.write(out, json_content)
bundletool = struct(
build = _build,
build_device_json = _build_device_json,
bundle_to_apks = _bundle_to_apks,
extract_config = _extract_config,
extract_manifest = _extract_manifest,
proto_apk_to_module = _proto_apk_to_module,
)