Refactor proguard scripts
Currently, we use proguard from two places: proguard.py and apk_obfuscate.py. These are used to preprocess libraries and to process full apks, respectively. This extracts construction/running/filtering output of the actual proguard command to a simple builder class that is then used in both places. This makes some parts of how proguard is run to be more consistent between the two. proguard.py now supports running proguard in the way needed for apks. (GN will be using proguard.py instead of apk_obfuscate.py) BUG=359249,478319 Review URL: https://codereview.chromium.org/1103013002 Cr-Original-Commit-Position: refs/heads/master@{#328439} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: e852f8d50a4c65f0de6fcc3753abdc8ba3b22a9e
This commit is contained in:
Родитель
04a29cead4
Коммит
c0bc4f0ef1
|
@ -15,6 +15,8 @@ import os
|
|||
import sys
|
||||
|
||||
from util import build_utils
|
||||
from util import proguard_util
|
||||
|
||||
|
||||
def ParseArgs(argv):
|
||||
parser = optparse.OptionParser()
|
||||
|
@ -71,72 +73,60 @@ def ParseArgs(argv):
|
|||
)
|
||||
|
||||
build_utils.CheckOptions(options, parser, required=required_options)
|
||||
|
||||
return options, args
|
||||
|
||||
|
||||
def DoProguard(options):
|
||||
proguard = proguard_util.ProguardCmdBuilder(options.proguard_jar_path)
|
||||
proguard.outjar(options.obfuscated_jar_path)
|
||||
|
||||
library_classpath = [options.android_sdk_jar]
|
||||
input_jars = build_utils.ParseGypList(options.input_jars_paths)
|
||||
|
||||
exclude_paths = []
|
||||
configs = build_utils.ParseGypList(options.proguard_configs)
|
||||
if options.tested_apk_obfuscated_jar_path:
|
||||
# configs should only contain the process_resources.py generated config.
|
||||
assert len(configs) == 1, (
|
||||
'test apks should not have custom proguard configs: ' + str(configs))
|
||||
tested_jar_info = build_utils.ReadJson(
|
||||
options.tested_apk_obfuscated_jar_path + '.info')
|
||||
exclude_paths = tested_jar_info['inputs']
|
||||
configs = tested_jar_info['configs']
|
||||
|
||||
proguard.is_test(True)
|
||||
proguard.mapping(options.tested_apk_obfuscated_jar_path + '.mapping')
|
||||
library_classpath.append(options.tested_apk_obfuscated_jar_path)
|
||||
|
||||
proguard.libraryjars(library_classpath)
|
||||
proguard_injars = [p for p in input_jars if p not in exclude_paths]
|
||||
proguard.injars(proguard_injars)
|
||||
proguard.configs(configs)
|
||||
|
||||
proguard.CheckOutput()
|
||||
|
||||
this_info = {
|
||||
'inputs': proguard_injars,
|
||||
'configs': configs
|
||||
}
|
||||
|
||||
build_utils.WriteJson(
|
||||
this_info, options.obfuscated_jar_path + '.info')
|
||||
|
||||
|
||||
def main(argv):
|
||||
options, _ = ParseArgs(argv)
|
||||
|
||||
library_classpath = [options.android_sdk_jar]
|
||||
input_jars = build_utils.ParseGypList(options.input_jars_paths)
|
||||
|
||||
dependency_class_filters = [
|
||||
'*R.class', '*R$*.class', '*Manifest.class', '*BuildConfig.class']
|
||||
|
||||
if options.testapp:
|
||||
dependency_class_filters = [
|
||||
'*R.class', '*R$*.class', '*Manifest.class', '*BuildConfig.class']
|
||||
build_utils.MergeZips(
|
||||
options.test_jar_path, input_jars, dependency_class_filters)
|
||||
|
||||
if options.configuration_name == 'Release' and options.proguard_enabled:
|
||||
proguard_cmd = [
|
||||
'java', '-jar', options.proguard_jar_path,
|
||||
'-forceprocessing',
|
||||
'-libraryjars', ':'.join(library_classpath),
|
||||
'-dump', options.obfuscated_jar_path + '.dump',
|
||||
'-printseeds', options.obfuscated_jar_path + '.seeds',
|
||||
'-printusage', options.obfuscated_jar_path + '.usage',
|
||||
'-printmapping', options.obfuscated_jar_path + '.mapping',
|
||||
]
|
||||
|
||||
exclude_paths = []
|
||||
configs = build_utils.ParseGypList(options.proguard_configs)
|
||||
if (options.tested_apk_obfuscated_jar_path and
|
||||
options.tested_apk_obfuscated_jar_path != '/'):
|
||||
# configs should only contain the process_resources.py generated config.
|
||||
assert len(configs) == 1, (
|
||||
'test apks should not have custom proguard configs: ' + str(configs))
|
||||
tested_jar_info = build_utils.ReadJson(
|
||||
options.tested_apk_obfuscated_jar_path + '.info')
|
||||
exclude_paths = tested_jar_info['inputs']
|
||||
configs = tested_jar_info['configs']
|
||||
proguard_cmd += [
|
||||
'-dontobfuscate',
|
||||
'-dontoptimize',
|
||||
'-dontshrink',
|
||||
'-dontskipnonpubliclibraryclassmembers',
|
||||
'-libraryjars', options.tested_apk_obfuscated_jar_path,
|
||||
'-applymapping', options.tested_apk_obfuscated_jar_path + '.mapping',
|
||||
]
|
||||
|
||||
proguard_injars = [p for p in input_jars if p not in exclude_paths]
|
||||
proguard_cmd += ['-injars', ':'.join(proguard_injars)]
|
||||
|
||||
for config_file in configs:
|
||||
proguard_cmd += ['-include', config_file]
|
||||
|
||||
# The output jar must be specified after inputs.
|
||||
proguard_cmd += ['-outjars', options.obfuscated_jar_path]
|
||||
|
||||
build_utils.CheckOutput(proguard_cmd)
|
||||
|
||||
this_info = {
|
||||
'inputs': proguard_injars,
|
||||
'configs': configs
|
||||
}
|
||||
|
||||
build_utils.WriteJson(
|
||||
this_info, options.obfuscated_jar_path + '.info')
|
||||
DoProguard(options)
|
||||
else:
|
||||
output_files = [
|
||||
options.obfuscated_jar_path,
|
||||
|
|
|
@ -5,54 +5,32 @@
|
|||
# found in the LICENSE file.
|
||||
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
from util import build_utils
|
||||
from util import proguard_util
|
||||
|
||||
def DoProguard(options):
|
||||
injars = options.input_path
|
||||
outjars = options.output_path
|
||||
proguard = proguard_util.ProguardCmdBuilder(options.proguard_path)
|
||||
proguard.injars(build_utils.ParseGypList(options.input_paths))
|
||||
proguard.configs(build_utils.ParseGypList(options.proguard_configs))
|
||||
proguard.outjar(options.output_path)
|
||||
|
||||
if options.mapping:
|
||||
proguard.mapping(options.mapping)
|
||||
|
||||
if options.is_test:
|
||||
proguard.is_test(True)
|
||||
|
||||
classpath = []
|
||||
for arg in options.classpath:
|
||||
classpath += build_utils.ParseGypList(arg)
|
||||
classpath = list(set(classpath))
|
||||
libraryjars = ':'.join(classpath)
|
||||
# proguard does its own dependency checking, which can be avoided by deleting
|
||||
# the output.
|
||||
if os.path.exists(options.output_path):
|
||||
os.remove(options.output_path)
|
||||
proguard_cmd = ['java', '-jar',
|
||||
options.proguard_path,
|
||||
'-injars', injars,
|
||||
'-outjars', outjars,
|
||||
'-libraryjars', libraryjars,
|
||||
'@' + options.proguard_config]
|
||||
build_utils.CheckOutput(proguard_cmd, print_stdout=True,
|
||||
stdout_filter=FilterProguardOutput)
|
||||
proguard.libraryjars(classpath)
|
||||
|
||||
proguard.CheckOutput()
|
||||
|
||||
def FilterProguardOutput(output):
|
||||
'''ProGuard outputs boring stuff to stdout (proguard version, jar path, etc)
|
||||
as well as interesting stuff (notes, warnings, etc). If stdout is entirely
|
||||
boring, this method suppresses the output.
|
||||
'''
|
||||
ignore_patterns = [
|
||||
'ProGuard, version ',
|
||||
'Reading program jar [',
|
||||
'Reading library jar [',
|
||||
'Preparing output jar [',
|
||||
' Copying resources from program jar [',
|
||||
]
|
||||
for line in output.splitlines():
|
||||
for pattern in ignore_patterns:
|
||||
if line.startswith(pattern):
|
||||
break
|
||||
else:
|
||||
# line doesn't match any of the patterns; it's probably something worth
|
||||
# printing out.
|
||||
return output
|
||||
return ''
|
||||
return proguard.GetInputs()
|
||||
|
||||
|
||||
def main(args):
|
||||
|
@ -61,23 +39,27 @@ def main(args):
|
|||
build_utils.AddDepfileOption(parser)
|
||||
parser.add_option('--proguard-path',
|
||||
help='Path to the proguard executable.')
|
||||
parser.add_option('--input-path',
|
||||
help='Path to the .jar file proguard should run on.')
|
||||
parser.add_option('--input-paths',
|
||||
help='Paths to the .jar files proguard should run on.')
|
||||
parser.add_option('--output-path', help='Path to the generated .jar file.')
|
||||
parser.add_option('--proguard-config',
|
||||
help='Path to the proguard configuration file.')
|
||||
parser.add_option('--proguard-configs',
|
||||
help='Paths to proguard configuration files.')
|
||||
parser.add_option('--mapping', help='Path to proguard mapping to apply.')
|
||||
parser.add_option('--is-test', action='store_true',
|
||||
help='If true, extra proguard options for instrumentation tests will be '
|
||||
'added.')
|
||||
parser.add_option('--classpath', action='append',
|
||||
help="Classpath for proguard.")
|
||||
help='Classpath for proguard.')
|
||||
parser.add_option('--stamp', help='Path to touch on success.')
|
||||
|
||||
options, _ = parser.parse_args(args)
|
||||
|
||||
DoProguard(options)
|
||||
inputs = DoProguard(options)
|
||||
|
||||
if options.depfile:
|
||||
build_utils.WriteDepfile(
|
||||
options.depfile,
|
||||
build_utils.GetPythonDependencies())
|
||||
inputs + build_utils.GetPythonDependencies())
|
||||
|
||||
if options.stamp:
|
||||
build_utils.Touch(options.stamp)
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
# Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import os
|
||||
from util import build_utils
|
||||
|
||||
def FilterProguardOutput(output):
|
||||
'''ProGuard outputs boring stuff to stdout (proguard version, jar path, etc)
|
||||
as well as interesting stuff (notes, warnings, etc). If stdout is entirely
|
||||
boring, this method suppresses the output.
|
||||
'''
|
||||
ignore_patterns = [
|
||||
'ProGuard, version ',
|
||||
'Reading program jar [',
|
||||
'Reading library jar [',
|
||||
'Preparing output jar [',
|
||||
' Copying resources from program jar [',
|
||||
]
|
||||
for line in output.splitlines():
|
||||
for pattern in ignore_patterns:
|
||||
if line.startswith(pattern):
|
||||
break
|
||||
else:
|
||||
# line doesn't match any of the patterns; it's probably something worth
|
||||
# printing out.
|
||||
return output
|
||||
return ''
|
||||
|
||||
|
||||
class ProguardCmdBuilder(object):
|
||||
def __init__(self, proguard_jar):
|
||||
assert os.path.exists(proguard_jar)
|
||||
self._proguard_jar_path = proguard_jar
|
||||
self._test = None
|
||||
self._mapping = None
|
||||
self._libraries = None
|
||||
self._injars = None
|
||||
self._configs = None
|
||||
self._outjar = None
|
||||
|
||||
def outjar(self, path):
|
||||
assert self._outjar is None
|
||||
self._outjar = path
|
||||
|
||||
def is_test(self, enable):
|
||||
assert self._test is None
|
||||
self._test = enable
|
||||
|
||||
def mapping(self, path):
|
||||
assert self._mapping is None
|
||||
assert os.path.exists(path), path
|
||||
self._mapping = path
|
||||
|
||||
def libraryjars(self, paths):
|
||||
assert self._libraries is None
|
||||
for p in paths:
|
||||
assert os.path.exists(p), p
|
||||
self._libraries = paths
|
||||
|
||||
def injars(self, paths):
|
||||
assert self._injars is None
|
||||
for p in paths:
|
||||
assert os.path.exists(p), p
|
||||
self._injars = paths
|
||||
|
||||
def configs(self, paths):
|
||||
assert self._configs is None
|
||||
for p in paths:
|
||||
assert os.path.exists(p), p
|
||||
self._configs = paths
|
||||
|
||||
def build(self):
|
||||
assert self._injars is not None
|
||||
assert self._outjar is not None
|
||||
assert self._configs is not None
|
||||
cmd = [
|
||||
'java', '-jar', self._proguard_jar_path,
|
||||
'-forceprocessing',
|
||||
]
|
||||
if self._test:
|
||||
cmd += [
|
||||
'-dontobfuscate',
|
||||
'-dontoptimize',
|
||||
'-dontshrink',
|
||||
'-dontskipnonpubliclibraryclassmembers',
|
||||
]
|
||||
|
||||
if self._mapping:
|
||||
cmd += [
|
||||
'-applymapping', self._mapping,
|
||||
]
|
||||
|
||||
if self._libraries:
|
||||
cmd += [
|
||||
'-libraryjars', ':'.join(self._libraries),
|
||||
]
|
||||
|
||||
cmd += [
|
||||
'-injars', ':'.join(self._injars)
|
||||
]
|
||||
|
||||
for config_file in self._configs:
|
||||
cmd += ['-include', config_file]
|
||||
|
||||
# The output jar must be specified after inputs.
|
||||
cmd += [
|
||||
'-outjars', self._outjar,
|
||||
'-dump', self._outjar + '.dump',
|
||||
'-printseeds', self._outjar + '.seeds',
|
||||
'-printusage', self._outjar + '.usage',
|
||||
'-printmapping', self._outjar + '.mapping',
|
||||
]
|
||||
return cmd
|
||||
|
||||
def GetInputs(self):
|
||||
inputs = [self._proguard_jar_path] + self._configs + self._injars
|
||||
if self._mapping:
|
||||
inputs.append(self._mapping)
|
||||
if self._libraries:
|
||||
inputs += self._libraries
|
||||
return inputs
|
||||
|
||||
|
||||
def CheckOutput(self):
|
||||
build_utils.CheckOutput(self.build(), print_stdout=True,
|
||||
stdout_filter=FilterProguardOutput)
|
||||
|
|
@ -806,7 +806,6 @@
|
|||
'--input-jars-paths=>(proguard_input_jar_paths)',
|
||||
'--proguard-configs=>(proguard_flags_paths)',
|
||||
|
||||
|
||||
'--test-jar-path', '<(test_jar_path)',
|
||||
'--obfuscated-jar-path', '<(obfuscated_jar_path)',
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче