include_tracer.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #!/usr/bin/env python
  2. # Copyright (c) 2011 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. # based on an almost identical script by: jyrki@google.com (Jyrki Alakuijala)
  6. """Prints out include dependencies in chrome.
  7. Since it ignores defines, it gives just a rough estimation of file size.
  8. Usage:
  9. tools/include_tracer.py -Iout/Default/gen chrome/browser/ui/browser.h
  10. """
  11. from __future__ import print_function
  12. import argparse
  13. import os
  14. import re
  15. import sys
  16. # Created by copying the command line for prerender_browsertest.cc, replacing
  17. # spaces with newlines, and dropping everything except -F and -I switches.
  18. # TODO(port): Add windows, linux directories.
  19. INCLUDE_PATHS = [
  20. '',
  21. 'gpu',
  22. 'skia/config',
  23. 'skia/ext',
  24. 'testing/gmock/include',
  25. 'testing/gtest/include',
  26. 'third_party/google_toolbox_for_mac/src',
  27. 'third_party/icu/public/common',
  28. 'third_party/icu/public/i18n',
  29. 'third_party/protobuf',
  30. 'third_party/protobuf/src',
  31. 'third_party/skia/gpu/include',
  32. 'third_party/skia/include/config',
  33. 'third_party/skia/include/core',
  34. 'third_party/skia/include/effects',
  35. 'third_party/skia/include/gpu',
  36. 'third_party/skia/include/pdf',
  37. 'third_party/skia/include/ports',
  38. 'v8/include',
  39. ]
  40. def Walk(include_dirs, seen, filename, parent, indent):
  41. """Returns the size of |filename| plus the size of all files included by
  42. |filename| and prints the include tree of |filename| to stdout. Every file
  43. is visited at most once.
  44. """
  45. total_bytes = 0
  46. # .proto(devel) filename translation
  47. if filename.endswith('.pb.h'):
  48. basename = filename[:-5]
  49. if os.path.exists(basename + '.proto'):
  50. filename = basename + '.proto'
  51. else:
  52. print('could not find ', filename)
  53. # Show and count files only once.
  54. if filename in seen:
  55. return total_bytes
  56. seen.add(filename)
  57. # Display the paths.
  58. print(' ' * indent + filename)
  59. # Skip system includes.
  60. if filename[0] == '<':
  61. return total_bytes
  62. # Find file in all include paths.
  63. resolved_filename = filename
  64. for root in INCLUDE_PATHS + [os.path.dirname(parent)] + include_dirs:
  65. if os.path.exists(os.path.join(root, filename)):
  66. resolved_filename = os.path.join(root, filename)
  67. break
  68. # Recurse.
  69. if os.path.exists(resolved_filename):
  70. lines = open(resolved_filename).readlines()
  71. else:
  72. print(' ' * (indent + 2) + "-- not found")
  73. lines = []
  74. for line in lines:
  75. line = line.strip()
  76. match = re.match(r'#include\s+(\S+).*', line)
  77. if match:
  78. include = match.group(1)
  79. if include.startswith('"'):
  80. include = include[1:-1]
  81. total_bytes += Walk(
  82. include_dirs, seen, include, resolved_filename, indent + 2)
  83. elif line.startswith('import '):
  84. total_bytes += Walk(
  85. include_dirs, seen, line.split('"')[1], resolved_filename, indent + 2)
  86. return total_bytes + len("".join(lines))
  87. def main():
  88. parser = argparse.ArgumentParser()
  89. parser.add_argument('-I', action='append', dest='include_dirs')
  90. parser.add_argument('source_file')
  91. options = parser.parse_args(sys.argv[1:])
  92. if not options.include_dirs:
  93. options.include_dirs = []
  94. bytes = Walk(options.include_dirs, set(), options.source_file, '', 0)
  95. print()
  96. print(float(bytes) / (1 << 20), "megabytes of chrome source")
  97. if __name__ == '__main__':
  98. sys.exit(main())