111 lines
3.6 KiB
Python
111 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
|
|
"""This is a wrapper function of apexer. It provides opportunity to do
|
|
some artifact preprocessing before calling into apexer. Some of these
|
|
artifact preprocessing are difficult or impossible to do in soong or
|
|
bazel such as trimming the apex native shared libs. It is better to do
|
|
these in a binary so that the preprocessing logic can be reused regardless
|
|
of the build system
|
|
"""
|
|
|
|
import argparse
|
|
from glob import glob
|
|
import os
|
|
import re
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
|
|
import apex_manifest_pb2
|
|
import apexer_wrapper_utils
|
|
|
|
def ParseArgs(argv):
|
|
parser = argparse.ArgumentParser(
|
|
description='wrapper to run apexer with native shared lib trimming')
|
|
parser.add_argument(
|
|
'--apexer',
|
|
help='path to apexer binary')
|
|
parser.add_argument(
|
|
'--canned_fs_config',
|
|
help='path to canned_fs_config file')
|
|
parser.add_argument(
|
|
'--manifest',
|
|
help='path to apex_manifest.pb file')
|
|
parser.add_argument(
|
|
'--libs_to_trim',
|
|
help='native shared libraries to trim')
|
|
parser.add_argument(
|
|
'input_dir',
|
|
metavar='INPUT_DIR',
|
|
help='the directory having files to be packaged')
|
|
parser.add_argument(
|
|
'output',
|
|
metavar='OUTPUT',
|
|
help='name of the APEX file')
|
|
parser.add_argument(
|
|
'rest_args',
|
|
nargs='*',
|
|
help='remaining flags that will be passed as-is to apexer')
|
|
return parser.parse_args(argv)
|
|
|
|
def TrimNativeSharedLibs(image_dir: str, canned_fs_config: str,
|
|
manifest: str, libs_to_trim: list[str]):
|
|
"""Place native shared libs for trimmed variant in a special way.
|
|
|
|
Traditional apex has native shared libs placed under /lib(64)? inside
|
|
the apex. However, for trimmed variant, for the libs to trim, they will
|
|
be replaced with a sym link to
|
|
|
|
/apex/sharedlibs/lib(64)?/foo.so/[sha512 foo.so]/foo.so
|
|
"""
|
|
|
|
libs_trimmed = set()
|
|
with open(canned_fs_config, 'r') as f:
|
|
lines = f.readlines()
|
|
for line in lines:
|
|
segs = line.split(' ')
|
|
if segs[0].endswith('.so'):
|
|
if any(segs[0].endswith(v) for v in libs_to_trim):
|
|
lib_relative_path = segs[0][1:]
|
|
lib_absolute_path = os.path.join(image_dir, lib_relative_path)
|
|
lib_name = os.path.basename(lib_relative_path)
|
|
libs_trimmed.add(lib_name)
|
|
digest = apexer_wrapper_utils.GetDigest(lib_absolute_path)
|
|
os.remove(lib_absolute_path)
|
|
link = os.path.join('/apex/sharedlibs', lib_relative_path, digest, lib_name)
|
|
os.symlink(link, lib_absolute_path)
|
|
|
|
manifest_pb = apex_manifest_pb2.ApexManifest()
|
|
with open(manifest, 'rb') as f:
|
|
manifest_pb.ParseFromString(f.read())
|
|
|
|
# bump version code
|
|
# google mainline module logic, for trimmed variant, the variant digit is 2
|
|
manifest_pb.version = 10*(manifest_pb.version // 10) + 2
|
|
|
|
# setting requireSharedApexLibs
|
|
del manifest_pb.requireSharedApexLibs[:]
|
|
manifest_pb.requireSharedApexLibs.extend(
|
|
sorted(re.sub(r':.{128}$', ':sha-512', lib)
|
|
for lib in libs_trimmed))
|
|
|
|
# write back to root apex_manifest.pb
|
|
with open(manifest, 'wb') as f:
|
|
f.write(manifest_pb.SerializeToString())
|
|
|
|
def main(argv):
|
|
args = ParseArgs(argv)
|
|
segs = args.libs_to_trim.split(',')
|
|
libs_to_trim = [v+'.so' for v in args.libs_to_trim.split(',')]
|
|
TrimNativeSharedLibs(args.input_dir, args.canned_fs_config, args.manifest,
|
|
libs_to_trim)
|
|
cmd = [args.apexer, '--canned_fs_config', args.canned_fs_config]
|
|
cmd.extend(['--manifest', args.manifest])
|
|
cmd.extend(args.rest_args)
|
|
cmd.extend([args.input_dir, args.output])
|
|
|
|
apexer_wrapper_utils.RunCommand(cmd)
|
|
|
|
if __name__ == "__main__":
|
|
main(sys.argv[1:])
|