435 lines
16 KiB
Python
435 lines
16 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("@bazel_skylib//lib:paths.bzl", "paths")
|
||
|
|
load("//build/bazel/rules:toolchain_utils.bzl", "verify_toolchain_exists")
|
||
|
|
load(":apex_info.bzl", "ApexInfo")
|
||
|
|
load(":bundle.bzl", "build_bundle_config")
|
||
|
|
|
||
|
|
def _arch_transition_impl(settings, _attr):
|
||
|
|
"""Implementation of arch_transition.
|
||
|
|
|
||
|
|
Six arch products are included for mainline modules: x86, x86_64, x86_64only, arm, arm64, arm64only.
|
||
|
|
"""
|
||
|
|
old_platform = str(settings["//command_line_option:platforms"][0])
|
||
|
|
|
||
|
|
# We can't use platforms alone to differentiate between x86_64 and x86_64
|
||
|
|
# with a secondary arch, which is significant for apex packaging that can
|
||
|
|
# optionally include the secondary arch's libs. That is currently determined
|
||
|
|
# by DeviceSecondaryArch in apex's lib inclusion logic, so we explicitly set
|
||
|
|
# DeviceSecondaryArch to "" for the 64bit only cases.
|
||
|
|
|
||
|
|
# TODO(b/249685973) Instead of using these __internal_x86 platforms, use
|
||
|
|
# the mainline_modules_<arch> android products
|
||
|
|
return {
|
||
|
|
# these key names must correspond to mainline_modules_<arch> product name suffixes.
|
||
|
|
"arm": {
|
||
|
|
"//command_line_option:platforms": old_platform + "__internal_arm",
|
||
|
|
},
|
||
|
|
"arm64": {
|
||
|
|
"//command_line_option:platforms": old_platform + "__internal_arm64",
|
||
|
|
},
|
||
|
|
"arm64only": {
|
||
|
|
"//command_line_option:platforms": old_platform + "__internal_arm64only",
|
||
|
|
},
|
||
|
|
"x86": {
|
||
|
|
"//command_line_option:platforms": old_platform + "__internal_x86",
|
||
|
|
},
|
||
|
|
"x86_64": {
|
||
|
|
"//command_line_option:platforms": old_platform + "__internal_x86_64",
|
||
|
|
},
|
||
|
|
"x86_64only": {
|
||
|
|
"//command_line_option:platforms": old_platform + "__internal_x86_64only",
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
# Multi-arch transition.
|
||
|
|
arch_transition = transition(
|
||
|
|
implementation = _arch_transition_impl,
|
||
|
|
inputs = [
|
||
|
|
"//command_line_option:platforms",
|
||
|
|
],
|
||
|
|
outputs = [
|
||
|
|
"//command_line_option:platforms",
|
||
|
|
],
|
||
|
|
)
|
||
|
|
|
||
|
|
def _merge_base_files(ctx, module_name, base_files):
|
||
|
|
"""Run merge_zips to merge all files created for each arch by _apex_base_file."""
|
||
|
|
merged_base_file = ctx.actions.declare_file(module_name + "/" + module_name + ".zip")
|
||
|
|
|
||
|
|
# Arguments
|
||
|
|
args = ctx.actions.args()
|
||
|
|
args.add("--ignore-duplicates")
|
||
|
|
args.add(merged_base_file)
|
||
|
|
args.add_all(base_files)
|
||
|
|
|
||
|
|
ctx.actions.run(
|
||
|
|
inputs = base_files,
|
||
|
|
outputs = [merged_base_file],
|
||
|
|
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."""
|
||
|
|
|
||
|
|
# Outputs
|
||
|
|
bundle_file = ctx.actions.declare_file(module_name + "/" + module_name + ".aab")
|
||
|
|
|
||
|
|
# Arguments
|
||
|
|
args = ctx.actions.args()
|
||
|
|
args.add("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 = [
|
||
|
|
bundle_config_file,
|
||
|
|
merged_base_file,
|
||
|
|
],
|
||
|
|
outputs = [bundle_file],
|
||
|
|
executable = ctx.executable._bundletool,
|
||
|
|
arguments = [args],
|
||
|
|
mnemonic = "ApexBundleFile",
|
||
|
|
)
|
||
|
|
return bundle_file
|
||
|
|
|
||
|
|
def _sign_bundle(ctx, aapt2, avbtool, module_name, bundle_file, apex_info):
|
||
|
|
""" Run dev_sign_bundle to sign the bundle_file."""
|
||
|
|
|
||
|
|
# Python3 interpreter for dev_sign_bundle to run other python scripts.
|
||
|
|
python_interpreter = ctx.toolchains["@bazel_tools//tools/python:toolchain_type"].py3_runtime.interpreter
|
||
|
|
if python_interpreter.basename != "python3":
|
||
|
|
python3 = ctx.actions.declare_file("python3")
|
||
|
|
ctx.actions.symlink(
|
||
|
|
output = python3,
|
||
|
|
target_file = python_interpreter,
|
||
|
|
is_executable = True,
|
||
|
|
)
|
||
|
|
python_interpreter = python3
|
||
|
|
|
||
|
|
# Input directory for dev_sign_bundle.
|
||
|
|
input_bundle_file = ctx.actions.declare_file(module_name + "/sign_bundle/input_dir/" + bundle_file.basename)
|
||
|
|
ctx.actions.symlink(
|
||
|
|
output = input_bundle_file,
|
||
|
|
target_file = bundle_file,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Output directory for dev_sign_bundle
|
||
|
|
output_dir = ctx.actions.declare_directory(module_name + "/sign_bundle/output_dir")
|
||
|
|
|
||
|
|
# Temporary directory for dev_sign_bundle
|
||
|
|
tmp_dir = ctx.actions.declare_directory(module_name + "/sign_bundle/tmp_dir")
|
||
|
|
|
||
|
|
# Jar file of prebuilts/bundletool
|
||
|
|
bundletool_jarfile = ctx.attr._bundletool_lib.files.to_list()[0]
|
||
|
|
|
||
|
|
# Keystore file
|
||
|
|
keystore_file = ctx.attr.dev_keystore.files.to_list()[0]
|
||
|
|
|
||
|
|
# ANDROID_HOST_OUT environment
|
||
|
|
debugfs_static = ctx.actions.declare_file(module_name + "/sign_bundle/android_host_out/bin/debugfs_static")
|
||
|
|
ctx.actions.symlink(
|
||
|
|
output = debugfs_static,
|
||
|
|
target_file = ctx.executable._debugfs,
|
||
|
|
is_executable = True,
|
||
|
|
)
|
||
|
|
fsck_erofs = ctx.actions.declare_file(module_name + "/sign_bundle/android_host_out/bin/fsck.erofs")
|
||
|
|
ctx.actions.symlink(
|
||
|
|
output = fsck_erofs,
|
||
|
|
target_file = ctx.executable._fsck_erofs,
|
||
|
|
is_executable = True,
|
||
|
|
)
|
||
|
|
signapk_jar = ctx.actions.declare_file(module_name + "/sign_bundle/android_host_out/framework/signapk.jar")
|
||
|
|
ctx.actions.symlink(
|
||
|
|
output = signapk_jar,
|
||
|
|
target_file = ctx.attr._signapk_jar.files.to_list()[0],
|
||
|
|
is_executable = False,
|
||
|
|
)
|
||
|
|
libconscrypt_openjdk_jni_so = ctx.actions.declare_file(module_name + "/sign_bundle/android_host_out/lib64/libconscrypt_openjdk_jni.so")
|
||
|
|
ctx.actions.symlink(
|
||
|
|
output = libconscrypt_openjdk_jni_so,
|
||
|
|
target_file = ctx.attr._libconscrypt_openjdk_jni.files.to_list()[1],
|
||
|
|
is_executable = False,
|
||
|
|
)
|
||
|
|
|
||
|
|
java_runtime = ctx.attr._java_runtime[java_common.JavaRuntimeInfo]
|
||
|
|
|
||
|
|
# Tools
|
||
|
|
tools = [
|
||
|
|
ctx.executable.dev_sign_bundle,
|
||
|
|
ctx.executable._deapexer,
|
||
|
|
ctx.executable._sign_apex,
|
||
|
|
ctx.executable._openssl,
|
||
|
|
ctx.executable._zip2zip,
|
||
|
|
ctx.executable._blkid,
|
||
|
|
aapt2,
|
||
|
|
avbtool.files_to_run.executable,
|
||
|
|
python_interpreter,
|
||
|
|
debugfs_static,
|
||
|
|
fsck_erofs,
|
||
|
|
bundletool_jarfile,
|
||
|
|
signapk_jar,
|
||
|
|
libconscrypt_openjdk_jni_so,
|
||
|
|
java_runtime.files,
|
||
|
|
]
|
||
|
|
|
||
|
|
# Inputs
|
||
|
|
inputs = [
|
||
|
|
input_bundle_file,
|
||
|
|
keystore_file,
|
||
|
|
apex_info.bundle_key_info.private_key,
|
||
|
|
apex_info.container_key_info.pem,
|
||
|
|
apex_info.container_key_info.pk8,
|
||
|
|
]
|
||
|
|
|
||
|
|
# Outputs
|
||
|
|
outputs = [output_dir, tmp_dir]
|
||
|
|
|
||
|
|
# Arguments
|
||
|
|
java_bin = paths.join(java_runtime.java_home, "bin")
|
||
|
|
args = ctx.actions.args()
|
||
|
|
args.add_all(["--input_dir", input_bundle_file.dirname])
|
||
|
|
args.add_all(["--output_dir", output_dir.path])
|
||
|
|
args.add_all(["--temp_dir", tmp_dir.path])
|
||
|
|
args.add_all(["--aapt2_path", aapt2.path])
|
||
|
|
args.add_all(["--bundletool_path", bundletool_jarfile.path])
|
||
|
|
args.add_all(["--deapexer_path", ctx.executable._deapexer.path])
|
||
|
|
args.add_all(["--blkid_path", ctx.executable._blkid.path])
|
||
|
|
args.add_all(["--debugfs_path", ctx.executable._debugfs.path])
|
||
|
|
args.add_all(["--java_binary_path", paths.join(java_bin, "java")])
|
||
|
|
args.add_all(["--apex_signer_path", ctx.executable._sign_apex])
|
||
|
|
|
||
|
|
ctx.actions.run(
|
||
|
|
inputs = inputs,
|
||
|
|
outputs = outputs,
|
||
|
|
executable = ctx.executable.dev_sign_bundle,
|
||
|
|
arguments = [args],
|
||
|
|
tools = tools,
|
||
|
|
env = {
|
||
|
|
# necessary for dev_sign_bundle.
|
||
|
|
"BAZEL_ANDROID_HOST_OUT": paths.dirname(debugfs_static.dirname),
|
||
|
|
"PATH": ":".join(
|
||
|
|
[
|
||
|
|
python_interpreter.dirname,
|
||
|
|
ctx.executable._deapexer.dirname,
|
||
|
|
avbtool.files_to_run.executable.dirname,
|
||
|
|
ctx.executable._openssl.dirname,
|
||
|
|
java_bin,
|
||
|
|
],
|
||
|
|
),
|
||
|
|
},
|
||
|
|
mnemonic = "ApexSignBundleFile",
|
||
|
|
)
|
||
|
|
|
||
|
|
apks_file = ctx.actions.declare_file(module_name + "/" + module_name + ".apks")
|
||
|
|
cert_info_file = ctx.actions.declare_file(module_name + "/" + module_name + ".cert_info.txt")
|
||
|
|
ctx.actions.run_shell(
|
||
|
|
inputs = [output_dir],
|
||
|
|
outputs = [apks_file, cert_info_file],
|
||
|
|
command = " ".join(["cp", output_dir.path + "/" + module_name + "/*", apks_file.dirname]),
|
||
|
|
)
|
||
|
|
|
||
|
|
return [apks_file, cert_info_file]
|
||
|
|
|
||
|
|
def _apex_aab_impl(ctx):
|
||
|
|
"""Implementation of apex_aab rule.
|
||
|
|
|
||
|
|
This drives the process of creating aab file from apex files created for each arch."""
|
||
|
|
verify_toolchain_exists(ctx, "//build/bazel/rules/apex:apex_toolchain_type")
|
||
|
|
apex_toolchain = ctx.toolchains["//build/bazel/rules/apex:apex_toolchain_type"].toolchain_info
|
||
|
|
|
||
|
|
prefixed_apex_files = []
|
||
|
|
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_info = ctx.split_attr.mainline_module[arch][ApexInfo]
|
||
|
|
apex_base_files.append(apex_info.base_file)
|
||
|
|
|
||
|
|
arch_subdir = "mainline_modules_%s" % arch
|
||
|
|
|
||
|
|
# A mapping of files to a prefix directory they should be copied to.
|
||
|
|
# These files will be accessible with the apex_files output_group.
|
||
|
|
mapping = {
|
||
|
|
apex_info.base_file: arch_subdir,
|
||
|
|
apex_info.signed_output: arch_subdir,
|
||
|
|
apex_info.symbols_used_by_apex: arch_subdir + "/ndk_apis_usedby_apex",
|
||
|
|
apex_info.backing_libs: arch_subdir + "/ndk_apis_backedby_apex",
|
||
|
|
apex_info.java_symbols_used_by_apex: arch_subdir + "/java_apis_usedby_apex",
|
||
|
|
# TODO(b/262267680): create licensetexts
|
||
|
|
# TODO(b/262267551): create shareprojects
|
||
|
|
}
|
||
|
|
|
||
|
|
# Forward the individual files for all variants in an additional output group,
|
||
|
|
# so dependents can easily access the multi-arch base APEX files by building
|
||
|
|
# this target with --output_groups=apex_files.
|
||
|
|
#
|
||
|
|
# Copy them into an arch-specific directory, since they have the same basename.
|
||
|
|
for _file, _dir in mapping.items():
|
||
|
|
_out = ctx.actions.declare_file(_dir + "/" + _file.basename)
|
||
|
|
ctx.actions.run_shell(
|
||
|
|
inputs = [_file],
|
||
|
|
outputs = [_out],
|
||
|
|
command = " ".join(["cp", _file.path, _out.path]),
|
||
|
|
)
|
||
|
|
prefixed_apex_files.append(_out)
|
||
|
|
|
||
|
|
# Create .aab file
|
||
|
|
bundle_config_file = build_bundle_config(ctx.actions, ctx.label.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)
|
||
|
|
|
||
|
|
# Create .apks file
|
||
|
|
apex_info = ctx.attr.mainline_module[0][ApexInfo]
|
||
|
|
package_name = apex_info.package_name
|
||
|
|
|
||
|
|
if ctx.attr.dev_sign_bundle and ctx.attr.dev_keystore and (package_name.startswith("com.google.android") or package_name.startswith("com.google.mainline")):
|
||
|
|
signed_files = _sign_bundle(ctx, apex_toolchain.aapt2, apex_toolchain.avbtool, module_name, bundle_file, apex_info)
|
||
|
|
return [
|
||
|
|
DefaultInfo(files = depset([bundle_file] + signed_files)),
|
||
|
|
OutputGroupInfo(apex_files = depset(prefixed_apex_files), signed_files = signed_files),
|
||
|
|
]
|
||
|
|
|
||
|
|
return [
|
||
|
|
DefaultInfo(files = depset([bundle_file])),
|
||
|
|
OutputGroupInfo(apex_files = depset(prefixed_apex_files)),
|
||
|
|
]
|
||
|
|
|
||
|
|
# apex_aab rule creates multi-arch outputs of a Mainline module, such as the
|
||
|
|
# 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,
|
||
|
|
toolchains = [
|
||
|
|
# The apex toolchain is not mandatory so that we don't get toolchain resolution errors
|
||
|
|
# even when the aab is not compatible with the current target (via target_compatible_with).
|
||
|
|
config_common.toolchain_type("//build/bazel/rules/apex:apex_toolchain_type", mandatory = False),
|
||
|
|
"@bazel_tools//tools/python:toolchain_type",
|
||
|
|
],
|
||
|
|
attrs = {
|
||
|
|
"dev_keystore": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = False,
|
||
|
|
),
|
||
|
|
"dev_sign_bundle": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
),
|
||
|
|
"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.",
|
||
|
|
),
|
||
|
|
"_blkid": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
default = "//external/e2fsprogs/misc:blkid",
|
||
|
|
),
|
||
|
|
"_bundletool": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
default = "//prebuilts/bundletool",
|
||
|
|
),
|
||
|
|
"_bundletool_lib": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = False,
|
||
|
|
default = "//prebuilts/bundletool:bundletool-lib",
|
||
|
|
),
|
||
|
|
"_deapexer": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
default = "//system/apex/tools:deapexer",
|
||
|
|
),
|
||
|
|
"_debugfs": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
default = "//external/e2fsprogs/debugfs:debugfs_static",
|
||
|
|
),
|
||
|
|
"_fsck_erofs": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
default = "//external/erofs-utils:fsck.erofs",
|
||
|
|
),
|
||
|
|
"_java_runtime": attr.label(
|
||
|
|
default = Label("@bazel_tools//tools/jdk:current_java_runtime"),
|
||
|
|
cfg = "exec",
|
||
|
|
providers = [java_common.JavaRuntimeInfo],
|
||
|
|
),
|
||
|
|
"_libconscrypt_openjdk_jni": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = False,
|
||
|
|
default = "//external/conscrypt:libconscrypt_openjdk_jni",
|
||
|
|
),
|
||
|
|
"_merge_zips": attr.label(
|
||
|
|
allow_single_file = True,
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
default = "//prebuilts/build-tools:linux-x86/bin/merge_zips",
|
||
|
|
),
|
||
|
|
"_openssl": attr.label(
|
||
|
|
allow_single_file = True,
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
default = "//prebuilts/build-tools:linux-x86/bin/openssl",
|
||
|
|
),
|
||
|
|
"_sign_apex": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
default = "//build/make/tools/releasetools:sign_apex",
|
||
|
|
),
|
||
|
|
"_signapk_jar": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = False,
|
||
|
|
default = "//build/bazel/rules/apex:signapk_deploy_jar",
|
||
|
|
),
|
||
|
|
"_zip2zip": attr.label(
|
||
|
|
allow_single_file = True,
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
default = "//build/soong/cmd/zip2zip:zip2zip",
|
||
|
|
),
|
||
|
|
"_zipper": attr.label(
|
||
|
|
cfg = "exec",
|
||
|
|
executable = True,
|
||
|
|
default = "@bazel_tools//tools/zip:zipper",
|
||
|
|
),
|
||
|
|
},
|
||
|
|
)
|
||
|
|
|
||
|
|
def apex_aab(name, mainline_module, dev_sign_bundle = None, dev_keystore = None, target_compatible_with = [], **kwargs):
|
||
|
|
target_compatible_with = select({
|
||
|
|
"//build/bazel/platforms/os:android": [],
|
||
|
|
"//conditions:default": ["@platforms//:incompatible"],
|
||
|
|
}) + target_compatible_with
|
||
|
|
|
||
|
|
_apex_aab(
|
||
|
|
name = name,
|
||
|
|
mainline_module = mainline_module,
|
||
|
|
dev_sign_bundle = dev_sign_bundle,
|
||
|
|
dev_keystore = dev_keystore,
|
||
|
|
target_compatible_with = target_compatible_with,
|
||
|
|
**kwargs
|
||
|
|
)
|