blob: e67a06e8b0183e2d9665c566d5bc53de1c415ef8 [file] [log] [blame]
Søren Gjessecbeae782019-05-21 14:14:25 +02001#!/usr/bin/env python
2# Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5from __future__ import print_function
6import os
7import sys
8import zipfile
9
10# Proguard lookup program classes before library classes. In R8 this is
11# not the behaviour (it used to be) R8 will check library classes before
12# program classes. Some apps have duplicate classes in the library and program.
13# To make these apps work with R8 simulate program classes before library
14# classes by creating a new library jar which have all the provided library
15# classes which are not also in program classes.
16def SanitizeLibraries(sanitized_lib_path, sanitized_pgconf_path, pgconfs):
17
18 injars = []
19 libraryjars = []
20
21 with open(sanitized_pgconf_path, 'w') as sanitized_pgconf:
22 for pgconf in pgconfs:
23 pgconf_dirname = os.path.abspath(os.path.dirname(pgconf))
24 first_library_jar = True
25 with open(pgconf) as pgconf_file:
26 for line in pgconf_file:
27 trimmed = line.strip()
28 if trimmed.startswith('-injars'):
29 # Collect -injars and leave them in the configuration.
30 injar = os.path.join(
31 pgconf_dirname, trimmed[len('-injars'):].strip())
32 injars.append(injar)
33 sanitized_pgconf.write('-injars {}\n'.format(injar))
34 elif trimmed.startswith('-libraryjars'):
35 # Collect -libraryjars and replace them with the sanitized library.
36 libraryjar = os.path.join(
37 pgconf_dirname, trimmed[len('-libraryjars'):].strip())
38 libraryjars.append(libraryjar)
39 if first_library_jar:
40 sanitized_pgconf.write(
41 '-libraryjars {}\n'.format(sanitized_lib_path))
42 first_library_jar = False
43 sanitized_pgconf.write('# {}'.format(line))
44 else:
45 sanitized_pgconf.write(line)
46
47 program_entries = set()
48 library_entries = set()
49
50 for injar in injars:
51 with zipfile.ZipFile(injar, 'r') as injar_zf:
52 for zipinfo in injar_zf.infolist():
53 program_entries.add(zipinfo.filename)
54
55 with zipfile.ZipFile(sanitized_lib_path, 'w') as output_zf:
56 for libraryjar in libraryjars:
57 with zipfile.ZipFile(libraryjar, 'r') as input_zf:
58 for zipinfo in input_zf.infolist():
59 if (not zipinfo.filename in program_entries
60 and not zipinfo.filename in library_entries):
61 library_entries.add(zipinfo.filename)
62 output_zf.writestr(zipinfo, input_zf.read(zipinfo))
63
64 return sanitized_pgconf_path
65
66def main(argv):
67 if (len(argv) < 3):
68 print("Wrong number of arguments!")
69 print("Usage: sanitize_libraries.py " +
70 "<sanitized_lib> <sanitized_pgconf> (<existing_pgconf)+")
71 return 1
72 else:
73 SanitizeLibraries(argv[0], argv[1], argv[2:])
74
75if __name__ == '__main__':
76 sys.exit(main(sys.argv[1:]))