OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import subprocess | 6 import subprocess |
7 import os | 7 import os |
8 import argparse | 8 import argparse |
9 import logging | 9 import logging |
10 | 10 |
11 ROOT_DIR = os.path.abspath(os.path.join(__file__, os.pardir, os.pardir, | 11 ROOT_DIR = os.path.abspath(os.path.join(__file__, os.pardir, os.pardir, |
12 os.pardir)) | 12 os.pardir)) |
13 | 13 |
14 def dependencies(): | 14 # Where to cache GN results (they're expensive to compute). |
15 args = [ | 15 GN_CACHE_PATH = os.path.abspath(os.path.join(ROOT_DIR, 'in_gn.txt')) |
16 'gn', | |
17 'desc', | |
18 os.path.join('out', 'Debug'), | |
19 '//sky/engine/public:blink', | |
20 'deps', '--all' | |
21 ] | |
22 targets = subprocess.check_output(args).splitlines() | |
23 return map(str.strip, targets) | |
24 | 16 |
25 | 17 |
26 def sources(target): | 18 def stripped_lines_from_command(cmd, cwd=None): |
27 print target | 19 lines = subprocess.check_output(cmd, cwd=cwd).splitlines() |
28 args = [ | 20 return map(str.strip, lines) |
29 'gn', | 21 |
30 'desc', | 22 |
23 def gn_desc(*args): | |
24 # GN doesn't understand absolute paths yet, so use a relative BUILD_DIR | |
25 # and pass ROOT_DIR as the CWD. | |
26 cmd = [ | |
27 'gn', 'desc', | |
brettw
2014/10/24 19:58:47
For "desc" you will have to specify a build direct
eseidel
2014/10/24 20:42:59
Great. Will do in the next patch! Thanks!
| |
28 # Hard-coding Debug for now: | |
31 os.path.join('out', 'Debug'), | 29 os.path.join('out', 'Debug'), |
32 target, | 30 ] + list(args) |
33 'sources' | 31 return stripped_lines_from_command(cmd, cwd=ROOT_DIR) |
34 ] | 32 |
35 sources = subprocess.check_output(args).splitlines() | 33 |
36 return map(lambda s: s[2:], map(str.strip, sources)) | 34 def targets_under(target): |
35 targets = gn_desc(target, 'deps', '--all') | |
36 return filter(lambda s: s.startswith(target), targets) | |
37 | |
38 | |
39 def used_files(target): | |
40 logging.info(target) | |
41 sources = map(lambda s: s[2:], gn_desc(target, 'sources')) | |
42 inputs = map(lambda s: s[2:], gn_desc(target, 'inputs')) | |
43 return sources + inputs | |
37 | 44 |
38 | 45 |
39 def find_on_disk(path): | 46 def find_on_disk(path): |
40 # FIXME: Use os.walk and do fancier ignoring. | 47 # FIXME: Use os.walk and do fancier ignoring. |
41 find_output = subprocess.check_output(['find', path, '-type', 'f']) | 48 return stripped_lines_from_command(['find', path, '-type', 'f']) |
42 return map(str.strip, find_output.splitlines()) | |
43 | 49 |
44 | 50 |
45 def main(): | 51 def main(): |
46 logging.basicConfig() | 52 logging.basicConfig(level=logging.INFO) |
47 | 53 |
48 os.chdir(ROOT_DIR) | 54 if os.path.exists(GN_CACHE_PATH): |
49 if os.path.exists('in_gn.txt'): | 55 logging.info('Using cached GN list: %s' % GN_CACHE_PATH) |
50 logging.info('Using cached GN list: %s' % os.path.abspath('in_gn.txt')) | 56 in_gn = set(map(str.strip, open(GN_CACHE_PATH).readlines())) |
51 in_gn = set(map(str.strip, open('in_gn.txt').readlines())) | |
52 else: | 57 else: |
53 logging.info('No gn cache found, rebuilding: %s' % os.abspath('in_gn.txt ')) | 58 logging.info('No gn cache found, rebuilding: %s' % GN_CACHE_PATH) |
54 targets = filter(lambda s: '//sky' in s, dependencies()) | 59 in_gn = set(sum(map(used_files, targets_under('//sky')), [])) |
55 in_gn = set(sum(map(sources, targets), [])) | 60 open(GN_CACHE_PATH, 'w+').write('\n'.join(in_gn)) |
56 open('in_gn.txt', 'w+').write('\n'.join(in_gn)) | |
57 | 61 |
58 on_disk = set(find_on_disk('sky/engine')) | 62 on_disk = set(find_on_disk('sky/engine')) |
59 # Ignore web/tests and bindings/tests | 63 # Ignore web/tests and bindings/tests |
60 on_disk = set(filter(lambda p: '/tests/' not in p, on_disk)) | 64 on_disk = set(filter(lambda p: '/tests/' not in p, on_disk)) |
61 | 65 |
62 missing_from_gn = sorted(on_disk - in_gn) | 66 missing_from_gn = sorted(on_disk - in_gn) |
63 | 67 |
64 IGNORED_EXTENSIONS = [ | 68 IGNORED_EXTENSIONS = [ |
65 '.py', # Probably some to remove, probably some to teach gn about. | 69 '.py', # Probably some to remove, probably some to teach gn about. |
66 # Python files not being known to gn can cause flaky builds too! | 70 # Python files not being known to gn can cause flaky builds too! |
67 '.pyc', | 71 '.pyc', |
68 '.gypi', | 72 '.gypi', |
69 '.gn', | 73 '.gn', |
70 '.gni', | 74 '.gni', |
71 '.h', # Ignore headers for the moment. | 75 '.h', # Ignore headers for the moment. |
72 ] | 76 ] |
73 for ext in IGNORED_EXTENSIONS: | 77 for ext in IGNORED_EXTENSIONS: |
74 missing_from_gn = filter(lambda p: not p.endswith(ext), missing_from_gn) | 78 missing_from_gn = filter(lambda p: not p.endswith(ext), missing_from_gn) |
75 | 79 |
76 # All upper-case files like README, DEPS, etc. are fine. | 80 # All upper-case files like README, DEPS, etc. are fine. |
77 missing_from_gn = filter(lambda p: not os.path.basename(p).isupper(), | 81 missing_from_gn = filter(lambda p: not os.path.basename(p).isupper(), |
78 missing_from_gn) | 82 missing_from_gn) |
79 | 83 |
80 print '\n'.join(missing_from_gn) | 84 print '\n'.join(missing_from_gn) |
81 | 85 |
82 | 86 |
83 if __name__ == '__main__': | 87 if __name__ == '__main__': |
84 main() | 88 main() |
OLD | NEW |