| Index: build/fix_gn_headers.py
|
| diff --git a/build/fix_gn_headers.py b/build/fix_gn_headers.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..5520a47815d1b5d969e8a3e2ea774b4292422e5a
|
| --- /dev/null
|
| +++ b/build/fix_gn_headers.py
|
| @@ -0,0 +1,125 @@
|
| +#!/usr/bin/env python
|
| +# Copyright 2017 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Fix header files missing in GN.
|
| +
|
| +This script takes the missing header files from check_gn_headers.py, and
|
| +try to fix them by adding them to the GN files.
|
| +Manual cleaning up is likely required afterwards.
|
| +"""
|
| +
|
| +import argparse
|
| +import os
|
| +import re
|
| +import subprocess
|
| +import sys
|
| +
|
| +
|
| +def AddHeadersNextToCC(headers, skip_ambiguous=True):
|
| + """Add header files next to the corresponding .cc files in GN files.
|
| +
|
| + When skip_ambiguous is True, skip if multiple .cc files are found.
|
| + Returns unhandled headers.
|
| +
|
| + Manual cleaning up is likely required, especially if not skip_ambiguous.
|
| + """
|
| + edits = {}
|
| + unhandled = []
|
| + for filename in headers:
|
| + filename = filename.strip()
|
| + if not (filename.endswith('.h') or filename.endswith('.hh')):
|
| + continue
|
| + basename = os.path.basename(filename)
|
| + print filename
|
| + cc = r'\b' + os.path.splitext(basename)[0] + r'\.(cc|cpp|mm)\b'
|
| + p = subprocess.Popen(
|
| + ['git', 'grep', '-En', cc + '"', '--', '*.gn', '*.gni'],
|
| + stdout=subprocess.PIPE)
|
| + out, _ = p.communicate()
|
| + if p.returncode != 0 or not out:
|
| + unhandled.append(filename)
|
| + continue
|
| +
|
| + if skip_ambiguous and len(out.splitlines()) > 1:
|
| + print '\n[WARNING] Ambiguous matching for', filename
|
| + print out
|
| + continue
|
| +
|
| + for gnline in out.splitlines():
|
| + gnfile, linenr, contents = gnline.split(':')
|
| + linenr = int(linenr)
|
| + new = re.sub(cc, basename, contents)
|
| + lines = open(gnfile).read().splitlines()
|
| + # Skip if it's already there. It could be before or after the match.
|
| + if lines[linenr] == new:
|
| + continue
|
| + if lines[linenr - 2] == new:
|
| + continue
|
| + print ' ', gnfile, linenr, new
|
| + edits.setdefault(gnfile, {})[linenr] = new
|
| +
|
| + for gnfile in edits:
|
| + lines = open(gnfile).read().splitlines()
|
| + for l in sorted(edits[gnfile].keys(), reverse=True):
|
| + lines.insert(l, edits[gnfile][l])
|
| + open(gnfile, 'w').write('\n'.join(lines) + '\n')
|
| +
|
| + return unhandled
|
| +
|
| +
|
| +def AddHeadersToSources(headers, skip_ambiguous=True):
|
| + """Add header files to the sources list in the first GN file.
|
| +
|
| + The target GN file is the first one up the parent directories.
|
| + This usually does the wrong thing for _test files if the test and the main
|
| + target are in the same .gn file.
|
| + When skip_ambiguous is True, skip if multiple sources arrays are found.
|
| +
|
| + "git cl format" afterwards is required. Manually cleaning up duplicated items
|
| + is likely required.
|
| + """
|
| + for filename in headers:
|
| + filename = filename.strip()
|
| + print filename
|
| + dirname = os.path.dirname(filename)
|
| + while not os.path.exists(os.path.join(dirname, 'BUILD.gn')):
|
| + dirname = os.path.dirname(dirname)
|
| + rel = filename[len(dirname) + 1:]
|
| + gnfile = os.path.join(dirname, 'BUILD.gn')
|
| +
|
| + lines = open(gnfile).read().splitlines()
|
| + matched = [i for i, l in enumerate(lines) if ' sources = [' in l]
|
| + if skip_ambiguous and len(matched) > 1:
|
| + print '[WARNING] Multiple sources in', gnfile
|
| + continue
|
| +
|
| + if len(matched) < 1:
|
| + continue
|
| + print ' ', gnfile, rel
|
| + index = matched[0]
|
| + lines.insert(index + 1, '"%s",' % rel)
|
| + open(gnfile, 'w').write('\n'.join(lines) + '\n')
|
| +
|
| +
|
| +def main():
|
| + parser = argparse.ArgumentParser()
|
| + parser.add_argument('input_file',
|
| + help="missing headers, output of check_gn_headers.py")
|
| + parser.add_argument('--prefix',
|
| + help="only handle path name with this prefix")
|
| +
|
| + args, _extras = parser.parse_known_args()
|
| +
|
| + headers = open(args.input_file).readlines()
|
| +
|
| + if args.prefix:
|
| + headers = [i for i in headers if i.startswith(args.prefix)]
|
| +
|
| + unhandled = AddHeadersNextToCC(headers)
|
| + AddHeadersToSources(unhandled)
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + sys.exit(main())
|
|
|