Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: tools/isolate/trace_inputs.py

Issue 9704099: Improve trace_inputs.py to output a format easy to convert to gypi. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix exception Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/isolate/isolate.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Runs strace or dtrace on a test and processes the logs to extract the 6 """Runs strace or dtrace on a test and processes the logs to extract the
7 dependencies from the source tree. 7 dependencies from the source tree.
8 8
9 Automatically extracts directories where all the files are used to make the 9 Automatically extracts directories where all the files are used to make the
10 dependencies list more compact. 10 dependencies list more compact.
(...skipping 24 matching lines...) Expand all
35 '/proc', 35 '/proc',
36 '/sys', 36 '/sys',
37 '/tmp', 37 '/tmp',
38 '/usr', 38 '/usr',
39 '/var', 39 '/var',
40 ) 40 )
41 41
42 @staticmethod 42 @staticmethod
43 def gen_trace(cmd, cwd, logname): 43 def gen_trace(cmd, cwd, logname):
44 """Runs strace on an executable.""" 44 """Runs strace on an executable."""
45 silent = not isEnabledFor(logging.DEBUG) 45 silent = not isEnabledFor(logging.INFO)
46 stdout = stderr = None 46 stdout = stderr = None
47 if silent: 47 if silent:
48 stdout = subprocess.PIPE 48 stdout = subprocess.PIPE
49 stderr = subprocess.PIPE 49 stderr = subprocess.PIPE
50 trace_cmd = ['strace', '-f', '-e', 'trace=open', '-o', logname] 50 trace_cmd = ['strace', '-f', '-e', 'trace=open', '-o', logname]
51 cmd = [os.path.normpath(os.path.join(cwd, c)) for c in cmd] 51 cmd = [os.path.normpath(os.path.join(cwd, c)) for c in cmd]
52 p = subprocess.Popen( 52 p = subprocess.Popen(
53 trace_cmd + cmd, cwd=cwd, stdout=stdout, stderr=stderr) 53 trace_cmd + cmd, cwd=cwd, stdout=stdout, stderr=stderr)
54 out, err = p.communicate() 54 out, err = p.communicate()
55 if p.returncode != 0: 55 if p.returncode != 0:
56 print 'Failure: %d' % p.returncode 56 print 'Failure: %d' % p.returncode
57 # pylint: disable=E1103 57 # pylint: disable=E1103
58 print ''.join(out.splitlines(True)[-100:]) 58 if out:
59 print ''.join(err.splitlines(True)[-100:]) 59 print ''.join(out.splitlines(True)[-100:])
60 if err:
61 print ''.join(err.splitlines(True)[-100:])
60 return p.returncode 62 return p.returncode
61 63
62 @staticmethod 64 @staticmethod
63 def parse_log(filename, blacklist): 65 def parse_log(filename, blacklist):
64 """Processes a strace log and returns the files opened and the files that do 66 """Processes a strace log and returns the files opened and the files that do
65 not exist. 67 not exist.
66 68
67 Most of the time, files that do not exist are temporary test files that 69 Most of the time, files that do not exist are temporary test files that
68 should be put in /tmp instead. See http://crbug.com/116251 70 should be put in /tmp instead. See http://crbug.com/116251
69 71
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 ppid, pid, execname, self->arg0, self->arg1, self->arg2, errno); 151 ppid, pid, execname, self->arg0, self->arg1, self->arg2, errno);
150 self->arg0 = 0; 152 self->arg0 = 0;
151 self->arg1 = 0; 153 self->arg1 = 0;
152 self->arg2 = 0; 154 self->arg2 = 0;
153 } 155 }
154 """ 156 """
155 157
156 @classmethod 158 @classmethod
157 def gen_trace(cls, cmd, cwd, logname): 159 def gen_trace(cls, cmd, cwd, logname):
158 """Runs dtrace on an executable.""" 160 """Runs dtrace on an executable."""
159 silent = not isEnabledFor(logging.DEBUG) 161 silent = not isEnabledFor(logging.INFO)
160 print 'Running: %s' % cmd 162 print 'Running: %s' % cmd
161 signal = 'Go!' 163 signal = 'Go!'
162 logging.debug('Our pid: %d' % os.getpid()) 164 logging.debug('Our pid: %d' % os.getpid())
163 165
164 # Part 1: start the child process. 166 # Part 1: start the child process.
165 stdout = stderr = None 167 stdout = stderr = None
166 if silent: 168 if silent:
167 stdout = subprocess.PIPE 169 stdout = subprocess.PIPE
168 stderr = subprocess.PIPE 170 stderr = subprocess.PIPE
169 child_cmd = [ 171 child_cmd = [
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 os.path.join(directory, f) for f in 281 os.path.join(directory, f) for f in
280 os.listdir(os.path.join(root, directory)) 282 os.listdir(os.path.join(root, directory))
281 if not f.endswith(('.svn', '.pyc')) 283 if not f.endswith(('.svn', '.pyc'))
282 ) 284 )
283 if not (actual - files): 285 if not (actual - files):
284 files -= actual 286 files -= actual
285 files.add(directory + '/') 287 files.add(directory + '/')
286 return sorted(files) 288 return sorted(files)
287 289
288 290
289 def trace_inputs(log, cmd, api): 291 def trace_inputs(log, cmd, api, gyp_proj_dir, product_dir):
290 """Tries to load the logs if available. If not, trace the test.""" 292 """Tries to load the logs if available. If not, trace the test."""
293 def print_if(txt):
294 if not gyp_proj_dir:
295 print(txt)
296
291 logname = os.path.join(BASE_DIR, os.path.basename(log)) 297 logname = os.path.join(BASE_DIR, os.path.basename(log))
292 if not os.path.isfile(logname): 298 if not os.path.isfile(logname):
293 print 'Tracing... %s' % cmd 299 print_if('Tracing... %s' % cmd)
294 returncode = api.gen_trace(cmd, ROOT_DIR, logname) 300 returncode = api.gen_trace(cmd, ROOT_DIR, logname)
295 if returncode: 301 if returncode:
296 return returncode 302 return returncode
297 303
298 def blacklist(f): 304 def blacklist(f):
299 """Strips ignored paths.""" 305 """Strips ignored paths."""
300 return f.startswith(api.IGNORED) or f.endswith('.pyc') 306 return f.startswith(api.IGNORED) or f.endswith('.pyc')
301 307
302 print 'Loading traces... %s' % logname 308 print_if('Loading traces... %s' % logname)
303 files, non_existent = api.parse_log(logname, blacklist) 309 files, non_existent = api.parse_log(logname, blacklist)
304 print('Total: %d' % len(files)) 310
305 print('Non existent: %d' % len(non_existent)) 311 print_if('Total: %d' % len(files))
312 print_if('Non existent: %d' % len(non_existent))
306 for f in non_existent: 313 for f in non_existent:
307 print(' %s' % f) 314 print_if(' %s' % f)
308 315
309 expected, unexpected = relevant_files(files, ROOT_DIR + '/') 316 expected, unexpected = relevant_files(files, ROOT_DIR + '/')
310 if unexpected: 317 if unexpected:
311 print('Unexpected: %d' % len(unexpected)) 318 print_if('Unexpected: %d' % len(unexpected))
312 for f in unexpected: 319 for f in unexpected:
313 print(' %s' % f) 320 print_if(' %s' % f)
314 321
315 simplified = extract_directories(expected, ROOT_DIR) 322 simplified = extract_directories(expected, ROOT_DIR)
316 print('Interesting: %d reduced to %d' % (len(expected), len(simplified))) 323 print_if('Interesting: %d reduced to %d' % (len(expected), len(simplified)))
317 for f in simplified: 324 for f in simplified:
318 print(' %s' % f) 325 print_if(' %s' % f)
319 326
327 if gyp_proj_dir:
328 def fix(f):
329 if f.startswith(product_dir):
330 return '<(PRODUCT_DIR)%s' % f[len(product_dir):]
331 elif f.startswith(gyp_proj_dir):
332 return f[len(gyp_proj_dir)+1:]
333 else:
334 return '<(DEPTH)/%s' % f
335 corrected = [fix(f) for f in simplified]
336 files = [f for f in corrected if not f.endswith('/')]
337 dirs = [f for f in corrected if f.endswith('/')]
338 # Constructs the python code manually.
339 print(
340 '{\n'
341 ' \'variables\': {\n'
342 ' \'isolate_files\': [\n') + (
343 ''.join(' \'%s\',\n' % f for f in files)) + (
344 ' ],\n'
345 ' \'isolate_dirs\': [\n') + (
346 ''.join(' \'%s\',\n' % f for f in dirs)) + (
347 ' ],\n'
348 ' },\n'
349 '},')
320 return 0 350 return 0
321 351
322 352
323 def main(): 353 def main():
324 parser = optparse.OptionParser( 354 parser = optparse.OptionParser(
325 usage='%prog <options> [cmd line...]') 355 usage='%prog <options> [cmd line...]')
326 parser.allow_interspersed_args = False 356 parser.allow_interspersed_args = False
327 parser.add_option( 357 parser.add_option(
328 '-v', '--verbose', action='count', default=0, help='Use multiple times') 358 '-v', '--verbose', action='count', default=0, help='Use multiple times')
329 parser.add_option('-l', '--log', help='Log file') 359 parser.add_option('-l', '--log', help='Log file')
360 parser.add_option(
361 '-g', '--gyp',
362 help='When specified, outputs the inputs files in a way compatible for '
363 'gyp processing. Should be set to the relative path containing the '
364 'gyp file, e.g. \'chrome\' or \'net\'')
365 parser.add_option(
366 '-p', '--product-dir', default='out/Release',
367 help='Directory for PRODUCT_DIR')
330 368
331 options, args = parser.parse_args() 369 options, args = parser.parse_args()
332 level = [logging.ERROR, logging.INFO, logging.DEBUG][min(2, options.verbose)] 370 level = [logging.ERROR, logging.INFO, logging.DEBUG][min(2, options.verbose)]
333 logging.basicConfig( 371 logging.basicConfig(
334 level=level, 372 level=level,
335 format='%(levelname)5s %(module)15s(%(lineno)3d):%(message)s') 373 format='%(levelname)5s %(module)15s(%(lineno)3d):%(message)s')
336 374
337 if not args: 375 if not args:
338 parser.error('Must supply a command to run') 376 parser.error('Must supply a command to run')
339 if not options.log: 377 if not options.log:
340 parser.error('Must supply a log file with -l') 378 parser.error('Must supply a log file with -l')
341 379
342 if sys.platform == 'linux2': 380 if sys.platform == 'linux2':
343 api = Strace 381 api = Strace
344 elif sys.platform == 'darwin': 382 elif sys.platform == 'darwin':
345 api = Dtrace 383 api = Dtrace
346 else: 384 else:
347 print >> sys.stderr, 'Unsupported platform' 385 print >> sys.stderr, 'Unsupported platform'
348 return 1 386 return 1
349 387
350 return trace_inputs(options.log, args, api) 388 return trace_inputs(options.log, args, api, options.gyp, options.product_dir)
351 389
352 390
353 if __name__ == '__main__': 391 if __name__ == '__main__':
354 sys.exit(main()) 392 sys.exit(main())
OLDNEW
« no previous file with comments | « tools/isolate/isolate.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698