blob: c17782e2c7811aec4781d0546a21c4f55f84e449 [file] [log] [blame]
"""
Copyright (C) 2022 The Android Open Source Project
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.
"""
load("//build/bazel/rules:apex.bzl", "ApexInfo")
def _arch_transition_impl(settings, attr):
"""Implementation of arch_transition.
Four archs are included for mainline modules: x86, x86_64, arm and arm64.
"""
return {
"x86": {
"//command_line_option:platforms": "//build/bazel/platforms:android_x86",
},
"x86_64": {
"//command_line_option:platforms": "//build/bazel/platforms:android_x86_64",
},
"arm": {
"//command_line_option:platforms": "//build/bazel/platforms:android_arm",
},
"arm64": {
"//command_line_option:platforms": "//build/bazel/platforms:android_arm64",
},
}
# Multi-arch transition.
arch_transition = transition(
implementation = _arch_transition_impl,
inputs = [],
outputs = [
"//command_line_option:platforms",
],
)
# Arch to ABI map
_arch_abi_map = {
"arm64": "arm64-v8a",
"arm": "armeabi-v7a",
"x86_64": "x86_64",
"x86": "x86",
}
def _apex_proto_convert(ctx, arch, module_name, apex_file):
"""Run 'aapt2 convert' to convert resource files to protobuf format."""
# Inputs
inputs = [
apex_file,
ctx.executable._aapt2,
]
# Outputs
filename = apex_file.basename
pos_dot = filename.rindex(".")
proto_convert_file = ctx.actions.declare_file("/".join([
module_name,
arch,
filename[:pos_dot] + ".pb" + filename[pos_dot:]]))
outputs = [proto_convert_file]
# Arguments
args = ctx.actions.args()
args.add_all(["convert"])
args.add_all(["--output-format", "proto"])
args.add_all([apex_file])
args.add_all(["-o", proto_convert_file.path])
ctx.actions.run(
inputs = inputs,
outputs = outputs,
executable = ctx.executable._aapt2,
arguments = [args],
mnemonic = "ApexProtoConvert",
)
return proto_convert_file
def _apex_base_file(ctx, arch, module_name, apex_proto_file):
"""Run zip2zip to transform the apex file the expected directory structure
with all files that will be included in the base module of aab file."""
# Inputs
inputs = [
apex_proto_file,
ctx.executable._zip2zip,
]
# Outputs
base_file = ctx.actions.declare_file("/".join([module_name, arch, module_name + ".base"]))
outputs = [base_file]
# Arguments
args = ctx.actions.args()
args.add_all(["-i", apex_proto_file])
args.add_all(["-o", base_file])
abi = _arch_abi_map[arch]
args.add_all([
"apex_payload.img:apex/%s.img" % abi,
"apex_build_info.pb:apex/%s.build_info.pb" % abi,
"apex_manifest.json:root/apex_manifest.json",
"apex_manifest.pb:root/apex_manifest.pb",
"AndroidManifest.xml:manifest/AndroidManifest.xml",
"assets/NOTICE.html.gz:assets/NOTICE.html.gz",
])
ctx.actions.run(
inputs = inputs,
outputs = outputs,
executable = ctx.executable._zip2zip,
arguments = [args],
mnemonic = "ApexBaseFile",
)
return base_file
def _build_bundle_config(ctx, arch, module_name):
"""Create bundle_config.json as configuration for running bundletool."""
file_content = {
"compression": {
"uncompressed_glob": [
"apex_payload.img",
"apex_manifest.*",
],
},
"apex_config": {},
}
bundle_config_file = ctx.actions.declare_file("/".join([module_name, "bundle_config.json"]))
ctx.actions.write(bundle_config_file, json.encode(file_content))
return bundle_config_file
def _merge_base_files(ctx, module_name, base_files):
"""Run merge_zips to merge all files created for each arch by _apex_base_file."""
# Inputs
inputs = base_files + [ctx.executable._merge_zips]
# Outputs
merged_base_file = ctx.actions.declare_file(module_name + "/" + module_name + ".zip")
outputs = [merged_base_file]
# Arguments
args = ctx.actions.args()
args.add_all(["--ignore-duplicates"])
args.add_all([merged_base_file])
args.add_all(base_files)
ctx.actions.run(
inputs = inputs,
outputs = outputs,
executable = ctx.executable._merge_zips,
arguments = [args],
mnemonic = "ApexMergeBaseFiles",
)
return merged_base_file
def _apex_bundle(ctx, module_name, merged_base_file, bundle_config_file):
"""Run bundletool to create the aab file."""
# Inputs
inputs = [
bundle_config_file,
merged_base_file,
ctx.executable._bundletool,
]
# Outputs
bundle_file = ctx.actions.declare_file(module_name + "/" + module_name + ".aab")
outputs = [bundle_file]
# Arguments
args = ctx.actions.args()
args.add_all(["build-bundle"])
args.add_all(["--config", bundle_config_file])
args.add_all(["--modules", merged_base_file])
args.add_all(["--output", bundle_file])
ctx.actions.run(
inputs = inputs,
outputs = outputs,
executable = ctx.executable._bundletool,
arguments = [args],
mnemonic = "ApexBundleFile",
)
return bundle_file
def _apex_aab_impl(ctx):
"""Implementation of apex_aab rule, which drives the process of creating aab
file from apex files created for each arch."""
apex_base_files = []
bundle_config_file = None
module_name = ctx.attr.mainline_module[0].label.name
for arch in ctx.split_attr.mainline_module:
apex_file = ctx.split_attr.mainline_module[arch].files.to_list()[0]
proto_convert_file = _apex_proto_convert(ctx, arch, module_name, apex_file)
base_file = _apex_base_file(ctx, arch, module_name, proto_convert_file)
apex_base_files.append(base_file)
# It is assumed that the bundle config is the same for all products.
if bundle_config_file == None:
bundle_config_file = _build_bundle_config(ctx, arch, module_name)
merged_base_file = _merge_base_files(ctx, module_name, apex_base_files)
bundle_file = _apex_bundle(ctx, module_name, merged_base_file, bundle_config_file)
return [DefaultInfo(files = depset([bundle_file]))]
# apex_aab rule creates Android Apk Bundle (.aab) file of the APEX specified in mainline_module.
# There is no equivalent Soong module, and it is currently done in shell script by
# invoking Soong multiple times.
apex_aab = rule(
implementation = _apex_aab_impl,
attrs = {
"mainline_module": attr.label(
mandatory = True,
cfg = arch_transition,
providers = [ApexInfo],
doc = "The label of a mainline module target",
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
doc = "Allow transition.",
),
"_zipper": attr.label(
cfg = "host",
executable = True,
default = "@bazel_tools//tools/zip:zipper",
),
"_aapt2": attr.label(
allow_single_file = True,
cfg = "host",
executable = True,
default = "//prebuilts/sdk/tools:linux/bin/aapt2",
),
"_merge_zips": attr.label(
allow_single_file = True,
cfg = "host",
executable = True,
default = "//prebuilts/build-tools:linux-x86/bin/merge_zips",
),
"_zip2zip": attr.label(
allow_single_file = True,
cfg = "host",
executable = True,
default = "//prebuilts/build-tools:linux-x86/bin/zip2zip",
),
"_bundletool": attr.label(
cfg = "host",
executable = True,
default = "//prebuilts/bundletool",
),
},
)