• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2
3"""This is a wrapper function of apexer. It provides opportunity to do
4some artifact preprocessing before calling into apexer. Some of these
5artifact preprocessing are difficult or impossible to do in soong or
6bazel such as placing native shared libs in DCLA. It is better to do
7these in a binary so that the DCLA preprocessing logic can be reused
8regardless of the build system
9"""
10
11import argparse
12from glob import glob
13import os
14import shutil
15import sys
16import tempfile
17
18import apexer_wrapper_utils
19
20def ParseArgs(argv):
21  parser = argparse.ArgumentParser(
22      description='wrapper to run apexer for DCLA')
23  parser.add_argument(
24      '--apexer',
25      help='path to apexer binary')
26  parser.add_argument(
27      '--canned_fs_config',
28      help='path to canned_fs_config file')
29  parser.add_argument(
30      'input_dir',
31      metavar='INPUT_DIR',
32      help='the directory having files to be packaged')
33  parser.add_argument(
34      'output',
35      metavar='OUTPUT',
36      help='name of the APEX file')
37  parser.add_argument(
38      'rest_args',
39      nargs='*',
40      help='remaining flags that will be passed as-is to apexer')
41  return parser.parse_args(argv)
42
43def PlaceDCLANativeSharedLibs(image_dir: str, canned_fs_config: str) -> str:
44  """Place native shared libs for DCLA in a special way.
45
46  Traditional apex has native shared libs placed under /lib(64)? inside
47  the apex. However, for DCLA, it needs to be placed in a special way:
48
49  /lib(64)?/foo.so/<sha512 foo.so>/foo.so
50
51  This function moves the shared libs to desired location and update
52  canned_fs_config file accordingly
53  """
54
55  # remove all .so entries from canned_fs_config
56  parent_dir = os.path.dirname(canned_fs_config)
57  updated_canned_fs_config = os.path.join(parent_dir, 'updated_canned_fs_config')
58  with open(canned_fs_config, 'r') as f:
59    lines = f.readlines()
60  with open(updated_canned_fs_config, 'w') as f:
61    for line in lines:
62      segs = line.split(' ')
63      if not segs[0].endswith('.so'):
64        f.write(line)
65      else:
66        with tempfile.TemporaryDirectory() as tmp_dir:
67          # move native libs
68          lib_file = os.path.join(image_dir, segs[0][1:])
69          digest = apexer_wrapper_utils.GetDigest(lib_file)
70          lib_name = os.path.basename(lib_file)
71          dest_dir = os.path.join(lib_file, digest)
72
73          shutil.move(lib_file, os.path.join(tmp_dir, lib_name))
74          os.makedirs(dest_dir, exist_ok=True)
75          shutil.move(os.path.join(tmp_dir, lib_name),
76                      os.path.join(dest_dir, lib_name))
77
78          # add canned_fs_config entries
79          f.write(f'{segs[0]} 0 2000 0755\n')
80          f.write(f'{os.path.join(segs[0], digest)} 0 2000 0755\n')
81          f.write(f'{os.path.join(segs[0], digest, lib_name)} 1000 1000 0644\n')
82
83  # return the modified canned_fs_config
84  return updated_canned_fs_config
85
86def main(argv):
87  args = ParseArgs(argv)
88  args.canned_fs_config = PlaceDCLANativeSharedLibs(
89      args.input_dir, args.canned_fs_config)
90
91  cmd = [args.apexer, '--canned_fs_config', args.canned_fs_config]
92  cmd.extend(args.rest_args)
93  cmd.extend([args.input_dir, args.output])
94
95  apexer_wrapper_utils.RunCommand(cmd)
96
97if __name__ == "__main__":
98 main(sys.argv[1:])
99