diff options
Diffstat (limited to 'tools/v8_gypfiles/broken/verify_source_deps.py')
-rw-r--r-- | tools/v8_gypfiles/broken/verify_source_deps.py | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/tools/v8_gypfiles/broken/verify_source_deps.py b/tools/v8_gypfiles/broken/verify_source_deps.py new file mode 100644 index 0000000000..396b19e901 --- /dev/null +++ b/tools/v8_gypfiles/broken/verify_source_deps.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# Copyright 2015 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Script to print potentially missing source dependencies based on the actual +.h and .cc files in the source tree and which files are included in the gyp +and gn files. The latter inclusion is overapproximated. + +TODO(machenbach): If two source files with the same name exist, but only one +is referenced from a gyp/gn file, we won't necessarily detect it. +""" + +import itertools +import re +import os +import subprocess +import sys + + +V8_BASE = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + +GYP_FILES = [ + os.path.join(V8_BASE, 'gypfiles', 'd8.gyp'), + os.path.join(V8_BASE, 'gypfiles', 'v8.gyp'), + os.path.join(V8_BASE, 'gypfiles', 'inspector.gypi'), + os.path.join(V8_BASE, 'gypfiles', 'v8vtune.gyp'), + os.path.join(V8_BASE, 'gypfiles', 'samples.gyp'), + os.path.join(V8_BASE, 'gypfiles', 'mkgrokdump.gyp'), + os.path.join(V8_BASE, 'gypfiles', 'parser-shell.gyp'), +] + +ALL_GYP_PREFIXES = [ + '..', + 'common', + os.path.join('src', 'third_party', 'vtune'), + 'src', + 'samples', + 'testing', + 'tools', + os.path.join('test', 'common'), + os.path.join('test', 'inspector'), + os.path.join('test', 'mkgrokdump'), +] + +GYP_UNSUPPORTED_FEATURES = [ + 'gcmole', + 'setup-isolate-deserialize.cc', + 'v8-version.h' +] + +GN_FILES = [ + os.path.join(V8_BASE, 'BUILD.gn'), + os.path.join(V8_BASE, 'src', 'inspector', 'BUILD.gn'), + os.path.join(V8_BASE, 'test', 'inspector', 'BUILD.gn'), + os.path.join(V8_BASE, 'test', 'mkgrokdump', 'BUILD.gn'), + os.path.join(V8_BASE, 'tools', 'BUILD.gn'), +] + +GN_UNSUPPORTED_FEATURES = [ + 'aix', + 'cygwin', + 'freebsd', + 'gcmole', + 'openbsd', + 'ppc', + 'qnx', + 'solaris', + 'vtune', + 'v8-version.h', +] + +ALL_GN_PREFIXES = [ + '..', + os.path.join('src', 'inspector'), + 'src', + 'testing', + os.path.join('test', 'inspector'), + os.path.join('test', 'mkgrokdump'), +] + +def pathsplit(path): + return re.split('[/\\\\]', path) + +def path_no_prefix(path, prefixes): + for prefix in prefixes: + if path.startswith(prefix + os.sep): + return path_no_prefix(path[len(prefix) + 1:], prefixes) + return path + + +def isources(prefixes): + cmd = ['git', 'ls-tree', '-r', 'HEAD', '--full-name', '--name-only'] + for f in subprocess.check_output(cmd, universal_newlines=True).split('\n'): + if not (f.endswith('.h') or f.endswith('.cc')): + continue + yield path_no_prefix(os.path.join(*pathsplit(f)), prefixes) + + +def iflatten(obj): + if isinstance(obj, dict): + for value in obj.values(): + for i in iflatten(value): + yield i + elif isinstance(obj, list): + for value in obj: + for i in iflatten(value): + yield i + elif isinstance(obj, basestring): + yield path_no_prefix(os.path.join(*pathsplit(obj)), ALL_GYP_PREFIXES) + + +def iflatten_gyp_file(gyp_file): + """Overaproximates all values in the gyp file. + + Iterates over all string values recursively. Removes '../' path prefixes. + """ + with open(gyp_file) as f: + return iflatten(eval(f.read())) + + +def iflatten_gn_file(gn_file): + """Overaproximates all values in the gn file. + + Iterates over all double quoted strings. + """ + with open(gn_file) as f: + for line in f.read().splitlines(): + match = re.match(r'.*"([^"]*)".*', line) + if match: + yield path_no_prefix( + os.path.join(*pathsplit(match.group(1))), ALL_GN_PREFIXES) + + +def icheck_values(values, prefixes): + for source_file in isources(prefixes): + if source_file not in values: + yield source_file + + +def missing_gyp_files(): + gyp_values = set(itertools.chain( + *[iflatten_gyp_file(gyp_file) for gyp_file in GYP_FILES] + )) + gyp_files = sorted(icheck_values(gyp_values, ALL_GYP_PREFIXES)) + return filter( + lambda x: not any(i in x for i in GYP_UNSUPPORTED_FEATURES), gyp_files) + + +def missing_gn_files(): + gn_values = set(itertools.chain( + *[iflatten_gn_file(gn_file) for gn_file in GN_FILES] + )) + + gn_files = sorted(icheck_values(gn_values, ALL_GN_PREFIXES)) + return filter( + lambda x: not any(i in x for i in GN_UNSUPPORTED_FEATURES), gn_files) + + +def main(): + print "----------- Files not in gyp: ------------" + for i in missing_gyp_files(): + print i + + print "\n----------- Files not in gn: -------------" + for i in missing_gn_files(): + print i + return 0 + +if '__main__' == __name__: + sys.exit(main()) |