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

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: address comments Created 3 years, 8 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')):
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 # Skip if it's already there. It could be before or after the match.
56 if lines[linenr] == new:
57 continue
58 if lines[linenr - 2] == new:
59 continue
60 print ' ', gnfile, linenr, new
61 edits.setdefault(gnfile, {})[linenr] = new
62
63 for gnfile in edits:
64 lines = open(gnfile).read().splitlines()
65 for l in sorted(edits[gnfile].keys(), reverse=True):
66 lines.insert(l, edits[gnfile][l])
67 open(gnfile, 'w').write('\n'.join(lines) + '\n')
68
69 return unhandled
70
71
72 def AddHeadersToSources(headers, skip_ambiguous=True):
73 """Add header files to the sources list in the first GN file.
74
75 The target GN file is the first one up the parent directories.
76 This usually does the wrong thing for _test files if the test and the main
77 target are in the same .gn file.
78 When skip_ambiguous is True, skip if multiple sources arrays are found.
79
80 "git cl format" afterwards is required. Manually cleaning up duplicated items
81 is likely required.
82 """
83 for filename in headers:
84 filename = filename.strip()
85 print filename
86 dirname = os.path.dirname(filename)
87 while not os.path.exists(os.path.join(dirname, 'BUILD.gn')):
88 dirname = os.path.dirname(dirname)
89 rel = filename[len(dirname) + 1:]
90 gnfile = os.path.join(dirname, 'BUILD.gn')
91
92 lines = open(gnfile).read().splitlines()
93 matched = [i for i, l in enumerate(lines) if ' sources = [' in l]
94 if skip_ambiguous and len(matched) > 1:
95 print '[WARNING] Multiple sources in', gnfile
96 continue
97
98 if len(matched) < 1:
99 continue
100 print ' ', gnfile, rel
101 index = matched[0]
102 lines.insert(index + 1, '"%s",' % rel)
103 open(gnfile, 'w').write('\n'.join(lines) + '\n')
104
105
106 def main():
107 parser = argparse.ArgumentParser()
108 parser.add_argument('input_file',
109 help="missing headers, output of check_gn_headers.py")
110 parser.add_argument('--prefix',
111 help="only handle path name with this prefix")
112
113 args, _extras = parser.parse_known_args()
114
115 headers = open(args.input_file).readlines()
116
117 if args.prefix:
118 headers = [i for i in headers if i.startswith(args.prefix)]
119
120 unhandled = AddHeadersNextToCC(headers)
121 AddHeadersToSources(unhandled)
122
123
124 if __name__ == '__main__':
125 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