blob: 56e3156550aa4c07bac6e87445a0d82f472366c5 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001#!/usr/bin/env python
2# Copyright 2015 the V8 project 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
6"""
7Script to print potentially missing source dependencies based on the actual
8.h and .cc files in the source tree and which files are included in the gyp
9and gn files. The latter inclusion is overapproximated.
10
11TODO(machenbach): Gyp files in src will point to source files in src without a
12src/ prefix. For simplicity, all paths relative to src are stripped. But this
13tool won't be accurate for other sources in other directories (e.g. cctest).
14"""
15
16import itertools
17import re
18import os
19
20
21V8_BASE = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
22V8_SRC_BASE = os.path.join(V8_BASE, 'src')
23V8_INCLUDE_BASE = os.path.join(V8_BASE, 'include')
24
25GYP_FILES = [
26 os.path.join(V8_BASE, 'src', 'd8.gyp'),
Ben Murdochc5610432016-08-08 18:44:38 +010027 os.path.join(V8_BASE, 'src', 'v8.gyp'),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028 os.path.join(V8_BASE, 'src', 'third_party', 'vtune', 'v8vtune.gyp'),
29 os.path.join(V8_BASE, 'test', 'cctest', 'cctest.gyp'),
30 os.path.join(V8_BASE, 'test', 'unittests', 'unittests.gyp'),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000031 os.path.join(V8_BASE, 'tools', 'parser-shell.gyp'),
32]
33
34
35def path_no_prefix(path):
36 if path.startswith('../'):
37 return path_no_prefix(path[3:])
38 elif path.startswith('src/'):
39 return path_no_prefix(path[4:])
40 else:
41 return path
42
43
44def isources(directory):
45 for root, dirs, files in os.walk(directory):
46 for f in files:
47 if not (f.endswith('.h') or f.endswith('.cc')):
48 continue
49 yield path_no_prefix(os.path.relpath(os.path.join(root, f), V8_BASE))
50
51
52def iflatten(obj):
53 if isinstance(obj, dict):
54 for value in obj.values():
55 for i in iflatten(value):
56 yield i
57 elif isinstance(obj, list):
58 for value in obj:
59 for i in iflatten(value):
60 yield i
61 elif isinstance(obj, basestring):
62 yield path_no_prefix(obj)
63
64
65def iflatten_gyp_file(gyp_file):
66 """Overaproximates all values in the gyp file.
67
68 Iterates over all string values recursively. Removes '../' path prefixes.
69 """
70 with open(gyp_file) as f:
71 return iflatten(eval(f.read()))
72
73
74def iflatten_gn_file(gn_file):
75 """Overaproximates all values in the gn file.
76
77 Iterates over all double quoted strings.
78 """
79 with open(gn_file) as f:
80 for line in f.read().splitlines():
81 match = re.match(r'.*"([^"]*)".*', line)
82 if match:
83 yield path_no_prefix(match.group(1))
84
85
86def icheck_values(values, *source_dirs):
87 for source_file in itertools.chain(
88 *[isources(source_dir) for source_dir in source_dirs]
89 ):
90 if source_file not in values:
91 yield source_file
92
93
94gyp_values = set(itertools.chain(
95 *[iflatten_gyp_file(gyp_file) for gyp_file in GYP_FILES]
96 ))
97
98print "----------- Files not in gyp: ------------"
99for i in sorted(icheck_values(gyp_values, V8_SRC_BASE, V8_INCLUDE_BASE)):
100 print i
101
102gn_values = set(iflatten_gn_file(os.path.join(V8_BASE, 'BUILD.gn')))
103
104print "\n----------- Files not in gn: -------------"
105for i in sorted(icheck_values(gn_values, V8_SRC_BASE, V8_INCLUDE_BASE)):
106 print i