Home | History | Annotate | Download | only in sizeviewer
      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 
      5 import json
      6 import os
      7 import string
      8 import subprocess
      9 import sys
     10 
     11 
     12 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
     13 
     14 
     15 def Run(*args):
     16   with open(os.devnull, 'w') as null:
     17     subprocess.check_call(args, stdout=null, stderr=null)
     18 
     19 
     20 def FindNode(node, component):
     21   for child in node['children']:
     22     if child['name'] == component:
     23       return child
     24   return None
     25 
     26 
     27 def 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 
     42 def 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 
     94 if __name__ == '__main__':
     95   sys.exit(main())
     96