1# Copyright 2013 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import json 6import os 7import string 8import subprocess 9import sys 10 11 12BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 13 14 15def Run(*args): 16 with open(os.devnull, 'w') as null: 17 subprocess.check_call(args, stdout=null, stderr=null) 18 19 20def FindNode(node, component): 21 for child in node['children']: 22 if child['name'] == component: 23 return child 24 return None 25 26 27def InsertIntoTree(tree, source_name, size): 28 components = source_name.replace(':', '').split('\\') 29 node = tree 30 for index, component in enumerate(components): 31 data = FindNode(node, component) 32 if not data: 33 data = { 'name': component } 34 if index == len(components) - 1: 35 data['size'] = size 36 else: 37 data['children'] = [] 38 node['children'].append(data) 39 node = data 40 41 42def main(): 43 out_dir = os.path.join(BASE_DIR, '..', '..', '..', 'out', 'Release') 44 jsons = [] 45 for dll in ('chrome.dll', 'chrome_child.dll'): 46 dll_path = os.path.normpath(os.path.join(out_dir, dll)) 47 if os.path.exists(dll_path): 48 print 'Tallying %s...' % dll_path 49 json_path = dll_path + '.json' 50 Run(os.path.join(BASE_DIR, 'code_tally.exe'), 51 '--input-image=' + dll_path, 52 '--input-pdb=' + dll_path + '.pdb', 53 '--output-file=' + json_path) 54 jsons.append(json_path) 55 if not jsons: 56 print 'Couldn\'t find binaries, looking in', out_dir 57 return 1 58 59 for json_name in jsons: 60 with open(json_name, 'r') as jsonf: 61 all_data = json.load(jsonf) 62 html_path = os.path.splitext(json_name)[0] + '.html' 63 print 'Generating %s...' % html_path 64 by_source = {} 65 for obj_name, obj_data in all_data['objects'].iteritems(): 66 for symbol, symbol_data in obj_data.iteritems(): 67 size = int(symbol_data['size']) 68 # Sometimes there's symbols with no source file, we just ignore those. 69 if 'contribs' in symbol_data: 70 # There may be more than one file in the list, we just assign to the 71 # first source file that contains the symbol, rather than try to 72 # split or duplicate info. 73 src_index = symbol_data['contribs'][0] 74 source = all_data['sources'][int(src_index)] 75 if source not in by_source: 76 by_source[source] = [] 77 by_source[source].append(size) 78 binary_name = all_data['executable']['name'] 79 data = {} 80 data['name'] = binary_name 81 data['children'] = [] 82 for source, sizes in by_source.iteritems(): 83 InsertIntoTree(data, source, sum(sizes)) 84 with open(html_path, 'w') as f: 85 with open(os.path.join(BASE_DIR, 'template.html'), 'r') as templatef: 86 template = templatef.read() 87 f.write(string.Template(template).substitute( 88 {'data': json.dumps(data, indent=2), 89 'dllname': binary_name + ' ' + all_data['executable']['version']})) 90 91 return 0 92 93 94if __name__ == '__main__': 95 sys.exit(main()) 96