diff options
author | cjhopman@chromium.org <cjhopman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-11 13:19:47 +0000 |
---|---|---|
committer | cjhopman@chromium.org <cjhopman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-11 13:19:47 +0000 |
commit | e92d61e1866c035d790131692b2bb78754420153 (patch) | |
tree | c31bfe70d5f82fe53aa88a2f1a5ba960f165fbba | |
parent | ac59ea834e59a588c3354f14c2b4ae47cb384aad (diff) | |
download | chromium_src-e92d61e1866c035d790131692b2bb78754420153.zip chromium_src-e92d61e1866c035d790131692b2bb78754420153.tar.gz chromium_src-e92d61e1866c035d790131692b2bb78754420153.tar.bz2 |
Convert apk obfuscation to python
For the apk specific java files, we now run proguard on the jar instead of the classes.
BUG=375324,359249
Review URL: https://codereview.chromium.org/322443005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@276377 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | build/android/ant/apk-obfuscate.xml | 175 | ||||
-rwxr-xr-x | build/android/gyp/apk_obfuscate.py | 132 | ||||
-rw-r--r-- | build/apk_fake_jar.gypi | 10 | ||||
-rw-r--r-- | build/java_apk.gypi | 81 |
4 files changed, 188 insertions, 210 deletions
diff --git a/build/android/ant/apk-obfuscate.xml b/build/android/ant/apk-obfuscate.xml deleted file mode 100644 index 094c988..0000000 --- a/build/android/ant/apk-obfuscate.xml +++ /dev/null @@ -1,175 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - Copyright (C) 2005-2008 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<project default="-obfuscate"> - <property name="verbose" value="false" /> - <property name="out.dir" location="${OUT_DIR}" /> - <!-- Output directories --> - <property name="out.dir" value="bin" /> - <property name="out.absolute.dir" location="${out.dir}" /> - <property name="out.classes.absolute.dir" location="${out.dir}/classes" /> - - <!-- tools location --> - <property name="sdk.dir" location="${ANDROID_SDK_ROOT}"/> - <property name="android.tools.dir" location="${sdk.dir}/tools" /> - - <property name="project.target.android.jar" location="${ANDROID_SDK_JAR}" /> - <path id="project.target.class.path"> - <pathelement location="${project.target.android.jar}" /> - </path> - - - <!-- jar file from where the tasks are loaded --> - <path id="android.antlibs"> - <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" /> - </path> - - <!-- Custom tasks --> - <taskdef resource="anttasks.properties" classpathref="android.antlibs" /> - - <!-- Classpath for javac --> - <path id="javac.custom.classpath"> - <filelist files="${INPUT_JARS_PATHS}"/> - </path> - - <condition property="project.is.testapp" value="true" else="false"> - <equals arg1="${IS_TEST_APK}" arg2="1" /> - </condition> - - <property name="proguard.enabled" value="${PROGUARD_ENABLED}" /> - <property name="proguard.config" value="${PROGUARD_FLAGS}" /> - - <property name="manifest.file" value="${ANDROID_MANIFEST}" /> - <property name="manifest.abs.file" location="${manifest.file}" /> - - <!-- Obfuscate target - This is only active in release builds when proguard.config is defined - in default.properties. - - --> - <!-- - Override obfuscate target to pass javac.custom.classpath to Proguard. SDK tools do not provide - any way to pass custom class paths to Proguard. - --> - <target name="-obfuscate"> - <if condition="${project.is.testapp}"> - <then> - <!-- get the project manifest package --> - <xpath input="${manifest.abs.file}" - expression="/manifest/@package" output="project.app.package" /> - <loadresource property="project.app.packagepath"> - <propertyresource name="project.app.package"/> - <filterchain> - <replacestring from="." to="/"/> - </filterchain> - </loadresource> - <property name="create.test.jar.exclusions" value="${project.app.packagepath}/R.class ${project.app.packagepath}/R$*.class ${project.app.packagepath}/Manifest.class ${project.app.packagepath}/Manifest$*.class ${project.app.packagepath}/BuildConfig.class"/> - <jar destfile="${TEST_JAR_PATH}" - excludes="${create.test.jar.exclusions}" - duplicate="preserve" - > - <restrict> - <name name="**/*.class"/> - <archives> - <zips> - <path refid="javac.custom.classpath"/> - </zips> - </archives> - </restrict> - <fileset dir="${out.dir}/classes"/> - </jar> - </then> - </if> - <if> - <condition> - <and> - <istrue value="${proguard.enabled}"/> - <equals arg1="${CONFIGURATION_NAME}" arg2="Release"/> - </and> - </condition> - <then> - <property name="obfuscate.absolute.dir" location="${out.absolute.dir}/proguard"/> - <property name="preobfuscate.jar.file" value="${obfuscate.absolute.dir}/original.jar"/> - <property name="obfuscated.jar.file" value="${OBFUSCATED_JAR_PATH}"/> - <property name="obfuscated.jar.abs.file" location="${obfuscated.jar.file}"/> - - <!-- Add Proguard Tasks --> - <property name="proguard.jar" location="${android.tools.dir}/proguard/lib/proguard.jar"/> - <taskdef name="proguard" classname="proguard.ant.ProGuardTask" classpath="${proguard.jar}"/> - - <!-- Set the android classpath Path object into a single property. It'll be - all the jar files separated by a platform path-separator. - Each path must be quoted if it contains spaces. - --> - <pathconvert property="project.target.classpath.value" refid="project.target.class.path"> - <firstmatchmapper> - <regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"'/> - <identitymapper/> - </firstmatchmapper> - </pathconvert> - - <!-- Build a path object with all the jar files that must be obfuscated. - This include the project compiled source code and any 3rd party jar - files. --> - <path id="project.all.classes.path"> - <pathelement location="${preobfuscate.jar.file}"/> - <!-- Pass javac.custom.classpath for apks. --> - <path refid="javac.custom.classpath"/> - </path> - <!-- Set the project jar files Path object into a single property. It'll be - all the jar files separated by a platform path-separator. - Each path must be quoted if it contains spaces. - --> - <pathconvert property="project.all.classes.value" refid="project.all.classes.path"> - <firstmatchmapper> - <regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"'/> - <identitymapper/> - </firstmatchmapper> - </pathconvert> - - <!-- Turn the path property ${proguard.config} from an A:B:C property - into a series of includes: -include A -include B -include C - suitable for processing by the ProGuard task. Note - this does - not include the leading '-include "' or the closing '"'; those - are added under the <proguard> call below. - --> - <path id="proguard.configpath"> - <filelist files="${proguard.config}"/> - </path> - <pathconvert pathsep='" -include "' property="proguard.configcmd" - refid="proguard.configpath"/> - - <mkdir dir="${obfuscate.absolute.dir}"/> - <delete file="${preobfuscate.jar.file}"/> - <delete file="${obfuscated.jar.abs.file}"/> - <jar basedir="${out.classes.absolute.dir}" - destfile="${preobfuscate.jar.file}"/> - <proguard> - -include "${proguard.configcmd}" - -injars ${project.all.classes.value} - -outjars "${obfuscated.jar.abs.file}" - -libraryjars ${project.target.classpath.value} - -dump "${obfuscate.absolute.dir}/dump.txt" - -printseeds "${obfuscate.absolute.dir}/seeds.txt" - -printusage "${obfuscate.absolute.dir}/usage.txt" - -printmapping "${obfuscate.absolute.dir}/mapping.txt" - </proguard> - </then> - </if> - <touch file="${STAMP}" /> - </target> -</project> diff --git a/build/android/gyp/apk_obfuscate.py b/build/android/gyp/apk_obfuscate.py new file mode 100755 index 0000000..1e2eccf --- /dev/null +++ b/build/android/gyp/apk_obfuscate.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# +# Copyright 2014 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. + +"""Generates the obfuscated jar and test jar for an apk. + +If proguard is not enabled or 'Release' is not in the configuration name, +obfuscation will be a no-op. +""" + +import fnmatch +import optparse +import os +import sys +import zipfile + +from util import build_utils + +def ParseArgs(argv): + parser = optparse.OptionParser() + parser.add_option('--android-sdk', help='path to the Android SDK folder') + parser.add_option('--android-sdk-tools', + help='path to the Android SDK build tools folder') + parser.add_option('--android-sdk-jar', + help='path to Android SDK\'s android.jar') + parser.add_option('--proguard-jar-path', + help='Path to proguard.jar in the sdk') + + parser.add_option('--input-jars-paths', + help='Path to jars to include in obfuscated jar') + + parser.add_option('--proguard-config-files', + help='Paths to proguard config files') + + parser.add_option('--configuration-name', + help='Gyp configuration name (i.e. Debug, Release)') + parser.add_option('--proguard-enabled', action='store_true', + help='Set if proguard is enabled for this target.') + + parser.add_option('--obfuscated-jar-path', + help='Output path for obfuscated jar.') + + parser.add_option('--testapp', action='store_true', + help='Set this if building an instrumentation test apk') + parser.add_option('--test-jar-path', + help='Output path for jar containing all the test apk\'s ' + 'code.') + + parser.add_option('--stamp', help='File to touch on success') + + (options, args) = parser.parse_args(argv) + + if args: + parser.error('No positional arguments should be given. ' + str(args)) + + # Check that required options have been provided. + required_options = ( + 'android_sdk', + 'android_sdk_tools', + 'android_sdk_jar', + 'proguard_jar_path', + 'input_jars_paths', + 'configuration_name', + 'obfuscated_jar_path', + ) + build_utils.CheckOptions(options, parser, required=required_options) + + return options, args + + +def main(argv): + options, _ = ParseArgs(argv) + + library_classpath = [options.android_sdk_jar] + javac_custom_classpath = build_utils.ParseGypList(options.input_jars_paths) + + dependency_class_filters = [ + '*R.class', '*R$*.class', '*Manifest.class', '*BuildConfig.class'] + + def DependencyClassFilter(name): + for name_filter in dependency_class_filters: + if fnmatch.fnmatch(name, name_filter): + return False + return True + + if options.testapp: + with zipfile.ZipFile(options.test_jar_path, 'w') as test_jar: + for jar in build_utils.ParseGypList(options.input_jars_paths): + with zipfile.ZipFile(jar, 'r') as jar_zip: + for name in filter(DependencyClassFilter, jar_zip.namelist()): + with jar_zip.open(name) as zip_entry: + test_jar.writestr(name, zip_entry.read()) + + if options.configuration_name == 'Release' and options.proguard_enabled: + proguard_project_classpath = javac_custom_classpath + + proguard_cmd = [ + 'java', '-jar', options.proguard_jar_path, + '-forceprocessing', + '-injars', ':'.join(proguard_project_classpath), + '-libraryjars', ':'.join(library_classpath), + '-outjars', options.obfuscated_jar_path, + '-dump', options.obfuscated_jar_path + '.dump', + '-printseeds', options.obfuscated_jar_path + '.seeds', + '-printusage', options.obfuscated_jar_path + '.usage', + '-printmapping', options.obfuscated_jar_path + '.mapping', + ] + + for proguard_file in build_utils.ParseGypList( + options.proguard_config_files): + proguard_cmd += ['-include', proguard_file] + + build_utils.CheckOutput(proguard_cmd) + else: + output_files = [ + options.obfuscated_jar_path, + options.obfuscated_jar_path + '.dump', + options.obfuscated_jar_path + '.seeds', + options.obfuscated_jar_path + '.usage', + options.obfuscated_jar_path + '.mapping'] + for f in output_files: + if os.path.exists(f): + os.remove(f) + build_utils.Touch(f) + + if options.stamp: + build_utils.Touch(options.stamp) + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/build/apk_fake_jar.gypi b/build/apk_fake_jar.gypi index 2787691..128b84c 100644 --- a/build/apk_fake_jar.gypi +++ b/build/apk_fake_jar.gypi @@ -12,14 +12,4 @@ 'library_dexed_jars_paths': ['>(apk_output_jar_path)'], }, }, - # Add an action with the appropriate output. This allows the generated - # buildfiles to determine which target the output corresponds to. - 'actions': [ - { - 'action_name': 'fake_generate_jar', - 'inputs': [], - 'outputs': ['>(apk_output_jar_path)'], - 'action': [], - }, - ], } diff --git a/build/java_apk.gypi b/build/java_apk.gypi index b654ad8..9e2b937 100644 --- a/build/java_apk.gypi +++ b/build/java_apk.gypi @@ -98,6 +98,7 @@ 'jar_excluded_classes': [], 'jar_path': '<(PRODUCT_DIR)/lib.java/<(jar_name)', 'obfuscated_jar_path': '<(intermediate_dir)/obfuscated.jar', + 'test_jar_path': '<(PRODUCT_DIR)/test.lib.java/<(apk_name).jar', 'dex_path': '<(intermediate_dir)/classes.dex', 'emma_device_jar': '<(android_sdk_root)/tools/lib/emma_device.jar', 'android_manifest_path%': '<(java_in_dir)/AndroidManifest.xml', @@ -585,6 +586,7 @@ ], 'outputs': [ '<(jar_stamp)', + '<(jar_path)', ], 'action': [ 'python', '<(DEPTH)/build/android/gyp/jar.py', @@ -595,43 +597,72 @@ ] }, { - 'action_name': 'ant_obfuscate_<(_target_name)', + 'action_name': 'obfuscate_<(_target_name)', 'message': 'Obfuscating <(_target_name)', + 'variables': { + 'additional_obfuscate_options': [], + 'proguard_out_dir': '<(intermediate_dir)/proguard', + 'proguard_input_jar_paths': [ + '>@(input_jars_paths)', + '<(jar_path)', + ], + 'conditions': [ + ['is_test_apk == 1', { + 'additional_obfuscate_options': [ + '--testapp', + ], + }], + ['proguard_enabled == "true"', { + 'additional_obfuscate_options': [ + '--proguard-enabled', + ], + }], + ], + }, + 'conditions': [ + ['is_test_apk == 1', { + 'outputs': [ + '<(test_jar_path)', + ], + }], + ], 'inputs': [ - '<(DEPTH)/build/android/ant/apk-obfuscate.xml', + '<(DEPTH)/build/android/gyp/apk_obfuscate.py', '<(DEPTH)/build/android/gyp/util/build_utils.py', - '<(DEPTH)/build/android/gyp/ant.py', - '<(android_manifest_path)', '>@(proguard_flags_paths)', - '<(instr_stamp)', + '>@(proguard_input_jar_paths)', ], 'outputs': [ # This lists obfuscate_stamp instead of obfuscated_jar_path because # ant only writes the latter if the md5 of the inputs changes. '<(obfuscate_stamp)', + + # In non-Release builds, these paths will all be empty files. + '<(obfuscated_jar_path)', + '<(obfuscated_jar_path).dump', + '<(obfuscated_jar_path).seeds', + '<(obfuscated_jar_path).mapping', + '<(obfuscated_jar_path).usage', ], 'action': [ - 'python', '<(DEPTH)/build/android/gyp/ant.py', - '-quiet', - '-DANDROID_MANIFEST=<(android_manifest_path)', - '-DANDROID_SDK_JAR=<(android_sdk_jar)', - '-DANDROID_SDK_ROOT=<(android_sdk_root)', - '-DANDROID_SDK_VERSION=<(android_sdk_version)', - '-DANDROID_SDK_TOOLS=<(android_sdk_tools)', - '-DAPK_NAME=<(apk_name)', - '-DCONFIGURATION_NAME=<(CONFIGURATION_NAME)', - '-DINPUT_JARS_PATHS=>(input_jars_paths)', - '-DIS_TEST_APK=<(is_test_apk)', - '-DOBFUSCATED_JAR_PATH=<(obfuscated_jar_path)', - '-DOUT_DIR=<(intermediate_dir)', - '-DPROGUARD_ENABLED=<(proguard_enabled)', - '-DPROGUARD_FLAGS=<(proguard_flags_paths)', - '-DTEST_JAR_PATH=<(PRODUCT_DIR)/test.lib.java/<(apk_name).jar', + 'python', '<(DEPTH)/build/android/gyp/apk_obfuscate.py', - '-DSTAMP=<(obfuscate_stamp)', - '-Dbasedir=.', - '-buildfile', - '<(DEPTH)/build/android/ant/apk-obfuscate.xml', + '--configuration-name', '<(CONFIGURATION_NAME)', + + '--android-sdk', '<(android_sdk)', + '--android-sdk-tools', '<(android_sdk_tools)', + '--android-sdk-jar', '<(android_sdk_jar)', + + '--input-jars-paths=>(proguard_input_jar_paths)', + '--test-jar-path', '<(test_jar_path)', + '--obfuscated-jar-path', '<(obfuscated_jar_path)', + + '--proguard-jar-path', '<(android_sdk_root)/tools/proguard/lib/proguard.jar', + + '--proguard-config-files=<(proguard_flags_paths)', + '--stamp', '<(obfuscate_stamp)', + + '<@(additional_obfuscate_options)', ], }, { |