• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# Copyright 2019 The Chromium Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import argparse
7import os
8import re
9import sys
10import zipfile
11
12sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir))
13from pylib.dex import dex_parser
14from util import build_utils
15import action_helpers  # build_utils adds //build to sys.path.
16
17_FLAGS_PATH = (
18    '//chrome/android/java/static_library_dex_reference_workarounds.flags')
19
20
21def _FindIllegalStaticLibraryReferences(static_lib_dex_files,
22                                        main_apk_dex_files):
23  main_apk_defined_types = set()
24  for dex_file in main_apk_dex_files:
25    for class_def_item in dex_file.class_def_item_list:
26      main_apk_defined_types.add(
27          dex_file.GetTypeString(class_def_item.class_idx))
28
29  static_lib_referenced_types = set()
30  for dex_file in static_lib_dex_files:
31    for type_item in dex_file.type_item_list:
32      static_lib_referenced_types.add(
33          dex_file.GetString(type_item.descriptor_idx))
34
35  return main_apk_defined_types.intersection(static_lib_referenced_types)
36
37
38def _DexFilesFromPath(path):
39  if zipfile.is_zipfile(path):
40    with zipfile.ZipFile(path) as z:
41      return [
42          dex_parser.DexFile(bytearray(z.read(name))) for name in z.namelist()
43          if re.match(r'.*classes[0-9]*\.dex$', name)
44      ]
45  else:
46    with open(path) as f:
47      return dex_parser.DexFile(bytearray(f.read()))
48
49
50def main(args):
51  args = build_utils.ExpandFileArgs(args)
52  parser = argparse.ArgumentParser()
53  action_helpers.add_depfile_arg(parser)
54  parser.add_argument(
55      '--stamp', required=True, help='Path to file to touch upon success.')
56  parser.add_argument(
57      '--static-library-dex',
58      required=True,
59      help='classes.dex or classes.zip for the static library APK that was '
60      'proguarded with other dependent APKs')
61  parser.add_argument(
62      '--static-library-dependent-dex',
63      required=True,
64      action='append',
65      dest='static_library_dependent_dexes',
66      help='classes.dex or classes.zip for the APKs that use the static '
67      'library APK')
68  args = parser.parse_args(args)
69
70  static_library_dexfiles = _DexFilesFromPath(args.static_library_dex)
71  for path in args.static_library_dependent_dexes:
72    dependent_dexfiles = _DexFilesFromPath(path)
73    illegal_references = _FindIllegalStaticLibraryReferences(
74        static_library_dexfiles, dependent_dexfiles)
75
76    if illegal_references:
77      msg = 'Found illegal references from {} to {}\n'.format(
78          args.static_library_dex, path)
79      msg += 'Add a -keep rule to avoid this. '
80      msg += 'See {} for an example and why this is necessary.\n'.format(
81          _FLAGS_PATH)
82      msg += 'The illegal references are:\n'
83      msg += '\n'.join(illegal_references)
84      sys.stderr.write(msg)
85      sys.exit(1)
86
87  input_paths = [args.static_library_dex] + args.static_library_dependent_dexes
88  build_utils.Touch(args.stamp)
89  action_helpers.write_depfile(args.depfile, args.stamp, inputs=input_paths)
90
91
92if __name__ == '__main__':
93  sys.exit(main(sys.argv[1:]))
94