diff options
author | gkanwar@chromium.org <gkanwar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-22 00:08:31 +0000 |
---|---|---|
committer | gkanwar@chromium.org <gkanwar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-22 00:08:31 +0000 |
commit | c0a127749a99ad36ac62f2764ab259508cef5267 (patch) | |
tree | 397358c8d0b89b1d97b70048bd0d3715ccf6777a /build | |
parent | 9934a5e76dd787bb8924bda6e6830824c1726058 (diff) | |
download | chromium_src-c0a127749a99ad36ac62f2764ab259508cef5267.zip chromium_src-c0a127749a99ad36ac62f2764ab259508cef5267.tar.gz chromium_src-c0a127749a99ad36ac62f2764ab259508cef5267.tar.bz2 |
Makes GYP changes for EMMA coverage
One piece of the overall java coverage change.
See: https://codereview.chromium.org/20210002/
NOTRY=True
BUG=255644
Review URL: https://chromiumcodereview.appspot.com/22870021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@218870 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'build')
-rw-r--r-- | build/android/ant/apk-package.xml | 55 | ||||
-rw-r--r-- | build/android/dex_action.gypi | 2 | ||||
-rwxr-xr-x | build/android/gyp/ant.py | 4 | ||||
-rwxr-xr-x | build/android/gyp/dex.py | 22 | ||||
-rwxr-xr-x | build/android/gyp/emma_instr.py | 184 | ||||
-rw-r--r-- | build/android/instr_action.gypi | 51 | ||||
-rw-r--r-- | build/common.gypi | 4 | ||||
-rw-r--r-- | build/java.gypi | 48 | ||||
-rw-r--r-- | build/java_apk.gypi | 37 |
9 files changed, 368 insertions, 39 deletions
diff --git a/build/android/ant/apk-package.xml b/build/android/ant/apk-package.xml index eeb156c..69f5501 100644 --- a/build/android/ant/apk-package.xml +++ b/build/android/ant/apk-package.xml @@ -21,6 +21,11 @@ <property name="out.absolute.dir" location="${out.dir}" /> <property name="sdk.dir" location="${ANDROID_SDK_ROOT}"/> + <property name="emma.device.jar" location="${EMMA_DEVICE_JAR}" /> + + <condition property="emma.enabled" value="true" else="false"> + <equals arg1="${EMMA_INSTRUMENT}" arg2="1"/> + </condition> <!-- jar file from where the tasks are loaded --> <path id="android.antlibs"> @@ -54,21 +59,43 @@ <property name="source.dir" value="${SOURCE_DIR}" /> <property name="source.absolute.dir" location="${source.dir}" /> + <!-- Macro that enables passing a variable list of external jar files + to ApkBuilder. --> + <macrodef name="package-helper"> + <element name="extra-jars" optional="yes" /> + <sequential> + <apkbuilder + outfolder="${out.absolute.dir}" + resourcefile="${resource.package.file.name}" + apkfilepath="${out.packaged.file}" + debugpackaging="${build.is.packaging.debug}" + debugsigning="${build.is.signing.debug}" + verbose="${verbose}" + hascode="true" + previousBuildType="/" + buildType="${build.is.packaging.debug}/${build.is.signing.debug}"> + <dex path="${intermediate.dex.file}"/> + <sourcefolder path="${source.absolute.dir}"/> + <nativefolder path="${native.libs.absolute.dir}" /> + <extra-jars/> + </apkbuilder> + </sequential> + </macrodef> + + <!-- Packages the application. --> <target name="-package"> - <apkbuilder - outfolder="${out.absolute.dir}" - resourcefile="${resource.package.file.name}" - apkfilepath="${out.packaged.file}" - debugpackaging="${build.is.packaging.debug}" - debugsigning="${build.is.signing.debug}" - verbose="${verbose}" - hascode="true" - previousBuildType="/" - buildType="${build.is.packaging.debug}/${build.is.signing.debug}"> - <dex path="${intermediate.dex.file}"/> - <sourcefolder path="${source.absolute.dir}"/> - <nativefolder path="${native.libs.absolute.dir}" /> - </apkbuilder> + <if condition="${emma.enabled}"> + <then> + <package-helper> + <extra-jars> + <jarfile path="${emma.device.jar}" /> + </extra-jars> + </package-helper> + </then> + <else> + <package-helper /> + </else> + </if> </target> </project> diff --git a/build/android/dex_action.gypi b/build/android/dex_action.gypi index ac956b6..9b640d6 100644 --- a/build/android/dex_action.gypi +++ b/build/android/dex_action.gypi @@ -33,6 +33,7 @@ 'input_paths': [], 'proguard_enabled%': 'false', 'proguard_enabled_input_path%': '', + 'dex_no_locals%': 0, }, 'inputs': [ '<(DEPTH)/build/android/gyp/util/build_utils.py', @@ -51,6 +52,7 @@ '--configuration-name=<(CONFIGURATION_NAME)', '--proguard-enabled=<(proguard_enabled)', '--proguard-enabled-input-path=<(proguard_enabled_input_path)', + '--no-locals=<(dex_no_locals)', # TODO(newt): remove this once http://crbug.com/177552 is fixed in ninja. '--ignore=>!(echo \'>(_inputs)\' | md5sum)', diff --git a/build/android/gyp/ant.py b/build/android/gyp/ant.py index acf3dcc..45ed3ed 100755 --- a/build/android/gyp/ant.py +++ b/build/android/gyp/ant.py @@ -3,7 +3,8 @@ # Copyright 2013 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. -"""An Ant wrapper that suppresses useless Ant output + +"""An Ant wrapper that suppresses useless Ant output. Ant build scripts output "BUILD SUCCESSFUL" and build timing at the end of every build. In the Android build, this just adds a lot of useless noise to the @@ -27,4 +28,3 @@ def main(argv): if __name__ == '__main__': sys.exit(main(sys.argv)) - diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py index c1e5869..f90de95 100755 --- a/build/android/gyp/dex.py +++ b/build/android/gyp/dex.py @@ -4,7 +4,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import fnmatch import optparse import os import sys @@ -15,10 +14,11 @@ from util import md5_check def DoDex(options, paths): dx_binary = os.path.join(options.android_sdk_tools, 'dx') - # See http://crbug.com/272064 for context on --force-jumbo. - dex_cmd = [dx_binary, '--dex', '--force-jumbo', '--output', - options.dex_path] + paths + dex_cmd = [dx_binary, '--dex', '--force-jumbo', '--output', options.dex_path] + if options.no_locals != '0': + dex_cmd.append('--no-locals') + dex_cmd += paths record_path = '%s.md5.stamp' % options.dex_path md5_check.CallAndRecordIfStale( @@ -36,11 +36,14 @@ def main(argv): help='Android sdk build tools directory.') parser.add_option('--dex-path', help='Dex output path.') parser.add_option('--configuration-name', - help='The build CONFIGURATION_NAME.') + help='The build CONFIGURATION_NAME.') parser.add_option('--proguard-enabled', - help='"true" if proguard is enabled.') + help='"true" if proguard is enabled.') parser.add_option('--proguard-enabled-input-path', - help='Path to dex in Release mode when proguard is enabled.') + help=('Path to dex in Release mode when proguard ' + 'is enabled.')) + parser.add_option('--no-locals', + help='Exclude locals list from the dex file.') parser.add_option('--stamp', help='Path to touch on success.') # TODO(newt): remove this once http://crbug.com/177552 is fixed in ninja. @@ -48,8 +51,8 @@ def main(argv): options, paths = parser.parse_args() - if (options.proguard_enabled == "true" - and options.configuration_name == "Release"): + if (options.proguard_enabled == 'true' + and options.configuration_name == 'Release'): paths = [options.proguard_enabled_input_path] DoDex(options, paths) @@ -60,4 +63,3 @@ def main(argv): if __name__ == '__main__': sys.exit(main(sys.argv)) - diff --git a/build/android/gyp/emma_instr.py b/build/android/gyp/emma_instr.py new file mode 100755 index 0000000..c682163 --- /dev/null +++ b/build/android/gyp/emma_instr.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Copyright 2013 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. + +"""Instruments classes and jar files. + +This script corresponds to the 'emma_instr' action in the java build process. +Depending on whether emma_instrument is set, the 'emma_instr' action will either +call one of the instrument commands, or the copy command. + +Possible commands are: +- instrument_jar: Accepts a jar and instruments it using emma.jar. +- instrument_classes: Accepts a directory contains java classes and instruments + it using emma.jar. +- copy: Triggered instead of an instrumentation command when we don't have EMMA + coverage enabled. This allows us to make this a required step without + necessarily instrumenting on every build. +""" + +import collections +import json +import os +import shutil +import sys +import tempfile + +sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir)) +from pylib.utils import command_option_parser + +from util import build_utils + + +def _AddCommonOptions(option_parser): + """Adds common options to |option_parser|.""" + option_parser.add_option('--input-path', + help=('Path to input file(s). Either the classes ' + 'directory, or the path to a jar.')) + option_parser.add_option('--output-path', + help=('Path to output final file(s) to. Either the ' + 'final classes directory, or the directory in ' + 'which to place the instrumented/copied jar.')) + option_parser.add_option('--stamp', help='Path to touch when done.') + + +def _AddInstrumentOptions(option_parser): + """Adds options related to instrumentation to |option_parser|.""" + _AddCommonOptions(option_parser) + option_parser.add_option('--coverage-file', + help='File to create with coverage metadata') + option_parser.add_option('--sources-file', + help='File to create with the list of sources.') + option_parser.add_option('--sources', + help='Space separated list of sources.') + option_parser.add_option('--src-root', + help='Root of the src repository.') + option_parser.add_option('--emma-jar', + help='Path to emma.jar.') + + +def _RunCopyCommand(command, options, args, option_parser): + """Just copies the jar from input to output locations. + + Args: + command: String indicating the command that was received to trigger + this function. + options: optparse options dictionary. + args: List of extra args from optparse. + option_parser: optparse.OptionParser object. + + Returns: + An exit code. + """ + if not (options.input_path and options.output_path): + option_parser.error('All arguments are required.') + + if os.path.isdir(options.input_path): + shutil.rmtree(options.output_path, ignore_errors=True) + shutil.copytree(options.input_path, options.output_path) + else: + shutil.copy(options.input_path, options.output_path) + + if options.stamp: + build_utils.Touch(options.stamp) + + +def _CreateSourcesFile(sources_string, sources_file, src_root): + """Adds all normalized source directories to |sources_file|. + + Args: + sources_string: String generated from gyp containing the list of sources. + sources_file: File into which to write the JSON list of sources. + src_root: Root which sources added to the file should be relative to. + + Returns: + An exit code. + """ + src_root = os.path.abspath(src_root) + sources = build_utils.ParseGypList(sources_string) + relative_sources = [] + for s in sources: + abs_source = os.path.abspath(s) + if abs_source[:len(src_root)] != src_root: + print ('Error: found source directory not under repository root: %s %s' + % (abs_source, src_root)) + return 1 + rel_source = os.path.relpath(abs_source, src_root) + + relative_sources.append(rel_source) + + with open(sources_file, 'w') as f: + json.dump(relative_sources, f) + + +def _RunInstrumentCommand(command, options, args, option_parser): + """Instruments the classes/jar files using EMMA. + + Args: + command: 'instrument_jar' or 'instrument_classes'. This distinguishes + whether we copy the output from the created lib/ directory, or classes/ + directory. + options: optparse options dictionary. + args: List of extra args from optparse. + option_parser: optparse.OptionParser object. + + Returns: + An exit code. + """ + if not (options.input_path and options.output_path and + options.coverage_file and options.sources_file and options.sources and + options.src_root and options.emma_jar): + option_parser.error('All arguments are required.') + + temp_dir = tempfile.mkdtemp() + try: + # TODO(gkanwar): Add '-ix' option to filter out useless classes. + build_utils.CheckCallDie(['java', '-cp', options.emma_jar, + 'emma', 'instr', + '-ip', options.input_path, + '-d', temp_dir, + '-out', options.coverage_file, + '-m', 'fullcopy'], suppress_output=True) + + if command == 'instrument_jar': + for jar in os.listdir(os.path.join(temp_dir, 'lib')): + shutil.copy(os.path.join(temp_dir, 'lib', jar), + options.output_path) + else: # 'instrument_classes' + if os.path.isdir(options.output_path): + shutil.rmtree(options.output_path, ignore_errors=True) + shutil.copytree(os.path.join(temp_dir, 'classes'), + options.output_path) + finally: + shutil.rmtree(temp_dir) + + _CreateSourcesFile(options.sources, options.sources_file, options.src_root) + + if options.stamp: + build_utils.Touch(options.stamp) + + return 0 + + +CommandFunctionTuple = collections.namedtuple( + 'CommandFunctionTuple', ['add_options_func', 'run_command_func']) +VALID_COMMANDS = { + 'copy': CommandFunctionTuple(_AddCommonOptions, + _RunCopyCommand), + 'instrument_jar': CommandFunctionTuple(_AddInstrumentOptions, + _RunInstrumentCommand), + 'instrument_classes': CommandFunctionTuple(_AddInstrumentOptions, + _RunInstrumentCommand), +} + + +def main(argv): + option_parser = command_option_parser.CommandOptionParser( + commands_dict=VALID_COMMANDS) + command_option_parser.ParseAndExecute(option_parser) + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/build/android/instr_action.gypi b/build/android/instr_action.gypi new file mode 100644 index 0000000..b22d5ec --- /dev/null +++ b/build/android/instr_action.gypi @@ -0,0 +1,51 @@ +# Copyright 2013 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. + +# This file is meant to be included into an action to provide a rule that +# instruments either java class files, or jars. + +{ + 'variables': { + 'instr_type%': 'jar', + 'input_path%': '', + 'output_path%': '', + 'stamp_path%': '', + 'extra_instr_args': [], + 'emma_jar': '<(android_sdk_root)/tools/lib/emma.jar', + 'conditions': [ + ['emma_instrument != 0', { + 'extra_instr_args': [ + '--coverage-file=<(intermediate_dir)/coverage.em', + '--sources-file=<(intermediate_dir)/emma_sources.txt', + '--sources=<(java_in_dir)/src >(additional_src_dirs) >(generated_src_dirs)', + '--src-root=<(DEPTH)', + '--emma-jar=<(emma_jar)', + ], + 'conditions': [ + ['instr_type == "jar"', { + 'instr_action': 'instrument_jar', + }, { + 'instr_action': 'instrument_classes', + }] + ], + }, { + 'instr_action': 'copy', + 'extra_instr_args': [], + }] + ] + }, + 'inputs': [ + '<(DEPTH)/build/android/gyp/emma_instr.py', + '<(DEPTH)/build/android/gyp/util/build_utils.py', + '<(DEPTH)/build/android/pylib/utils/command_option_parser.py', + ], + 'action': [ + 'python', '<(DEPTH)/build/android/gyp/emma_instr.py', + '<(instr_action)', + '--input-path=<(input_path)', + '--output-path=<(output_path)', + '--stamp=<(stamp_path)', + '<@(extra_instr_args)', + ] +} diff --git a/build/common.gypi b/build/common.gypi index 0e0efda..e70eaac 100644 --- a/build/common.gypi +++ b/build/common.gypi @@ -924,6 +924,10 @@ # Currently ignored on Windows. 'coverage%': 0, + # Set to 1 to enable java code coverage. Instruments classes during build + # to produce .ec files during runtime. + 'emma_coverage%': 0, + # Set to 1 to force Visual C++ to use legacy debug information format /Z7. # This is useful for parallel compilation tools which can't support /Zi. # Only used on Windows. diff --git a/build/java.gypi b/build/java.gypi index 5318e2a..95858ee 100644 --- a/build/java.gypi +++ b/build/java.gypi @@ -55,8 +55,11 @@ 'additional_src_dirs': [], 'javac_includes': [], 'jar_name': '<(_target_name).jar', - 'jar_path': '<(PRODUCT_DIR)/lib.java/<(jar_name)', + 'jar_dir': '<(PRODUCT_DIR)/lib.java', + 'jar_path': '<(intermediate_dir)/<(jar_name)', + 'jar_final_path': '<(jar_dir)/<(jar_name)', 'jar_excluded_classes': [ '*/R.class', '*/R##*.class' ], + 'instr_stamp': '<(intermediate_dir)/instr.stamp', 'additional_input_paths': [], 'dex_path': '<(PRODUCT_DIR)/lib.java/<(_target_name).dex.jar', 'generated_src_dirs': ['>@(generated_R_dirs)'], @@ -80,17 +83,24 @@ ['proguard_preprocess == 1', { 'javac_jar_path': '<(intermediate_dir)/<(_target_name).pre.jar' }, { - 'javac_jar_path': '<(PRODUCT_DIR)/lib.java/<(jar_name)' + 'javac_jar_path': '<(jar_path)' }], ], }, 'javac_jar_path': '<(javac_jar_path)', + 'conditions': [ + ['chromium_code != 0 and emma_coverage != 0', { + 'emma_instrument': 1, + }, { + 'emma_instrument': 0, + }], + ], }, # This all_dependent_settings is used for java targets only. This will add the # jar path to the classpath of dependent java targets. 'all_dependent_settings': { 'variables': { - 'input_jars_paths': ['<(jar_path)'], + 'input_jars_paths': ['<(jar_final_path)'], 'library_dexed_jars_paths': ['<(dex_path)'], }, }, @@ -320,21 +330,38 @@ ] }, { + 'action_name': 'instr_jar_<(_target_name)', + 'message': 'Instrumenting <(_target_name) jar', + 'variables': { + 'input_path': '<(jar_path)', + 'output_path': '<(jar_final_path)', + 'stamp_path': '<(instr_stamp)', + 'instr_type': 'jar', + }, + 'outputs': [ + '<(jar_final_path)', + ], + 'inputs': [ + '<(jar_path)', + ], + 'includes': [ 'android/instr_action.gypi' ], + }, + { 'action_name': 'jar_toc_<(_target_name)', 'message': 'Creating <(_target_name) jar.TOC', 'inputs': [ '<(DEPTH)/build/android/gyp/util/build_utils.py', '<(DEPTH)/build/android/gyp/util/md5_check.py', '<(DEPTH)/build/android/gyp/jar_toc.py', - '<(jar_path)', + '<(jar_final_path)', ], 'outputs': [ - '<(jar_path).TOC', + '<(jar_final_path).TOC', ], 'action': [ 'python', '<(DEPTH)/build/android/gyp/jar_toc.py', - '--jar-path=<(jar_path)', - '--toc-path=<(jar_path).TOC', + '--jar-path=<(jar_final_path)', + '--toc-path=<(jar_final_path).TOC', # TODO(newt): remove this once http://crbug.com/177552 is fixed in ninja. '--ignore=>!(echo \'>(_inputs)\' | md5sum)', @@ -343,7 +370,12 @@ { 'action_name': 'dex_<(_target_name)', 'variables': { - 'dex_input_paths': [ '<(jar_path)' ], + 'conditions': [ + ['emma_instrument != 0', { + 'dex_no_locals': 1, + }], + ], + 'dex_input_paths': [ '<(jar_final_path)' ], 'output_path': '<(dex_path)', }, 'includes': [ 'android/dex_action.gypi' ], diff --git a/build/java_apk.gypi b/build/java_apk.gypi index 0e550a0..1648481 100644 --- a/build/java_apk.gypi +++ b/build/java_apk.gypi @@ -87,15 +87,18 @@ 'native_libraries_template_data_file': '<(native_libraries_template_data_dir)/native_libraries_array.h', 'native_libraries_template_data_stamp': '<(intermediate_dir)/native_libraries_template_data.stamp', 'compile_stamp': '<(intermediate_dir)/compile.stamp', + 'instr_stamp': '<(intermediate_dir)/instr.stamp', 'jar_stamp': '<(intermediate_dir)/jar.stamp', 'obfuscate_stamp': '<(intermediate_dir)/obfuscate.stamp', 'strip_stamp': '<(intermediate_dir)/strip.stamp', 'classes_dir': '<(intermediate_dir)/classes', + 'classes_final_dir': '<(intermediate_dir)/classes_instr', 'javac_includes': [], 'jar_excluded_classes': [], 'jar_path': '<(PRODUCT_DIR)/lib.java/<(jar_name)', 'obfuscated_jar_path': '<(intermediate_dir)/obfuscated.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', 'push_stamp': '<(intermediate_dir)/push.stamp', 'link_stamp': '<(intermediate_dir)/link.stamp', @@ -128,6 +131,7 @@ ], }, 'native_lib_target%': '', + 'emma_instrument': '<(emma_coverage)', 'apk_package_native_libs_dir': '<(apk_package_native_libs_dir)', 'unsigned_standalone_apk_path': '<(unsigned_standalone_apk_path)', }, @@ -466,20 +470,37 @@ ], }, { + 'action_name': 'instr_classes_<(_target_name)', + 'message': 'Instrumenting <(_target_name) classes', + 'variables': { + 'input_path': '<(classes_dir)', + 'output_path': '<(classes_final_dir)', + 'stamp_path': '<(instr_stamp)', + 'instr_type': 'classes', + }, + 'outputs': [ + '<(instr_stamp)', + ], + 'inputs': [ + '<(compile_stamp)', + ], + 'includes': [ 'android/instr_action.gypi' ], + }, + { 'action_name': 'jar_<(_target_name)', 'message': 'Creating <(_target_name) jar', 'inputs': [ + '<(instr_stamp)', '<(DEPTH)/build/android/gyp/util/build_utils.py', '<(DEPTH)/build/android/gyp/util/md5_check.py', '<(DEPTH)/build/android/gyp/jar.py', - '<(compile_stamp)', ], 'outputs': [ '<(jar_stamp)', ], 'action': [ 'python', '<(DEPTH)/build/android/gyp/jar.py', - '--classes-dir=<(classes_dir)', + '--classes-dir=<(classes_final_dir)', '--jar-path=<(jar_path)', '--excluded-classes=<(jar_excluded_classes)', '--stamp=<(jar_stamp)', @@ -496,7 +517,7 @@ '<(DEPTH)/build/android/ant/create-test-jar.js', '<(DEPTH)/build/android/gyp/util/build_utils.py', '<(DEPTH)/build/android/gyp/ant.py', - '<(compile_stamp)', + '<(instr_stamp)', '>@(proguard_flags_paths)', ], 'outputs': [ @@ -542,10 +563,14 @@ 'input_paths': [ '<(obfuscate_stamp)' ], 'proguard_enabled_input_path': '<(obfuscated_jar_path)', }], + ['emma_instrument != 0', { + 'dex_input_paths': [ '<(emma_device_jar)' ], + 'dex_no_locals': 1, + }], ], - 'input_paths': [ '<(compile_stamp)' ], + 'input_paths': [ '<(instr_stamp)' ], 'dex_input_paths': [ '>@(library_dexed_jars_paths)' ], - 'dex_generated_input_dirs': [ '<(classes_dir)' ], + 'dex_generated_input_dirs': [ '<(classes_final_dir)' ], 'output_path': '<(dex_path)', }, 'includes': [ 'android/dex_action.gypi' ], @@ -630,6 +655,8 @@ '-DOUT_DIR=<(intermediate_dir)', '-DSOURCE_DIR=<(source_dir)', '-DUNSIGNED_APK_PATH=<(unsigned_apk_path)', + '-DEMMA_INSTRUMENT=<(emma_instrument)', + '-DEMMA_DEVICE_JAR=<(emma_device_jar)', '-Dbasedir=.', '-buildfile', |