2 # Copyright (c) 2013 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.
6 """Fixup GCC-generated dependency files.
8 Modify GCC generated dependency files so they are more suitable for including
9 in a GNU Makefile. Without the fixups, deleting or renaming headers can cause
10 the build to be broken.
12 See http://mad-scientist.net/make/autodep.html for more details of the problem.
19 TAG_LINE = '# Updated by fix_deps.py\n'
22 class Error(Exception):
26 def ParseLine(line, new_target):
27 """Parse one line of a GCC-generated deps file.
29 Each line contains an optional target and then a list
30 of space seperated dependencies. Spaces within filenames
31 are escaped with a backslash.
35 if new_target and ':' in line:
36 line = line.split(':', 1)[1]
39 line = line.rstrip('\\')
42 # Find the next non-escaped space
45 while pos > 0 and line[pos-1] == '\\':
46 pos = line.find(' ', pos+1)
49 filenames.append(line)
51 filenames.append(line[:pos])
57 def FixupDepFile(filename, output_filename=None):
58 if not os.path.exists(filename):
59 raise Error('File not found: %s' % filename)
61 if output_filename is None:
62 output_filename = filename
67 with open(filename) as infile:
70 raise Error('Already processed: %s' % filename)
72 deps += ParseLine(line, new_target)
73 new_target = line.endswith('\\')
75 # For every depenency found output a dummy target with no rules
77 outlines.append('%s:\n' % dep)
79 with open(output_filename, 'w') as outfile:
85 usage = "usage: %prog [options] <dep_file>"
86 parser = optparse.OptionParser(usage=usage, description=__doc__)
87 parser.add_option('-o', '--output', help='Output filename (defaults to '
88 'input name with .deps extension')
89 parser.add_option('-c', '--clean', action='store_true',
90 help='Remove input file after writing output')
91 options, args = parser.parse_args(argv)
93 raise parser.error('No input file specified')
95 raise parser.error('Only one argument supported')
96 input_filename = args[0]
97 output_filename = options.output
98 if not output_filename:
99 output_filename = os.path.splitext(input_filename)[0] + '.deps'
100 FixupDepFile(input_filename, output_filename)
101 if options.clean and input_filename != output_filename:
102 os.remove(input_filename)
105 if __name__ == '__main__':
107 sys.exit(main(sys.argv[1:]))
109 sys.stderr.write('%s: %s\n' % (os.path.basename(__file__), e))