• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# Copyright 2014 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Generates the obfuscated jar and test jar for an apk.
8
9If proguard is not enabled or 'Release' is not in the configuration name,
10obfuscation will be a no-op.
11"""
12
13import optparse
14import os
15import sys
16
17from util import build_utils
18
19def ParseArgs(argv):
20  parser = optparse.OptionParser()
21  parser.add_option('--android-sdk', help='path to the Android SDK folder')
22  parser.add_option('--android-sdk-tools',
23                    help='path to the Android SDK build tools folder')
24  parser.add_option('--android-sdk-jar',
25                    help='path to Android SDK\'s android.jar')
26  parser.add_option('--proguard-jar-path',
27                    help='Path to proguard.jar in the sdk')
28  parser.add_option('--input-jars-paths',
29                    help='Path to jars to include in obfuscated jar')
30
31  parser.add_option('--proguard-configs',
32                    help='Paths to proguard config files')
33
34  parser.add_option('--configuration-name',
35                    help='Gyp configuration name (i.e. Debug, Release)')
36  parser.add_option('--proguard-enabled', action='store_true',
37                    help='Set if proguard is enabled for this target.')
38
39  parser.add_option('--obfuscated-jar-path',
40                    help='Output path for obfuscated jar.')
41
42  parser.add_option('--testapp', action='store_true',
43                    help='Set this if building an instrumentation test apk')
44  parser.add_option('--tested-apk-obfuscated-jar-path',
45                    help='Path to obfusctated jar of the tested apk')
46  parser.add_option('--test-jar-path',
47                    help='Output path for jar containing all the test apk\'s '
48                    'code.')
49
50  parser.add_option('--stamp', help='File to touch on success')
51
52  (options, args) = parser.parse_args(argv)
53
54  if args:
55    parser.error('No positional arguments should be given. ' + str(args))
56
57  # Check that required options have been provided.
58  required_options = (
59      'android_sdk',
60      'android_sdk_tools',
61      'android_sdk_jar',
62      'proguard_jar_path',
63      'input_jars_paths',
64      'configuration_name',
65      'obfuscated_jar_path',
66      )
67
68  if options.testapp:
69    required_options += (
70        'test_jar_path',
71        )
72
73  build_utils.CheckOptions(options, parser, required=required_options)
74
75  return options, args
76
77
78def main(argv):
79  options, _ = ParseArgs(argv)
80
81  library_classpath = [options.android_sdk_jar]
82  input_jars = build_utils.ParseGypList(options.input_jars_paths)
83
84  dependency_class_filters = [
85      '*R.class', '*R$*.class', '*Manifest.class', '*BuildConfig.class']
86
87  if options.testapp:
88    build_utils.MergeZips(
89        options.test_jar_path, input_jars, dependency_class_filters)
90
91  if options.configuration_name == 'Release' and options.proguard_enabled:
92    proguard_cmd = [
93        'java', '-jar', options.proguard_jar_path,
94        '-forceprocessing',
95        '-libraryjars', ':'.join(library_classpath),
96        '-dump', options.obfuscated_jar_path + '.dump',
97        '-printseeds', options.obfuscated_jar_path + '.seeds',
98        '-printusage', options.obfuscated_jar_path + '.usage',
99        '-printmapping', options.obfuscated_jar_path + '.mapping',
100        ]
101
102    exclude_paths = []
103    configs = build_utils.ParseGypList(options.proguard_configs)
104    if (options.tested_apk_obfuscated_jar_path and
105        options.tested_apk_obfuscated_jar_path != '/'):
106      # configs should only contain the process_resources.py generated config.
107      assert len(configs) == 1, (
108          'test apks should not have custom proguard configs: ' + str(configs))
109      tested_jar_info = build_utils.ReadJson(
110          options.tested_apk_obfuscated_jar_path + '.info')
111      exclude_paths = tested_jar_info['inputs']
112      configs = tested_jar_info['configs']
113      proguard_cmd += [
114          '-dontobfuscate',
115          '-dontoptimize',
116          '-dontshrink',
117          '-dontskipnonpubliclibraryclassmembers',
118          '-libraryjars', options.tested_apk_obfuscated_jar_path,
119          '-applymapping', options.tested_apk_obfuscated_jar_path + '.mapping',
120          ]
121
122    proguard_injars = [p for p in input_jars if p not in exclude_paths]
123    proguard_cmd += ['-injars', ':'.join(proguard_injars)]
124
125    for config_file in configs:
126      proguard_cmd += ['-include', config_file]
127
128    # The output jar must be specified after inputs.
129    proguard_cmd += ['-outjars', options.obfuscated_jar_path]
130
131    build_utils.CheckOutput(proguard_cmd)
132
133    this_info = {
134      'inputs': proguard_injars,
135      'configs': configs
136    }
137
138    build_utils.WriteJson(
139        this_info, options.obfuscated_jar_path + '.info')
140  else:
141    output_files = [
142        options.obfuscated_jar_path,
143        options.obfuscated_jar_path + '.info',
144        options.obfuscated_jar_path + '.dump',
145        options.obfuscated_jar_path + '.seeds',
146        options.obfuscated_jar_path + '.usage',
147        options.obfuscated_jar_path + '.mapping']
148    for f in output_files:
149      if os.path.exists(f):
150        os.remove(f)
151      build_utils.Touch(f)
152
153  if options.stamp:
154    build_utils.Touch(options.stamp)
155
156if __name__ == '__main__':
157  sys.exit(main(sys.argv[1:]))
158