Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(683)

Side by Side Diff: build/check_gn_headers.py

Issue 2510303002: Add check_gn_headers.py to find missing headers in GN (Closed)
Patch Set: address nits Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | build/check_gn_headers_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2017 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
6 """Find header files missing in GN.
7
8 This script gets all the header files from ninja_deps, which is from the true
9 dependency generated by the compiler, and report if they don't exist in GN.
10 """
11
12 import argparse
13 import json
14 import os
15 import re
16 import subprocess
17 import sys
18
19
20 def GetHeadersFromNinja(out_dir):
21 """Return all the header files from ninja_deps"""
22 ninja_out = subprocess.check_output(['ninja', '-C', out_dir, '-t', 'deps'])
23 return ParseNinjaDepsOutput(ninja_out)
24
25
26 def ParseNinjaDepsOutput(ninja_out):
27 """Parse ninja output and get the header files"""
28 all_headers = set()
29
30 prefix = '..' + os.sep + '..' + os.sep
31
32 is_valid = False
33 for line in ninja_out.split('\n'):
34 if line.startswith(' '):
35 if not is_valid:
36 continue
37 if line.endswith('.h') or line.endswith('.hh'):
38 f = line.strip()
39 if f.startswith(prefix):
40 f = f[6:] # Remove the '../../' prefix
41 # build/ only contains build-specific files like build_config.h
42 # and buildflag.h, and system header files, so they should be
43 # skipped.
44 if not f.startswith('build'):
45 all_headers.add(f)
46 else:
47 is_valid = line.endswith('(VALID)')
48
49 return all_headers
50
51
52 def GetHeadersFromGN(out_dir):
53 """Return all the header files from GN"""
54 subprocess.check_call(['gn', 'gen', out_dir, '--ide=json', '-q'])
55 gn_json = json.load(open(os.path.join(out_dir, 'project.json')))
56 return ParseGNProjectJSON(gn_json)
57
58
59 def ParseGNProjectJSON(gn):
60 """Parse GN output and get the header files"""
61 all_headers = set()
62
63 for _target, properties in gn['targets'].iteritems():
64 for f in properties.get('sources', []):
65 if f.endswith('.h') or f.endswith('.hh'):
66 if f.startswith('//'):
67 f = f[2:] # Strip the '//' prefix.
68 all_headers.add(f)
69
70 return all_headers
71
72
73 def GetDepsPrefixes():
74 """Return all the folders controlled by DEPS file"""
75 gclient_out = subprocess.check_output(
76 ['gclient', 'recurse', '--no-progress', '-j1',
77 'python', '-c', 'import os;print os.environ["GCLIENT_DEP_PATH"]'])
78 prefixes = set()
79 for i in gclient_out.split('\n'):
80 if i.startswith('src/'):
81 i = i[4:]
82 prefixes.add(i)
83 return prefixes
84
85
86 def ParseWhiteList(whitelist):
87 out = set()
88 for line in whitelist.split('\n'):
89 line = re.sub(r'#.*', '', line).strip()
90 if line:
91 out.add(line)
92 return out
93
94
95 def main():
96 parser = argparse.ArgumentParser()
97 parser.add_argument('--out-dir', default='out/Release')
98 parser.add_argument('--json')
99 parser.add_argument('--whitelist')
100 parser.add_argument('args', nargs=argparse.REMAINDER)
101
102 args, _extras = parser.parse_known_args()
103
104 d = GetHeadersFromNinja(args.out_dir)
105 gn = GetHeadersFromGN(args.out_dir)
106 missing = d - gn
107
108 deps = GetDepsPrefixes()
109 missing = {m for m in missing if not any(m.startswith(d) for d in deps)}
110
111 if args.whitelist:
112 whitelist = ParseWhiteList(open(args.whitelist).read())
113 missing -= whitelist
114
115 missing = sorted(missing)
116
117 if args.json:
118 with open(args.json, 'w') as f:
119 json.dump(missing, f)
120
121 if len(missing) == 0:
122 return 0
123
124 print 'The following files should be included in gn files:'
125 for i in missing:
126 print i
127 return 1
128
129
130 if __name__ == '__main__':
131 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | build/check_gn_headers_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698