diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/libwebrtc/build/fix_gn_headers.py | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/build/fix_gn_headers.py')
-rwxr-xr-x | third_party/libwebrtc/build/fix_gn_headers.py | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/third_party/libwebrtc/build/fix_gn_headers.py b/third_party/libwebrtc/build/fix_gn_headers.py new file mode 100755 index 0000000000..71fb332bfd --- /dev/null +++ b/third_party/libwebrtc/build/fix_gn_headers.py @@ -0,0 +1,220 @@ +#!/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. +""" + +from __future__ import print_function + +import argparse +import os +import re +import subprocess +import sys + + +def GitGrep(pattern): + p = subprocess.Popen( + ['git', 'grep', '-En', pattern, '--', '*.gn', '*.gni'], + stdout=subprocess.PIPE) + out, _ = p.communicate() + return out, p.returncode + + +def ValidMatches(basename, cc, grep_lines): + """Filter out 'git grep' matches with header files already.""" + matches = [] + for line in grep_lines: + gnfile, linenr, contents = line.split(':') + linenr = int(linenr) + new = re.sub(cc, basename, contents) + lines = open(gnfile).read().splitlines() + assert contents in lines[linenr - 1] + # 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) + matches.append((gnfile, linenr, new)) + return matches + + +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' + out, returncode = GitGrep('(/|")' + cc + '"') + if returncode != 0 or not out: + unhandled.append(filename) + continue + + matches = ValidMatches(basename, cc, out.splitlines()) + + if len(matches) == 0: + continue + if len(matches) > 1: + print('\n[WARNING] Ambiguous matching for', filename) + for i in enumerate(matches, 1): + print('%d: %s' % (i[0], i[1])) + print() + if skip_ambiguous: + continue + + picked = raw_input('Pick the matches ("2,3" for multiple): ') + try: + matches = [matches[int(i) - 1] for i in picked.split(',')] + except (ValueError, IndexError): + continue + + for match in matches: + gnfile, linenr, new = match + 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 RemoveHeader(headers, skip_ambiguous=True): + """Remove non-existing headers in GN files. + + When skip_ambiguous is True, skip if multiple matches are found. + """ + 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) + out, returncode = GitGrep('(/|")' + basename + '"') + if returncode != 0 or not out: + unhandled.append(filename) + print(' Not found') + continue + + grep_lines = out.splitlines() + matches = [] + for line in grep_lines: + gnfile, linenr, contents = line.split(':') + print(' ', gnfile, linenr, contents) + linenr = int(linenr) + lines = open(gnfile).read().splitlines() + assert contents in lines[linenr - 1] + matches.append((gnfile, linenr, contents)) + + if len(matches) == 0: + continue + if len(matches) > 1: + print('\n[WARNING] Ambiguous matching for', filename) + for i in enumerate(matches, 1): + print('%d: %s' % (i[0], i[1])) + print() + if skip_ambiguous: + continue + + picked = raw_input('Pick the matches ("2,3" for multiple): ') + try: + matches = [matches[int(i) - 1] for i in picked.split(',')] + except (ValueError, IndexError): + continue + + for match in matches: + gnfile, linenr, contents = match + print(' ', gnfile, linenr, contents) + edits.setdefault(gnfile, set()).add(linenr) + + for gnfile in edits: + lines = open(gnfile).read().splitlines() + for l in sorted(edits[gnfile], reverse=True): + lines.pop(l - 1) + open(gnfile, 'w').write('\n'.join(lines) + '\n') + + return unhandled + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('input_file', help="missing or non-existing headers, " + "output of check_gn_headers.py") + parser.add_argument('--prefix', + help="only handle path name with this prefix") + parser.add_argument('--remove', action='store_true', + help="treat input_file as non-existing headers") + + 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)] + + if args.remove: + RemoveHeader(headers, False) + else: + unhandled = AddHeadersNextToCC(headers) + AddHeadersToSources(unhandled) + + +if __name__ == '__main__': + sys.exit(main()) |