| #!/usr/bin/env python |
| # Copyright (c) 2013 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. |
| |
| """Fixup GCC-generated dependency files. |
| |
| Modify GCC generated dependency files so they are more suitable for including |
| in a GNU Makefile. Without the fixups, deleting or renaming headers can cause |
| the build to be broken. |
| |
| See http://mad-scientist.net/make/autodep.html for more details of the problem. |
| """ |
| |
| import argparse |
| import os |
| import sys |
| |
| TAG_LINE = '# Updated by fix_deps.py\n' |
| |
| |
| class Error(Exception): |
| pass |
| |
| |
| def ParseLine(line, new_target): |
| """Parse one line of a GCC-generated deps file. |
| |
| Each line contains an optional target and then a list |
| of space seperated dependencies. Spaces within filenames |
| are escaped with a backslash. |
| """ |
| filenames = [] |
| |
| if new_target and ':' in line: |
| line = line.split(':', 1)[1] |
| |
| line = line.strip() |
| line = line.rstrip('\\') |
| |
| while True: |
| # Find the next non-escaped space |
| line = line.strip() |
| pos = line.find(' ') |
| while pos > 0 and line[pos-1] == '\\': |
| pos = line.find(' ', pos+1) |
| |
| if pos == -1: |
| filenames.append(line) |
| break |
| filenames.append(line[:pos]) |
| line = line[pos+1:] |
| |
| return filenames |
| |
| |
| def FixupDepFile(filename, output_filename=None): |
| if not os.path.exists(filename): |
| raise Error('File not found: %s' % filename) |
| |
| if output_filename is None: |
| output_filename = filename |
| |
| outlines = [TAG_LINE] |
| deps = [] |
| new_target = True |
| with open(filename) as infile: |
| for line in infile: |
| if line == TAG_LINE: |
| raise Error('Already processed: %s' % filename) |
| outlines.append(line) |
| deps += ParseLine(line, new_target) |
| new_target = line.endswith('\\') |
| |
| # For every depenency found output a dummy target with no rules |
| for dep in deps: |
| outlines.append('%s:\n' % dep) |
| |
| with open(output_filename, 'w') as outfile: |
| for line in outlines: |
| outfile.write(line) |
| |
| |
| def main(argv): |
| parser = argparse.ArgumentParser(description=__doc__) |
| parser.add_argument('-o', '--output', help='Output filename (defaults to ' |
| 'input name with .deps extension') |
| parser.add_argument('-c', '--clean', action='store_true', |
| help='Remove input file after writing output') |
| parser.add_argument('dep_file') |
| options = parser.parse_args(argv) |
| output_filename = options.output |
| if not output_filename: |
| output_filename = os.path.splitext(options.dep_file)[0] + '.deps' |
| FixupDepFile(options.dep_file, output_filename) |
| if options.clean and options.dep_file != output_filename: |
| os.remove(options.dep_file) |
| |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| try: |
| sys.exit(main(sys.argv[1:])) |
| except Error as e: |
| sys.stderr.write('%s: %s\n' % (os.path.basename(__file__), e)) |
| sys.exit(1) |