blob: 8ca54a79aef591403cd1757ab7ef3fddd94f751a [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
from __future__ import print_function
import os
import sys
import zipfile
# Proguard lookup program classes before library classes. In R8 this is
# not the behaviour (it used to be) R8 will check library classes before
# program classes. Some apps have duplicate classes in the library and program.
# To make these apps work with R8 simulate program classes before library
# classes by creating a new library jar which have all the provided library
# classes which are not also in program classes.
def SanitizeLibrariesInPgconf(
sanitized_lib_path,
sanitized_pgconf_path,
pgconfs,
injars = None,
libraryjars = None):
with open(sanitized_pgconf_path, 'w') as sanitized_pgconf:
injars = [] if injars is None else injars
libraryjars = [] if libraryjars is None else libraryjars
for pgconf in pgconfs:
pgconf_dirname = os.path.abspath(os.path.dirname(pgconf))
first_library_jar = True
with open(pgconf) as pgconf_file:
for line in pgconf_file:
trimmed = line.strip()
if trimmed.startswith('-injars'):
# Collect -injars and leave them in the configuration.
injar = os.path.join(
pgconf_dirname, trimmed[len('-injars'):].strip())
injars.append(injar)
sanitized_pgconf.write('-injars {}\n'.format(injar))
elif trimmed.startswith('-libraryjars'):
# Collect -libraryjars and replace them with the sanitized library.
libraryjar = os.path.join(
pgconf_dirname, trimmed[len('-libraryjars'):].strip())
libraryjars.append(libraryjar)
if first_library_jar:
sanitized_pgconf.write(
'-libraryjars {}\n'.format(sanitized_lib_path))
first_library_jar = False
sanitized_pgconf.write('# {}'.format(line))
else:
sanitized_pgconf.write(line)
SanitizeLibraries(sanitized_lib_path, libraryjars, injars)
def SanitizeLibraries(sanitized_lib_path, libraryjars, injars):
program_entries = set()
library_entries = set()
for injar in injars:
with zipfile.ZipFile(injar, 'r') as injar_zf:
for zipinfo in injar_zf.infolist():
program_entries.add(zipinfo.filename)
with zipfile.ZipFile(sanitized_lib_path, 'w') as output_zf:
for libraryjar in libraryjars:
with zipfile.ZipFile(libraryjar, 'r') as input_zf:
for zipinfo in input_zf.infolist():
if (not zipinfo.filename in program_entries
and not zipinfo.filename in library_entries):
library_entries.add(zipinfo.filename)
output_zf.writestr(zipinfo, input_zf.read(zipinfo))
def usage(argv, error):
print(error)
print("Usage: sanitize_libraries.py <sanitized_lib> <sanitized_pgconf> ("
+ "--injar <existing_injar>"
+ "|--libraryjar <existing_library_jar>"
+ "|--pgconf <existing_pgconf>)+")
return 1
def main(argv):
if (len(argv) < 4):
return usage(argv, "Wrong number of arguments!")
pgconfs = []
injars = []
libraryjars = []
i = 2
while i < len(argv):
directive = argv[i]
if directive not in ['--pgconf', '--injar', '--libraryjar']:
return usage(
argv,
'Unexpected argument, expected one of --pgconf, --injar, and '
+ '--libraryjar.')
if i + 1 >= len(argv):
return usage(argv, 'Expected argument after ' + directive + '.')
file = argv[i + 1]
if directive == '--pgconf':
pgconfs.append(file)
elif directive == '--injar':
injars.append(file)
elif directive == '--libraryjar':
libraryjars.append(file)
i = i + 2
SanitizeLibrariesInPgconf(argv[0], argv[1], pgconfs, injars, libraryjars)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))