Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2013 The Chromium Authors. All rights reserved. | 3 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Instruments classes and jar files. | 7 """Instruments classes and jar files. |
| 8 | 8 |
| 9 This script corresponds to the 'emma_instr' action in the java build process. | 9 This script corresponds to the 'emma_instr' action in the java build process. |
| 10 Depending on whether emma_instrument is set, the 'emma_instr' action will either | 10 Depending on whether emma_instrument is set, the 'emma_instr' action will either |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 import tempfile | 25 import tempfile |
| 26 | 26 |
| 27 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir)) | 27 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir)) |
| 28 from pylib.utils import command_option_parser | 28 from pylib.utils import command_option_parser |
| 29 | 29 |
| 30 from util import build_utils | 30 from util import build_utils |
| 31 | 31 |
| 32 | 32 |
| 33 def _AddCommonOptions(option_parser): | 33 def _AddCommonOptions(option_parser): |
| 34 """Adds common options to |option_parser|.""" | 34 """Adds common options to |option_parser|.""" |
| 35 build_utils.AddDepfileOption(option_parser) | |
| 35 option_parser.add_option('--input-path', | 36 option_parser.add_option('--input-path', |
| 36 help=('Path to input file(s). Either the classes ' | 37 help=('Path to input file(s). Either the classes ' |
| 37 'directory, or the path to a jar.')) | 38 'directory, or the path to a jar.')) |
| 38 option_parser.add_option('--output-path', | 39 option_parser.add_option('--output-path', |
| 39 help=('Path to output final file(s) to. Either the ' | 40 help=('Path to output final file(s) to. Either the ' |
| 40 'final classes directory, or the directory in ' | 41 'final classes directory, or the directory in ' |
| 41 'which to place the instrumented/copied jar.')) | 42 'which to place the instrumented/copied jar.')) |
| 42 option_parser.add_option('--stamp', help='Path to touch when done.') | 43 option_parser.add_option('--stamp', help='Path to touch when done.') |
| 43 option_parser.add_option('--coverage-file', | 44 option_parser.add_option('--coverage-file', |
| 44 help='File to create with coverage metadata.') | 45 help='File to create with coverage metadata.') |
| 45 option_parser.add_option('--sources-file', | 46 option_parser.add_option('--sources-list-file', |
| 46 help='File to create with the list of sources.') | 47 help='File to create with the list of sources.') |
| 47 | 48 |
| 48 | 49 |
| 49 def _AddInstrumentOptions(option_parser): | 50 def _AddInstrumentOptions(option_parser): |
| 50 """Adds options related to instrumentation to |option_parser|.""" | 51 """Adds options related to instrumentation to |option_parser|.""" |
| 51 _AddCommonOptions(option_parser) | 52 _AddCommonOptions(option_parser) |
| 52 option_parser.add_option('--sources', | 53 option_parser.add_option('--source-dirs', |
| 53 help='Space separated list of sources.') | 54 help='Space separated list of source directories. ' |
| 55 'source-files should not be specified if ' | |
| 56 'source-dirs is specified') | |
| 57 option_parser.add_option('--source-files', | |
| 58 help='Space separated list of source files. ' | |
| 59 'source-dirs should not be specified if ' | |
| 60 'source-files is specified') | |
| 54 option_parser.add_option('--src-root', | 61 option_parser.add_option('--src-root', |
| 55 help='Root of the src repository.') | 62 help='Root of the src repository.') |
| 56 option_parser.add_option('--emma-jar', | 63 option_parser.add_option('--emma-jar', |
| 57 help='Path to emma.jar.') | 64 help='Path to emma.jar.') |
| 58 option_parser.add_option( | 65 option_parser.add_option( |
| 59 '--filter-string', default='', | 66 '--filter-string', default='', |
| 60 help=('Filter string consisting of a list of inclusion/exclusion ' | 67 help=('Filter string consisting of a list of inclusion/exclusion ' |
| 61 'patterns separated with whitespace and/or comma.')) | 68 'patterns separated with whitespace and/or comma.')) |
| 62 | 69 |
| 63 | 70 |
| 64 def _RunCopyCommand(_command, options, _, option_parser): | 71 def _RunCopyCommand(_command, options, _, option_parser): |
| 65 """Copies the jar from input to output locations. | 72 """Copies the jar from input to output locations. |
| 66 | 73 |
| 67 Also removes any old coverage/sources file. | 74 Also removes any old coverage/sources file. |
| 68 | 75 |
| 69 Args: | 76 Args: |
| 70 command: String indicating the command that was received to trigger | 77 command: String indicating the command that was received to trigger |
| 71 this function. | 78 this function. |
| 72 options: optparse options dictionary. | 79 options: optparse options dictionary. |
| 73 args: List of extra args from optparse. | 80 args: List of extra args from optparse. |
| 74 option_parser: optparse.OptionParser object. | 81 option_parser: optparse.OptionParser object. |
| 75 | 82 |
| 76 Returns: | 83 Returns: |
| 77 An exit code. | 84 An exit code. |
| 78 """ | 85 """ |
| 79 if not (options.input_path and options.output_path and | 86 if not (options.input_path and options.output_path and |
| 80 options.coverage_file and options.sources_file): | 87 options.coverage_file and options.sources_list_file): |
| 81 option_parser.error('All arguments are required.') | 88 option_parser.error('All arguments are required.') |
| 82 | 89 |
| 83 coverage_file = os.path.join(os.path.dirname(options.output_path), | 90 if os.path.exists(options.coverage_file): |
| 84 options.coverage_file) | 91 os.remove(options.coverage_file) |
| 85 sources_file = os.path.join(os.path.dirname(options.output_path), | 92 if os.path.exists(options.sources_list_file): |
| 86 options.sources_file) | 93 os.remove(options.sources_list_file) |
| 87 if os.path.exists(coverage_file): | |
| 88 os.remove(coverage_file) | |
| 89 if os.path.exists(sources_file): | |
| 90 os.remove(sources_file) | |
| 91 | 94 |
| 92 shutil.copy(options.input_path, options.output_path) | 95 shutil.copy(options.input_path, options.output_path) |
| 93 | 96 |
| 94 if options.stamp: | 97 if options.stamp: |
| 95 build_utils.Touch(options.stamp) | 98 build_utils.Touch(options.stamp) |
| 96 | 99 |
| 100 if options.depfile: | |
| 101 build_utils.WriteDepfile(options.depfile, | |
| 102 build_utils.GetPythonDependencies()) | |
| 97 | 103 |
| 98 def _CreateSourcesFile(sources_string, sources_file, src_root): | 104 |
| 99 """Adds all normalized source directories to |sources_file|. | 105 def _GetSourceDirsFromSourceFiles(source_files_string): |
| 106 """Returns list of directories for the files in |source_files_string|. | |
| 100 | 107 |
| 101 Args: | 108 Args: |
| 102 sources_string: String generated from gyp containing the list of sources. | 109 source_files_string: String generated from GN or GYP containing the list |
| 103 sources_file: File into which to write the JSON list of sources. | 110 of source files. |
| 111 | |
| 112 Returns: | |
| 113 List of source directories. | |
| 114 """ | |
| 115 source_files = build_utils.ParseGypList(source_files_string) | |
| 116 source_dirs = set() | |
|
agrieve
2015/11/18 15:30:46
nit: More concise: return list(set(os.path.dirname
pkotwicz
2015/11/18 15:59:28
It might be because I am relatively new to Python,
agrieve
2015/11/18 16:06:18
In general, List comprehensions are preferred when
pkotwicz
2015/11/18 17:03:02
According to the Google style guide, "List compreh
| |
| 117 for source_file in source_files: | |
| 118 source_dirs.add(os.path.dirname(source_file)) | |
| 119 return list(source_dirs) | |
| 120 | |
| 121 | |
| 122 def _CreateSourcesListFile(source_dirs, sources_list_file, src_root): | |
| 123 """Adds all normalized source directories to |sources_list_file|. | |
| 124 | |
| 125 Args: | |
| 126 source_dirs: List of source directories. | |
| 127 sources_list_file: File into which to write the JSON list of sources. | |
| 104 src_root: Root which sources added to the file should be relative to. | 128 src_root: Root which sources added to the file should be relative to. |
| 105 | 129 |
| 106 Returns: | 130 Returns: |
| 107 An exit code. | 131 An exit code. |
| 108 """ | 132 """ |
| 109 src_root = os.path.abspath(src_root) | 133 src_root = os.path.abspath(src_root) |
| 110 sources = build_utils.ParseGypList(sources_string) | |
| 111 relative_sources = [] | 134 relative_sources = [] |
| 112 for s in sources: | 135 for s in source_dirs: |
| 113 abs_source = os.path.abspath(s) | 136 abs_source = os.path.abspath(s) |
| 114 if abs_source[:len(src_root)] != src_root: | 137 if abs_source[:len(src_root)] != src_root: |
| 115 print ('Error: found source directory not under repository root: %s %s' | 138 print ('Error: found source directory not under repository root: %s %s' |
| 116 % (abs_source, src_root)) | 139 % (abs_source, src_root)) |
| 117 return 1 | 140 return 1 |
| 118 rel_source = os.path.relpath(abs_source, src_root) | 141 rel_source = os.path.relpath(abs_source, src_root) |
| 119 | 142 |
| 120 relative_sources.append(rel_source) | 143 relative_sources.append(rel_source) |
| 121 | 144 |
| 122 with open(sources_file, 'w') as f: | 145 with open(sources_list_file, 'w') as f: |
| 123 json.dump(relative_sources, f) | 146 json.dump(relative_sources, f) |
| 124 | 147 |
| 125 | 148 |
| 126 def _RunInstrumentCommand(_command, options, _, option_parser): | 149 def _RunInstrumentCommand(_command, options, _, option_parser): |
| 127 """Instruments jar files using EMMA. | 150 """Instruments jar files using EMMA. |
| 128 | 151 |
| 129 Args: | 152 Args: |
| 130 command: String indicating the command that was received to trigger | 153 command: String indicating the command that was received to trigger |
| 131 this function. | 154 this function. |
| 132 options: optparse options dictionary. | 155 options: optparse options dictionary. |
| 133 args: List of extra args from optparse. | 156 args: List of extra args from optparse. |
| 134 option_parser: optparse.OptionParser object. | 157 option_parser: optparse.OptionParser object. |
| 135 | 158 |
| 136 Returns: | 159 Returns: |
| 137 An exit code. | 160 An exit code. |
| 138 """ | 161 """ |
| 139 if not (options.input_path and options.output_path and | 162 if not (options.input_path and options.output_path and |
| 140 options.coverage_file and options.sources_file and options.sources and | 163 options.coverage_file and options.sources_list_file and |
| 164 (options.source_files or options.source_dirs) and | |
| 141 options.src_root and options.emma_jar): | 165 options.src_root and options.emma_jar): |
| 142 option_parser.error('All arguments are required.') | 166 option_parser.error('All arguments are required.') |
| 143 | 167 |
| 144 coverage_file = os.path.join(os.path.dirname(options.output_path), | 168 if os.path.exists(options.coverage_file): |
| 145 options.coverage_file) | 169 os.remove(options.coverage_file) |
| 146 sources_file = os.path.join(os.path.dirname(options.output_path), | |
| 147 options.sources_file) | |
| 148 if os.path.exists(coverage_file): | |
| 149 os.remove(coverage_file) | |
| 150 temp_dir = tempfile.mkdtemp() | 170 temp_dir = tempfile.mkdtemp() |
| 151 try: | 171 try: |
| 152 cmd = ['java', '-cp', options.emma_jar, | 172 cmd = ['java', '-cp', options.emma_jar, |
| 153 'emma', 'instr', | 173 'emma', 'instr', |
| 154 '-ip', options.input_path, | 174 '-ip', options.input_path, |
| 155 '-ix', options.filter_string, | 175 '-ix', options.filter_string, |
| 156 '-d', temp_dir, | 176 '-d', temp_dir, |
| 157 '-out', coverage_file, | 177 '-out', options.coverage_file, |
| 158 '-m', 'fullcopy'] | 178 '-m', 'fullcopy'] |
| 159 build_utils.CheckOutput(cmd) | 179 build_utils.CheckOutput(cmd) |
| 160 | 180 |
| 161 for jar in os.listdir(os.path.join(temp_dir, 'lib')): | 181 temp_jar_dir = os.path.join(temp_dir, 'lib') |
| 162 shutil.copy(os.path.join(temp_dir, 'lib', jar), | 182 jars = os.listdir(temp_jar_dir) |
| 163 options.output_path) | 183 if len(jars) != 1: |
| 184 print('Error: multiple output files in: %s' % (temp_jar_dir)) | |
|
agrieve
2015/11/18 15:30:46
you should raise an exception rather than explicit
pkotwicz
2015/11/18 15:59:28
This way of handling exceptions is consistent with
| |
| 185 return 1 | |
| 186 | |
| 187 shutil.copy(os.path.join(temp_jar_dir, jars[0]), options.output_path) | |
| 164 finally: | 188 finally: |
| 165 shutil.rmtree(temp_dir) | 189 shutil.rmtree(temp_dir) |
| 166 | 190 |
| 167 _CreateSourcesFile(options.sources, sources_file, options.src_root) | 191 source_dirs = [] |
|
agrieve
2015/11/18 15:30:46
no need to initialize since it's re-assigned in bo
| |
| 192 if options.source_dirs: | |
| 193 source_dirs = build_utils.ParseGypList(options.source_dirs) | |
| 194 else: | |
| 195 source_dirs = _GetSourceDirsFromSourceFiles(options.source_files) | |
| 196 _CreateSourcesListFile(source_dirs, options.sources_list_file, | |
| 197 options.src_root) | |
|
agrieve
2015/11/18 15:30:46
nit: indent is off
pkotwicz
2015/11/18 15:59:28
I am confused. There is an '_' before the 'C" in _
| |
| 168 | 198 |
| 169 if options.stamp: | 199 if options.stamp: |
| 170 build_utils.Touch(options.stamp) | 200 build_utils.Touch(options.stamp) |
| 171 | 201 |
| 202 if options.depfile: | |
| 203 build_utils.WriteDepfile(options.depfile, | |
| 204 build_utils.GetPythonDependencies()) | |
| 205 | |
| 172 return 0 | 206 return 0 |
| 173 | 207 |
| 174 | 208 |
| 175 CommandFunctionTuple = collections.namedtuple( | 209 CommandFunctionTuple = collections.namedtuple( |
| 176 'CommandFunctionTuple', ['add_options_func', 'run_command_func']) | 210 'CommandFunctionTuple', ['add_options_func', 'run_command_func']) |
| 177 VALID_COMMANDS = { | 211 VALID_COMMANDS = { |
| 178 'copy': CommandFunctionTuple(_AddCommonOptions, | 212 'copy': CommandFunctionTuple(_AddCommonOptions, |
| 179 _RunCopyCommand), | 213 _RunCopyCommand), |
| 180 'instrument_jar': CommandFunctionTuple(_AddInstrumentOptions, | 214 'instrument_jar': CommandFunctionTuple(_AddInstrumentOptions, |
| 181 _RunInstrumentCommand), | 215 _RunInstrumentCommand), |
| 182 } | 216 } |
| 183 | 217 |
| 184 | 218 |
| 185 def main(): | 219 def main(): |
| 186 option_parser = command_option_parser.CommandOptionParser( | 220 option_parser = command_option_parser.CommandOptionParser( |
| 187 commands_dict=VALID_COMMANDS) | 221 commands_dict=VALID_COMMANDS) |
| 188 command_option_parser.ParseAndExecute(option_parser) | 222 command_option_parser.ParseAndExecute(option_parser) |
| 189 | 223 |
| 190 | 224 |
| 191 if __name__ == '__main__': | 225 if __name__ == '__main__': |
| 192 sys.exit(main()) | 226 sys.exit(main()) |
| OLD | NEW |