OLD | NEW |
(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()) |
OLD | NEW |