aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-12 18:40:13 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-12 18:40:13 +0000
commit3f7da29da8522a1492541d6c457469d13ef0a893 (patch)
treeb24a5406e82c1f3856e093af2d4575f5a76aa981
parentadf5da8fddeabe8941cf6ee2c12bdb1b18840f73 (diff)
parentc8cd5bd2736a22d4ab214c84f480ca7c357d7db4 (diff)
downloadbazel-3f7da29da8522a1492541d6c457469d13ef0a893.tar.gz
Snap for 8580505 from c8cd5bd2736a22d4ab214c84f480ca7c357d7db4 to main-cg-testing-releasemain-cg-testing-release
Change-Id: I88af5b7f22c2df662a4db3e3ad3c56b47ec87d70
-rwxr-xr-xci/rbc_regression_test.sh7
-rw-r--r--rules/apex/BUILD7
-rw-r--r--rules/apex/apex.bzl213
-rw-r--r--rules/apex/bazel_apexer_wrapper.py256
-rwxr-xr-xrules/apex/bazel_apexer_wrapper_test.sh46
-rw-r--r--rules/cc/cc_library_static.bzl11
6 files changed, 241 insertions, 299 deletions
diff --git a/ci/rbc_regression_test.sh b/ci/rbc_regression_test.sh
index 367653bb..16a14fb1 100755
--- a/ci/rbc_regression_test.sh
+++ b/ci/rbc_regression_test.sh
@@ -13,7 +13,7 @@ function die() {
function usage() {
cat <<EOF >&2
-Usage: $myname [-p] [-b] [-q] [-r] <product-variant> [product-variant ...]
+Usage: $myname [-q] [-r] <product-variant> [product-variant ...]
-q: Quiet. Suppress all output other than a failure message
-r: Retain Ninja files
EOF
@@ -38,12 +38,9 @@ declare -r myname=${mypath#${mydir}/}
flags_rbc=(RBC_PRODUCT_CONFIG=true)
quiet=
-while getopts "bkpqr" o; do
+while getopts "qr" o; do
case "${o}" in
- k) ;; # backward compatibility to be removed later
q) quiet=true ;;
- b) ;; # backward compatibility to be removed later
- p) ;; # backward compatibility to be removed later
r) retain_files=t ;;
*) usage ;;
esac
diff --git a/rules/apex/BUILD b/rules/apex/BUILD
index e5051bcb..c3d6b9bf 100644
--- a/rules/apex/BUILD
+++ b/rules/apex/BUILD
@@ -7,6 +7,13 @@ string_setting(
visibility = ["//visibility:public"],
)
+config_setting(
+ name = "non_apex",
+ flag_values = {
+ ":apex_name": "",
+ },
+)
+
string_setting(
name = "min_sdk_version",
build_setting_default = "",
diff --git a/rules/apex/apex.bzl b/rules/apex/apex.bzl
index 6034c38f..387ac6b2 100644
--- a/rules/apex/apex.bzl
+++ b/rules/apex/apex.bzl
@@ -22,20 +22,39 @@ load("//build/bazel/rules/android:android_app_certificate.bzl", "AndroidAppCerti
load("//build/bazel/rules/apex:transition.bzl", "apex_transition", "shared_lib_transition_32", "shared_lib_transition_64")
load("//build/bazel/rules/apex:cc.bzl", "ApexCcInfo", "apex_cc_aspect")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
-
-DIR_LIB = "lib"
-DIR_LIB64 = "lib64"
+load("@bazel_skylib//lib:paths.bzl", "paths")
ApexInfo = provider(
"ApexInfo has no field currently and is used by apex rule dependents to ensure an attribute is a target of apex rule.",
fields = {},
)
-# Prepare the input files info for bazel_apexer_wrapper to generate APEX filesystem image.
-def _prepare_apexer_wrapper_inputs(ctx):
- # dictionary to return in the format:
- # apex_manifest[(image_file_dirname, image_file_basename)] = bazel_output_file
- apex_manifest = {}
+def _create_file_mapping(ctx):
+ """Create a file mapping for the APEX filesystem image.
+
+ This returns a Dict[File, str] where the dictionary keys
+ are the input files, and the values are the paths that these
+ files should have in the apex staging dir / filesystem image.
+ """
+
+ # Dictionary mapping from the path of each dependency to it's path in the apex
+ file_mapping = {}
+
+ def _add_libs_32_target(key):
+ if len(ctx.split_attr.native_shared_libs_32.keys()) > 0:
+ _add_lib_file("lib", ctx.split_attr.native_shared_libs_32[key])
+
+ def _add_libs_64_target(key_32, key_64):
+ _add_libs_32_target(key_32)
+ if len(ctx.split_attr.native_shared_libs_64.keys()) > 0:
+ _add_lib_file("lib64", ctx.split_attr.native_shared_libs_64[key_64])
+
+ def _add_lib_file(dir, libs):
+ for dep in libs:
+ apex_cc_info = dep[ApexCcInfo]
+ for lib_file in apex_cc_info.transitive_shared_libs.to_list():
+ file_mapping[lib_file] = paths.join(dir, lib_file.basename)
+
x86_constraint = ctx.attr._x86_constraint[platform_common.ConstraintValueInfo]
x86_64_constraint = ctx.attr._x86_64_constraint[platform_common.ConstraintValueInfo]
@@ -43,13 +62,13 @@ def _prepare_apexer_wrapper_inputs(ctx):
arm64_constraint = ctx.attr._arm64_constraint[platform_common.ConstraintValueInfo]
if ctx.target_platform_has_constraint(x86_constraint):
- _add_libs_32_target(ctx, "x86", apex_manifest)
+ _add_libs_32_target("x86")
elif ctx.target_platform_has_constraint(x86_64_constraint):
- _add_libs_64_target(ctx, "x86", "x86_64", apex_manifest)
+ _add_libs_64_target("x86", "x86_64")
elif ctx.target_platform_has_constraint(arm_constraint):
- _add_libs_32_target(ctx, "arm", apex_manifest)
+ _add_libs_32_target("arm")
elif ctx.target_platform_has_constraint(arm64_constraint):
- _add_libs_64_target(ctx, "arm", "arm64", apex_manifest)
+ _add_libs_64_target("arm", "arm64")
# Handle prebuilts
for dep in ctx.attr.prebuilts:
@@ -58,7 +77,7 @@ def _prepare_apexer_wrapper_inputs(ctx):
filename = prebuilt_file_info.filename
else:
filename = dep.label.name
- apex_manifest[(prebuilt_file_info.dir, filename)] = prebuilt_file_info.src
+ file_mapping[prebuilt_file_info.src] = paths.join(prebuilt_file_info.dir, filename)
# Handle binaries
for dep in ctx.attr.binaries:
@@ -69,54 +88,24 @@ def _prepare_apexer_wrapper_inputs(ctx):
if sh_binary_info != None:
directory = "bin"
if sh_binary_info.sub_dir != None and sh_binary_info.sub_dir != "":
- directory = "/".join([directory, sh_binary_info.sub_dir])
+ directory = paths.join("bin", sh_binary_info.sub_dir)
if sh_binary_info.filename != None and sh_binary_info.filename != "":
filename = sh_binary_info.filename
else:
filename = dep.label.name
- apex_manifest[(directory, filename)] = default_info.files_to_run.executable
+ file_mapping[default_info.files_to_run.executable] = paths.join(directory, filename)
elif CcInfo in dep:
# cc_binary just takes the final executable from the runfiles.
- apex_manifest[("bin", dep.label.name)] = dep[DefaultInfo].files_to_run.executable
-
- apex_content_inputs = []
-
- bazel_apexer_wrapper_manifest = ctx.actions.declare_file("%s_bazel_apexer_wrapper_manifest" % ctx.attr.name)
- file_lines = []
-
- # Store the apex file target directory, file name and the path in the source tree in a file.
- # This file will be read by the bazel_apexer_wrapper to create the apex input directory.
- # Here is an example:
- # {etc/tz,tz_version,system/timezone/output_data/version/tz_version}
- for (apex_dirname, apex_basename), bazel_input_file in apex_manifest.items():
- apex_content_inputs.append(bazel_input_file)
- file_lines += [",".join([apex_dirname, apex_basename, bazel_input_file.path])]
-
- ctx.actions.write(bazel_apexer_wrapper_manifest, "\n".join(file_lines))
-
- return apex_content_inputs, bazel_apexer_wrapper_manifest
-
-def _add_libs_32_target(ctx, key, apex_manifest):
- if len(ctx.split_attr.native_shared_libs_32.keys()) > 0:
- _add_lib_file(DIR_LIB, ctx.split_attr.native_shared_libs_32[key], apex_manifest)
+ file_mapping[dep[DefaultInfo].files_to_run.executable] = paths.join("bin", dep.label.name)
-def _add_libs_64_target(ctx, key_32, key_64, apex_manifest):
- _add_libs_32_target(ctx, key_32, apex_manifest)
- if len(ctx.split_attr.native_shared_libs_64.keys()) > 0:
- _add_lib_file(DIR_LIB64, ctx.split_attr.native_shared_libs_64[key_64], apex_manifest)
-
-def _add_lib_file(dir, libs, apex_manifest):
- for dep in libs:
- apex_cc_info = dep[ApexCcInfo]
- for lib_file in apex_cc_info.transitive_shared_libs.to_list():
- apex_manifest[(dir, lib_file.basename)] = lib_file
+ return file_mapping
# conv_apex_manifest - Convert the JSON APEX manifest to protobuf, which is needed by apexer.
def _convert_apex_manifest_json_to_pb(ctx, apex_toolchain):
apex_manifest_json = ctx.file.manifest
- apex_manifest_pb = ctx.actions.declare_file("apex_manifest.pb")
+ apex_manifest_pb = ctx.actions.declare_file(ctx.attr.name + "_apex_manifest.pb")
ctx.actions.run(
outputs = [apex_manifest_pb],
@@ -133,8 +122,43 @@ def _convert_apex_manifest_json_to_pb(ctx, apex_toolchain):
return apex_manifest_pb
+def _generate_canned_fs_config(ctx, filepaths):
+ """Generate filesystem config.
+
+ This encodes the filemode, uid, and gid of each file in the APEX,
+ including apex_manifest.json and apex_manifest.pb.
+ NOTE: every file must have an entry.
+ """
+
+ # Ensure all paths don't start with / and are normalized
+ filepaths = [paths.normalize(f).lstrip("/") for f in filepaths]
+ filepaths = [f for f in filepaths if f]
+
+ # First, collect a set of all the directories in the apex
+ apex_subdirs_set = {}
+ for f in filepaths:
+ d = paths.dirname(f)
+ if d != "": # The root dir is handled manually below
+ # Make sure all the parent dirs of the current subdir are in the set, too
+ dirs = d.split("/")
+ for i in range(1, len(dirs)+1):
+ apex_subdirs_set["/".join(dirs[:i])] = True
+
+ config_lines = []
+ config_lines += ["/ 0 2000 0755"]
+ config_lines += ["/apex_manifest.json 1000 1000 0644"]
+ config_lines += ["/apex_manifest.pb 1000 1000 0644"]
+ config_lines += ["/" + filepath + " 1000 1000 0644" for filepath in filepaths]
+ config_lines += ["/" + d + " 0 2000 0755" for d in apex_subdirs_set.keys()]
+ config_lines = sorted(config_lines)
+
+ file = ctx.actions.declare_file(ctx.attr.name + '_canned_fs_config.txt')
+ ctx.actions.write(file, '\n'.join(config_lines))
+
+ return file
+
# apexer - generate the APEX file.
-def _run_apexer(ctx, apex_toolchain, apex_content_inputs, bazel_apexer_wrapper_manifest, apex_manifest_pb):
+def _run_apexer(ctx, apex_toolchain):
# Inputs
file_contexts = ctx.file.file_contexts
apex_key_info = ctx.attr.key[ApexKeyInfo]
@@ -143,27 +167,40 @@ def _run_apexer(ctx, apex_toolchain, apex_content_inputs, bazel_apexer_wrapper_m
android_jar = apex_toolchain.android_jar
android_manifest = ctx.file.android_manifest
+ file_mapping = _create_file_mapping(ctx)
+ canned_fs_config = _generate_canned_fs_config(ctx, file_mapping.values())
+ apex_manifest_pb = _convert_apex_manifest_json_to_pb(ctx, apex_toolchain)
+
+ file_mapping_file = ctx.actions.declare_file(ctx.attr.name + '_apex_file_mapping.json')
+ ctx.actions.write(file_mapping_file, json.encode({k.path: v for k,v in file_mapping.items()}))
+
# Outputs
apex_output_file = ctx.actions.declare_file(ctx.attr.name + ".apex.unsigned")
# Arguments
args = ctx.actions.args()
+ args.add(file_mapping_file.path)
+ args.add(apex_toolchain.apexer.path)
if ctx.attr._apexer_verbose[BuildSettingInfo].value:
- args.add_all(["--verbose", True])
+ args.add("--verbose")
+ args.add('--force')
+ args.add('--include_build_info')
+ args.add_all(['--canned_fs_config', canned_fs_config.path])
args.add_all(["--manifest", apex_manifest_pb.path])
args.add_all(["--file_contexts", file_contexts.path])
args.add_all(["--key", privkey.path])
args.add_all(["--pubkey", pubkey.path])
- min_sdk_version = ctx.attr.min_sdk_version
+ args.add_all(['--payload_type', 'image'])
+ args.add_all(['--target_sdk_version', '10000'])
+ args.add_all(['--payload_fs_type', 'ext4'])
# TODO(b/215339575): This is a super rudimentary way to convert "current" to a numerical number.
# Generalize this to API level handling logic in a separate Starlark utility, preferably using
# API level maps dumped from api_levels.go
+ min_sdk_version = ctx.attr.min_sdk_version
if min_sdk_version == "current":
min_sdk_version = "10000"
args.add_all(["--min_sdk_version", min_sdk_version])
- args.add_all(["--bazel_apexer_wrapper_manifest", bazel_apexer_wrapper_manifest])
- args.add_all(["--apexer_path", apex_toolchain.apexer])
# apexer needs the list of directories containing all auxilliary tools invoked during
# the creation of an apex
@@ -184,19 +221,25 @@ def _run_apexer(ctx, apex_toolchain, apex_content_inputs, bazel_apexer_wrapper_m
]
args.add_all(["--apexer_tool_path", ":".join(apexer_tool_paths)])
- args.add_all(["--apex_output_file", apex_output_file])
if android_manifest != None:
args.add_all(["--android_manifest", android_manifest.path])
- inputs = apex_content_inputs + [
- bazel_apexer_wrapper_manifest,
+ args.add("STAGING_DIR_PLACEHOLDER")
+ args.add(apex_output_file)
+
+ inputs = [
+ file_mapping_file,
+ canned_fs_config,
apex_manifest_pb,
file_contexts,
privkey,
pubkey,
android_jar,
- ]
+ ] + file_mapping.keys()
+
+ if android_manifest != None:
+ inputs.append(android_manifest)
tools = [
avbtool_files,
@@ -204,14 +247,10 @@ def _run_apexer(ctx, apex_toolchain, apex_content_inputs, bazel_apexer_wrapper_m
mke2fs_files,
resize2fs_files,
apex_toolchain.aapt2,
-
apex_toolchain.apexer,
apex_toolchain.sefcontext_compile,
]
- if android_manifest != None:
- inputs.append(android_manifest)
-
ctx.actions.run(
inputs = inputs,
tools = tools,
@@ -225,17 +264,6 @@ def _run_apexer(ctx, apex_toolchain, apex_content_inputs, bazel_apexer_wrapper_m
# Sign a file with signapk.
def _run_signapk(ctx, unsigned_file, signed_file, private_key, public_key, mnemonic):
- # Inputs
- inputs = [
- unsigned_file,
- private_key,
- public_key,
- ctx.executable._signapk,
- ]
-
- # Outputs
- outputs = [signed_file]
-
# Arguments
args = ctx.actions.args()
args.add_all(["-a", 4096])
@@ -244,8 +272,13 @@ def _run_signapk(ctx, unsigned_file, signed_file, private_key, public_key, mnemo
args.add_all([unsigned_file, signed_file])
ctx.actions.run(
- inputs = inputs,
- outputs = outputs,
+ inputs = [
+ unsigned_file,
+ private_key,
+ public_key,
+ ctx.executable._signapk,
+ ],
+ outputs = [signed_file],
executable = ctx.executable._signapk,
arguments = [args],
mnemonic = mnemonic,
@@ -255,21 +288,10 @@ def _run_signapk(ctx, unsigned_file, signed_file, private_key, public_key, mnemo
# Compress a file with apex_compression_tool.
def _run_apex_compression_tool(ctx, apex_toolchain, input_file, output_file_name):
- # Inputs
- inputs = [
- input_file,
- ]
-
avbtool_files = apex_toolchain.avbtool[DefaultInfo].files_to_run
- tools = [
- avbtool_files,
- apex_toolchain.apex_compression_tool,
- apex_toolchain.soong_zip,
- ]
# Outputs
compressed_file = ctx.actions.declare_file(output_file_name)
- outputs = [compressed_file]
# Arguments
args = ctx.actions.args()
@@ -280,9 +302,13 @@ def _run_apex_compression_tool(ctx, apex_toolchain, input_file, output_file_name
args.add_all(["--output", compressed_file])
ctx.actions.run(
- inputs = inputs,
- tools = tools,
- outputs = outputs,
+ inputs = [input_file],
+ tools = [
+ avbtool_files,
+ apex_toolchain.apex_compression_tool,
+ apex_toolchain.soong_zip,
+ ],
+ outputs = [compressed_file],
executable = apex_toolchain.apex_compression_tool,
arguments = [args],
mnemonic = "BazelApexCompressing",
@@ -293,26 +319,21 @@ def _run_apex_compression_tool(ctx, apex_toolchain, input_file, output_file_name
def _apex_rule_impl(ctx):
apex_toolchain = ctx.toolchains["//build/bazel/rules/apex:apex_toolchain_type"].toolchain_info
- apex_content_inputs, bazel_apexer_wrapper_manifest = _prepare_apexer_wrapper_inputs(ctx)
- apex_manifest_pb = _convert_apex_manifest_json_to_pb(ctx, apex_toolchain)
-
- unsigned_apex_output_file = _run_apexer(ctx, apex_toolchain, apex_content_inputs, bazel_apexer_wrapper_manifest, apex_manifest_pb)
+ unsigned_apex_output_file = _run_apexer(ctx, apex_toolchain)
apex_cert_info = ctx.attr.certificate[AndroidAppCertificateInfo]
private_key = apex_cert_info.pk8
public_key = apex_cert_info.pem
-
signed_apex = ctx.outputs.apex_output
+
_run_signapk(ctx, unsigned_apex_output_file, signed_apex, private_key, public_key, "BazelApexSigning")
- output_file = signed_apex
if ctx.attr.compressible:
compressed_apex_output_file = _run_apex_compression_tool(ctx, apex_toolchain, signed_apex, ctx.attr.name + ".capex.unsigned")
signed_capex = ctx.outputs.capex_output
_run_signapk(ctx, compressed_apex_output_file, signed_capex, private_key, public_key, "BazelCompressedApexSigning")
- files_to_build = depset([output_file])
- return [DefaultInfo(files = files_to_build), ApexInfo()]
+ return [DefaultInfo(files = depset([signed_apex])), ApexInfo()]
_apex = rule(
implementation = _apex_rule_impl,
diff --git a/rules/apex/bazel_apexer_wrapper.py b/rules/apex/bazel_apexer_wrapper.py
index 839cd53b..be12560b 100644
--- a/rules/apex/bazel_apexer_wrapper.py
+++ b/rules/apex/bazel_apexer_wrapper.py
@@ -14,198 +14,84 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import argparse
+import json
import os
import shutil
import subprocess
import sys
import tempfile
-def _create_apex(args, work_dir):
-
- image_apex_dir = "image.apex"
-
- # Used for creating canned_fs_config, since every file and dir in the APEX are represented
- # by an entry in the fs_config.
- apex_subdirs = []
- apex_filepaths = []
-
- input_dir = os.path.join(work_dir, image_apex_dir)
- os.makedirs(input_dir, exist_ok=True)
- bazel_apexer_wrapper_manifest = open(args.bazel_apexer_wrapper_manifest, 'r')
- file_lines = bazel_apexer_wrapper_manifest.readlines()
- for line in file_lines:
- line = line.strip()
- if (len(line) == 0):
- continue
- apex_dirname, apex_filename, bazel_input_file = line.split(",")
- full_apex_dirname = "/".join([input_dir, apex_dirname])
- os.makedirs(full_apex_dirname, exist_ok=True)
-
- apex_filepath = "/".join([apex_dirname, apex_filename])
- apex_filepaths.append(apex_filepath)
- apex_subdirs.append(apex_dirname)
-
- full_apex_filepath = "/".join([input_dir, apex_filepath])
- # Because Bazel execution root is a symlink forest, all the input files are symlinks, these
- # include the dependency files declared in the BUILD files as well as the files declared
- # and created in the bzl files. For sandbox runs the former are two or more level symlinks and
- # latter are one level symlinks. For non-sandbox runs, the former are one level symlinks
- # and the latter are actual files. Here are some examples:
- #
- # Two level symlinks:
- # system/timezone/output_data/version/tz_version ->
- # /usr/local/google/home/...out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
- # execroot/__main__/system/timezone/output_data/version/tz_version ->
- # /usr/local/google/home/.../system/timezone/output_data/version/tz_version
- #
- # Three level symlinks:
- # bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/libcrypto.so ->
- # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
- # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/libcrypto.so ->
- # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
- # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/
- # liblibcrypto_stripped.so ->
- # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
- # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/
- # liblibcrypto_unstripped.so
- #
- # One level symlinks:
- # bazel-out/android_target-fastbuild/bin/system/timezone/apex/apex_manifest.pb ->
- # /usr/local/google/home/.../out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
- # execroot/__main__/bazel-out/android_target-fastbuild/bin/system/timezone/apex/
- # apex_manifest.pb
-
- if os.path.islink(bazel_input_file):
- bazel_input_file = os.readlink(bazel_input_file)
-
- # For sandbox run these are the 2nd level symlinks and we need to resolve
- while os.path.islink(bazel_input_file) and 'execroot/__main__' in bazel_input_file:
- bazel_input_file = os.readlink(bazel_input_file)
-
- shutil.copyfile(bazel_input_file, full_apex_filepath, follow_symlinks=False)
-
- # Make sure subdirs are unique
- apex_subdirs_set = set()
- for d in apex_subdirs:
- apex_subdirs_set.add(d)
-
- # Make sure all the parent dirs of the current subdir are in the set, too
- dirs = d.split("/")
- for i in range(0, len(dirs)):
- apex_subdirs_set.add("/".join(dirs[:i]))
-
- canned_fs_config = _generate_canned_fs_config(work_dir, apex_subdirs_set, apex_filepaths)
-
- # Construct the main apexer command.
- cmd = [args.apexer_path]
- if args.verbose:
- cmd.append('--verbose')
- cmd.append('--force')
- cmd.append('--include_build_info')
- cmd.extend(['--file_contexts', args.file_contexts])
- cmd.extend(['--canned_fs_config', canned_fs_config])
- cmd.extend(['--key', args.key])
- cmd.extend(['--payload_type', 'image'])
- cmd.extend(['--target_sdk_version', '10000'])
- cmd.extend(['--payload_fs_type', 'ext4'])
- cmd.extend(['--apexer_tool_path', args.apexer_tool_paths])
-
- if args.android_manifest != None:
- cmd.extend(['--android_manifest', args.android_manifest])
-
- if args.pubkey != None:
- cmd.extend(['--pubkey', args.pubkey])
-
- if args.manifest != None:
- cmd.extend(['--manifest', args.manifest])
-
- if args.min_sdk_version != None:
- cmd.extend(['--min_sdk_version', args.min_sdk_version])
-
- if args.android_jar_path != None:
- cmd.extend(['--android_jar_path', args.android_jar_path])
-
- cmd.append(input_dir)
- cmd.append(args.apex_output_file)
-
- popen = subprocess.Popen(cmd)
- popen.wait()
-
- return True
-
-# Generate filesystem config. This encodes the filemode, uid, and gid of each
-# file in the APEX, including apex_manifest.json and apex_manifest.pb.
-#
-# NOTE: every file must have an entry.
-def _generate_canned_fs_config(work_dir, dirs, filepaths):
- with tempfile.NamedTemporaryFile(mode = 'w+', dir=work_dir, delete=False) as canned_fs_config:
- config_lines = []
- config_lines += ["/ 1000 1000 0755"]
- config_lines += ["/apex_manifest.json 1000 1000 0644"]
- config_lines += ["/apex_manifest.pb 1000 1000 0644"]
- config_lines += ["/" + filepath + " 1000 1000 0644" for filepath in filepaths]
- config_lines += ["/" + d + " 0 2000 0755" for d in dirs]
- canned_fs_config.write("\n".join(config_lines))
-
- return canned_fs_config.name
-
-def _parse_args(argv):
- parser = argparse.ArgumentParser(description='Build an APEX file')
-
- parser.add_argument(
- '--verbose',
- help='if enabled, make apexer log verbosely')
- parser.add_argument(
- '--manifest',
- help='path to the APEX manifest file (.pb)')
- parser.add_argument(
- '--apex_output_file',
- required=True,
- help='path to the APEX image file')
- parser.add_argument(
- '--bazel_apexer_wrapper_manifest',
- required=True,
- help='path to the manifest file that stores the info about the files to be packaged by apexer')
- parser.add_argument(
- '--android_manifest',
- help='path to the AndroidManifest file. If omitted, a default one is created and used')
- parser.add_argument(
- '--file_contexts',
- required=True,
- help='selinux file contexts file.')
- parser.add_argument(
- '--key',
- required=True,
- help='path to the private key file.')
- parser.add_argument(
- '--pubkey',
- help='path to the public key file. Used to bundle the public key in APEX for testing.')
- parser.add_argument(
- '--apexer_path',
- required=True,
- help='Path to the apexer binary.')
- parser.add_argument(
- '--apexer_tool_paths',
- required=True,
- help='Directories containing all the tools used by apexer, separated by ":" character.')
- parser.add_argument(
- '--min_sdk_version',
- help='Default Min SDK version to use for AndroidManifest.xml')
- parser.add_argument(
- '--android_jar_path',
- help='path to use as the source of the android API.')
-
- return parser.parse_args(argv)
-
def main(argv):
- args = _parse_args(argv)
-
- with tempfile.TemporaryDirectory() as work_dir:
- success = _create_apex(args, work_dir)
-
- if not success:
- sys.exit(1)
+ '''Build a staging directory, and then call apexer.
+
+ The first argument to this script must be the path to a file containing a json
+ dictionary mapping input files to their path in the staging directory. At least
+ one other argument must be "STAGING_DIR_PLACEHOLDER", which will be replaced
+ with the path to the staging directory.
+
+ Example:
+ bazel_apexer_wrapper apex_file_mapping.json path/to/apexer --various-apexer-flags STAGING_DIR_PLACEHOLDER path/to/out.apex.unsigned
+ '''
+ if len(argv) < 2:
+ sys.exit('bazel_apexer_wrapper needs at least 2 arguments.')
+ if not os.path.isfile(argv[0]):
+ sys.exit('File not found: '+argv[0])
+ if "STAGING_DIR_PLACEHOLDER" not in argv[1:]:
+ sys.exit('bazel_apexer_wrapper needs at least one argument to be "STAGING_DIR_PLACEHOLDER"')
+
+ with open(argv[0], 'r') as f:
+ file_mapping = json.load(f)
+ argv = argv[1:]
+
+ with tempfile.TemporaryDirectory() as staging_dir:
+ for path_in_bazel, path_in_apex in file_mapping.items():
+ path_in_apex = os.path.join(staging_dir, path_in_apex)
+ os.makedirs(os.path.dirname(path_in_apex), exist_ok=True)
+
+ # Because Bazel execution root is a symlink forest, all the input files are symlinks, these
+ # include the dependency files declared in the BUILD files as well as the files declared
+ # and created in the bzl files. For sandbox runs the former are two or more level symlinks and
+ # latter are one level symlinks. For non-sandbox runs, the former are one level symlinks
+ # and the latter are actual files. Here are some examples:
+ #
+ # Two level symlinks:
+ # system/timezone/output_data/version/tz_version ->
+ # /usr/local/google/home/...out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+ # execroot/__main__/system/timezone/output_data/version/tz_version ->
+ # /usr/local/google/home/.../system/timezone/output_data/version/tz_version
+ #
+ # Three level symlinks:
+ # bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/libcrypto.so ->
+ # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+ # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/libcrypto.so ->
+ # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+ # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/
+ # liblibcrypto_stripped.so ->
+ # /usr/local/google/home/yudiliu/android/aosp/master/out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+ # execroot/__main__/bazel-out/android_x86_64-fastbuild-ST-4ecd5e98bfdd/bin/external/boringssl/
+ # liblibcrypto_unstripped.so
+ #
+ # One level symlinks:
+ # bazel-out/android_target-fastbuild/bin/system/timezone/apex/apex_manifest.pb ->
+ # /usr/local/google/home/.../out/bazel/output_user_root/b1ed7e1e9af3ebbd1403e9cf794e4884/
+ # execroot/__main__/bazel-out/android_target-fastbuild/bin/system/timezone/apex/
+ # apex_manifest.pb
+ if os.path.islink(path_in_bazel):
+ path_in_bazel = os.readlink(path_in_bazel)
+
+ # For sandbox run these are the 2nd level symlinks and we need to resolve
+ while os.path.islink(path_in_bazel) and 'execroot/__main__' in path_in_bazel:
+ path_in_bazel = os.readlink(path_in_bazel)
+
+ shutil.copyfile(path_in_bazel, path_in_apex, follow_symlinks=False)
+
+ for i in range(len(argv)):
+ if argv[i] == "STAGING_DIR_PLACEHOLDER":
+ argv[i] = staging_dir
+
+ result = subprocess.run(argv)
+
+ sys.exit(result.returncode)
if __name__ == '__main__':
main(sys.argv[1:])
diff --git a/rules/apex/bazel_apexer_wrapper_test.sh b/rules/apex/bazel_apexer_wrapper_test.sh
index 24e26d00..29576ce2 100755
--- a/rules/apex/bazel_apexer_wrapper_test.sh
+++ b/rules/apex/bazel_apexer_wrapper_test.sh
@@ -73,14 +73,32 @@ output_file="${output_dir}/test.apex"
# Create the wrapper manifest file
bazel_apexer_wrapper_manifest_file=$(mktemp)
-echo "
-dir1,file1,"${input_dir}/file1"
-dir2/dir3,file2,"${input_dir}/file2"
-dir4,one_level_sym,"${input_dir}/one_level_sym"
-dir5,two_level_sym_in_execroot,"${input_dir}/two_level_sym_in_execroot"
-dir6,two_level_sym_not_in_execroot,"${input_dir}/two_level_sym_not_in_execroot"
-dir7,three_level_sym_in_execroot,"${input_dir}/three_level_sym_in_execroot"
-" > ${bazel_apexer_wrapper_manifest_file}
+echo "{
+\"${input_dir}/file1\": \"dir1/file1\",
+\"${input_dir}/file2\": \"dir2/dir3/file2\",
+\"${input_dir}/one_level_sym\": \"dir4/one_level_sym\",
+\"${input_dir}/two_level_sym_in_execroot\": \"dir5/two_level_sym_in_execroot\",
+\"${input_dir}/two_level_sym_not_in_execroot\": \"dir6/two_level_sym_not_in_execroot\",
+\"${input_dir}/three_level_sym_in_execroot\": \"dir7/three_level_sym_in_execroot\"
+}" > ${bazel_apexer_wrapper_manifest_file}
+
+canned_fs_config=$(mktemp)
+echo "/ 0 2000 0755
+/apex_manifest.json 1000 1000 0644
+/apex_manifest.pb 1000 1000 0644
+/dir1 0 2000 0755
+/dir1/file1 1000 1000 0644
+/dir2 0 2000 0755
+/dir2/dir3 0 2000 0755
+/dir2/dir3/file2 1000 1000 0644
+/dir4 0 2000 0755
+/dir4/one_level_sym 1000 1000 0644
+/dir5 0 2000 0755
+/dir5/two_level_sym_in_execroot 1000 1000 0644
+/dir6 0 2000 0755
+/dir6/two_level_sym_not_in_execroot 1000 1000 0644
+/dir7 0 2000 0755
+/dir7/three_level_sym_in_execroot 1000 1000 0644" > ${canned_fs_config}
apexer_tool_paths=${prebuilt_tool_path}:${avb_tool_path}:${avb_tool_path}:${e2fsdroid_path}:${mke2fs_path}:${resize2fs_path}:${debugfs_path}:${soong_zip_path}:${aapt2_path}
@@ -88,14 +106,16 @@ apexer_tool_paths=${prebuilt_tool_path}:${avb_tool_path}:${avb_tool_path}:${e2fs
# run bazel_apexer_wrapper
#############################################
"${RUNFILES_DIR}/__main__/build/bazel/rules/apex/bazel_apexer_wrapper" \
+ ${bazel_apexer_wrapper_manifest_file} \
+ ${apexer_tool_path} \
--manifest ${manifest_file} \
--file_contexts ${file_contexts_file} \
--key "${RUNFILES_DIR}/__main__/build/bazel/rules/apex/test.pem" \
- --apexer_path ${apexer_tool_path} \
- --apexer_tool_paths "${apexer_tool_paths}" \
- --apex_output_file ${output_file} \
- --bazel_apexer_wrapper_manifest ${bazel_apexer_wrapper_manifest_file} \
- --android_jar_path ${android_jar}
+ --apexer_tool_path "${apexer_tool_paths}" \
+ --android_jar_path ${android_jar} \
+ --canned_fs_config ${canned_fs_config} \
+ STAGING_DIR_PLACEHOLDER \
+ ${output_file}
#############################################
# check the result
diff --git a/rules/cc/cc_library_static.bzl b/rules/cc/cc_library_static.bzl
index f994490c..4526900e 100644
--- a/rules/cc/cc_library_static.bzl
+++ b/rules/cc/cc_library_static.bzl
@@ -144,6 +144,17 @@ def cc_library_static(
],
)
+ # TODO(b/231574899): restructure this to handle other images
+ copts += select({
+ "//build/bazel/rules/apex:non_apex": [],
+ "//conditions:default": [
+ "-D__ANDROID_APEX__",
+ # TODO(b/231322772): sdk_version/min_sdk_version if not finalized
+ "-D__ANDROID_APEX_MIN_SDK_VERSION__=10000",
+ ],
+ })
+
+
native.cc_library(
name = cpp_name,
srcs = srcs,