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

Side by Side Diff: build/fix_gn_headers.py

Issue 2781603003: Add script fix_gn_headers.py to fix GN missing headers (Closed)
Patch Set: my amendments Created 3 years, 9 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 | no next file » | 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 """Fix header files missing in GN.
7
8 This script takes the missing header files from check_gn_headers.py, and
9 try to fix them by adding them to the GN files.
10 Manual cleaning up is likely required afterwards.
11 """
12
13 import argparse
14 import os
15 import re
16 import subprocess
17 import sys
18
19
20 def AddHeadersNextToCC(headers, skip_ambiguous=True):
21 """Add header files next to the corresponding .cc files in GN files.
22
23 When skip_ambiguous is True, skip if multiple .cc files are found.
24 Returns unhandled headers.
25
26 Manual cleaning up is likely required, especially if not skip_ambiguous.
27 """
28 edits = {}
29 unhandled = []
30 for filename in headers:
31 filename = filename.strip()
32 if not (filename.endswith('.h') or filename.endswith('.hh')):
Nico 2017/03/28 14:37:55 Do we have any headers ending in .hh?
wychen 2017/03/28 17:52:05 Yes, we do, and some of them are part of the GN mi
33 continue
34 basename = os.path.basename(filename)
35 print filename
36 cc = r'\b' + os.path.splitext(basename)[0] + r'\.(cc|cpp|mm)\b'
37 p = subprocess.Popen(
38 ['git', 'grep', '-En', cc + '"', '--', '*.gn', '*.gni'],
39 stdout=subprocess.PIPE)
40 out, _ = p.communicate()
41 if p.returncode != 0 or not out:
42 unhandled.append(filename)
43 continue
44
45 if skip_ambiguous and len(out.splitlines()) > 1:
46 print '\n[WARNING] Ambiguous matching for', filename
47 print out
48 continue
49
50 for gnline in out.splitlines():
51 gnfile, linenr, contents = gnline.split(':')
52 linenr = int(linenr)
53 new = re.sub(cc, basename, contents)
54 lines = open(gnfile).read().splitlines()
55 if lines[linenr] == new:
56 continue
57 if lines[linenr - 2] == new:
Nico 2017/03/28 14:37:55 why this?
wychen 2017/03/28 17:52:05 This and the line above is for deduplication. line
58 continue
59 print ' ', gnfile, linenr, new
60 edits.setdefault(gnfile, {})[linenr] = new
61
62 for gnfile in edits:
63 lines = open(gnfile).read().splitlines()
64 for l in reversed(sorted(edits[gnfile].keys())):
Nico 2017/03/28 14:37:55 Ah, that was the bug! I had assumed the keys were
wychen 2017/03/28 17:52:05 Done.
65 lines.insert(l, edits[gnfile][l])
66 open(gnfile, 'w').write('\n'.join(lines) + '\n')
67
68 return unhandled
69
70
71 def AddHeadersToSources(headers, skip_ambiguous=True):
72 """Add header files to the sources list in the closest GN file.
Nico 2017/03/28 14:37:55 "to the _first_ sources list" Mention somehow tha
wychen 2017/03/28 17:52:05 Done.
73
74 When skip_ambiguous is True, skip if multiple sources arrays are found.
75
76 "git cl format" afterwards is required. Manually cleaning up duplicated items
77 is likely required.
78 """
79 for filename in headers:
80 filename = filename.strip()
81 print filename
82 dirname = os.path.dirname(filename)
83 while not os.path.exists(os.path.join(dirname, 'BUILD.gn')):
84 dirname = os.path.dirname(dirname)
85 rel = filename[len(dirname) + 1:]
86 gnfile = os.path.join(dirname, 'BUILD.gn')
87
88 lines = open(gnfile).read().splitlines()
89 matched = [i for i, l in enumerate(lines) if ' sources = [' in l]
90 if skip_ambiguous and len(matched) > 1:
91 print '[WARNING] Multiple sources in', gnfile
92 continue
93
94 if len(matched) < 1:
95 continue
96 print ' ', gnfile, rel
97 index = matched[0]
98 lines.insert(index + 1, '"%s",' % rel)
99 open(gnfile, 'w').write('\n'.join(lines) + '\n')
100
101
102 def main():
103 parser = argparse.ArgumentParser()
104 parser.add_argument('--input', required=True,
105 help="missing headers, output of check_gn_headers.py")
Nico 2017/03/28 14:37:55 nit: I'd make this one a positional argument
wychen 2017/03/28 17:52:05 Done.
106 parser.add_argument('--prefix',
107 help="only handle path name with this prefix")
108 parser.add_argument('args', nargs=argparse.REMAINDER)
109
110 args, _extras = parser.parse_known_args()
111
112 headers = open(args.input).readlines()
113
114 if args.prefix:
115 headers = [i for i in headers if i.startswith(args.prefix)]
116
117 unhandled = AddHeadersNextToCC(headers)
118 AddHeadersToSources(unhandled)
119
120
121 if __name__ == '__main__':
122 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698