blob: 671d3a931ac05d8b0a92a6c93c0f6056e0970f81 [file] [log] [blame]
Ian Zernydcb172e2022-02-22 15:36:45 +01001#!/usr/bin/env python3
Søren Gjessecbeae782019-05-21 14:14:25 +02002# 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
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020010
Søren Gjessecbeae782019-05-21 14:14:25 +020011# Proguard lookup program classes before library classes. In R8 this is
12# not the behaviour (it used to be) R8 will check library classes before
13# program classes. Some apps have duplicate classes in the library and program.
14# To make these apps work with R8 simulate program classes before library
15# classes by creating a new library jar which have all the provided library
16# classes which are not also in program classes.
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020017def SanitizeLibrariesInPgconf(sanitized_lib_path,
18 sanitized_pgconf_path,
19 pgconfs,
20 injars=None,
21 libraryjars=None):
22 with open(sanitized_pgconf_path, 'w') as sanitized_pgconf:
23 injars = [] if injars is None else injars
24 libraryjars = [] if libraryjars is None else libraryjars
25 for pgconf in pgconfs:
26 pgconf_dirname = os.path.abspath(os.path.dirname(pgconf))
27 first_library_jar = True
28 with open(pgconf) as pgconf_file:
29 for line in pgconf_file:
30 trimmed = line.strip()
31 if trimmed.startswith('-injars'):
32 # Collect -injars and leave them in the configuration.
33 injar = os.path.join(pgconf_dirname,
34 trimmed[len('-injars'):].strip())
35 injars.append(injar)
36 sanitized_pgconf.write('-injars {}\n'.format(injar))
37 elif trimmed.startswith('-libraryjars'):
38 # Collect -libraryjars and replace them with the sanitized library.
39 libraryjar = os.path.join(
40 pgconf_dirname,
41 trimmed[len('-libraryjars'):].strip())
42 libraryjars.append(libraryjar)
43 if first_library_jar:
44 sanitized_pgconf.write(
45 '-libraryjars {}\n'.format(sanitized_lib_path))
46 first_library_jar = False
47 sanitized_pgconf.write('# {}'.format(line))
48 else:
49 sanitized_pgconf.write(line)
Søren Gjessecbeae782019-05-21 14:14:25 +020050
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020051 SanitizeLibraries(sanitized_lib_path, libraryjars, injars)
Søren Gjesse889e09d2019-11-07 16:33:51 +010052
53
54def SanitizeLibraries(sanitized_lib_path, libraryjars, injars):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020055 program_entries = set()
56 library_entries = set()
Søren Gjessecbeae782019-05-21 14:14:25 +020057
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020058 for injar in injars:
59 with zipfile.ZipFile(injar, 'r') as injar_zf:
60 for zipinfo in injar_zf.infolist():
61 program_entries.add(zipinfo.filename)
Søren Gjessecbeae782019-05-21 14:14:25 +020062
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020063 with zipfile.ZipFile(sanitized_lib_path, 'w') as output_zf:
64 for libraryjar in libraryjars:
65 with zipfile.ZipFile(libraryjar, 'r') as input_zf:
66 for zipinfo in input_zf.infolist():
67 if (not zipinfo.filename in program_entries and
68 not zipinfo.filename in library_entries):
69 library_entries.add(zipinfo.filename)
70 output_zf.writestr(zipinfo, input_zf.read(zipinfo))
Søren Gjessecbeae782019-05-21 14:14:25 +020071
Søren Gjessecbeae782019-05-21 14:14:25 +020072
Christoffer Quist Adamsen0bd90752019-11-11 12:16:29 +010073def usage(argv, error):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020074 print(error)
75 print("Usage: sanitize_libraries.py <sanitized_lib> <sanitized_pgconf> (" +
76 "--injar <existing_injar>" + "|--libraryjar <existing_library_jar>" +
77 "|--pgconf <existing_pgconf>)+")
78 return 1
Christoffer Quist Adamsen0bd90752019-11-11 12:16:29 +010079
80
Søren Gjessecbeae782019-05-21 14:14:25 +020081def main(argv):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020082 if (len(argv) < 4):
83 return usage(argv, "Wrong number of arguments!")
84 pgconfs = []
85 injars = []
86 libraryjars = []
87 i = 2
88 while i < len(argv):
89 directive = argv[i]
90 if directive not in ['--pgconf', '--injar', '--libraryjar']:
91 return usage(
92 argv,
93 'Unexpected argument, expected one of --pgconf, --injar, and ' +
94 '--libraryjar.')
95 if i + 1 >= len(argv):
96 return usage(argv, 'Expected argument after ' + directive + '.')
97 file = argv[i + 1]
98 if directive == '--pgconf':
99 pgconfs.append(file)
100 elif directive == '--injar':
101 injars.append(file)
102 elif directive == '--libraryjar':
103 libraryjars.append(file)
104 i = i + 2
105 SanitizeLibrariesInPgconf(argv[0], argv[1], pgconfs, injars, libraryjars)
106
Søren Gjessecbeae782019-05-21 14:14:25 +0200107
108if __name__ == '__main__':
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200109 sys.exit(main(sys.argv[1:]))