261 lines
8.2 KiB
Python
261 lines
8.2 KiB
Python
"""
|
|
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",
|
|
),
|
|
},
|
|
)
|