[Author: aa]
[google-gears.git] / gears / tools / mkdepend.py
blobba7388c404c0cff131cfddf06fbb108d72331411
1 #!/usr/bin/python2.4
3 # Copyright 2007, Google Inc.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are met:
8 # 1. Redistributions of source code must retain the above copyright notice,
9 # this list of conditions and the following disclaimer.
10 # 2. Redistributions in binary form must reproduce the above copyright notice,
11 # this list of conditions and the following disclaimer in the documentation
12 # and/or other materials provided with the distribution.
13 # 3. Neither the name of Google Inc. nor the names of its contributors may be
14 # used to endorse or promote products derived from this software without
15 # specific prior written permission.
17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 """A really crappy C/C++ dependency generator (TM).
30 usage: %s target source
32 Print a list of all dependencies of source, in a form suitable for including
33 in a Makefile, i.e.
35 target : source dep1 dep2 dep3...
37 We make a couple simplifying assumptions here:
38 1. We are only executed from the top-level source directory
39 2. We assume that our include search path is really simple (in fact, it is
40 hard-coded -- yikes!)
41 3. We ignore the fact that some include files may be conditional (#ifdef)
42 """
44 import os
45 import re
46 import sys
48 SEARCH_DIRS=['', '..']
51 def readAllLines(f):
52 return open(f, 'r').read()
55 def grepForIncludes(file_contents):
56 return re.findall('#include\s+"(.*)"', file_contents)
59 def getIncludes(filename):
60 return grepForIncludes(readAllLines(filename))
63 def resolve(filename, f_fileexists =os.path.exists):
64 """
65 Scan the file system for a given file, trying each of the directories in
66 SEARCH_DIRS. If found, return the name of the file, otherwise return None.
67 """
68 for search_dir in SEARCH_DIRS:
69 resolved_filename = os.path.join(search_dir, filename)
70 if f_fileexists(resolved_filename):
71 return resolved_filename
73 return None
76 def getResolvedIncludes(filename, f_resolver =resolve, f_getIncludes =getIncludes):
77 return filter(None,
78 map(f_resolver,
79 f_getIncludes(filename)))
82 def getDependencies(filenames, f_getIncludes =getResolvedIncludes):
83 """
84 Return all the dependencies of the files in the list "filenames" by recursively
85 applying the function f_getIncludes.
86 """
87 includes = []
88 includes.extend(filenames)
89 for filename in filenames:
90 for fname_include in f_getIncludes(filename):
91 includes.extend(getDependencies([fname_include], f_getIncludes))
92 return includes
95 def sortAndRemoveDupes(list):
96 h = {}
97 for elt in list:
98 h[elt] = 1
99 l = h.keys()
100 l.sort()
101 return l
104 def printDependencies(deps, target, f_writer =sys.stdout.write):
105 f_writer("%s : " % target)
106 for dep in deps:
107 f_writer(os.path.normpath(dep) + ' ')
110 def checkArgs(argv, usage_string, f_writer =sys.stderr.write):
111 if len(argv) != 3:
112 f_writer(usage_string % argv[0])
113 return False
114 return True
117 def sortDependencies(deps):
119 Return first element (the .cc file) + sort of remaining elements (the header files).
121 return [deps[0]] + sortAndRemoveDupes(deps[1:])
124 if __name__ == '__main__':
125 if (not checkArgs(sys.argv, __doc__)):
126 sys.exit(1)
128 printDependencies(sortDependencies(getDependencies([sys.argv[1]])),
129 sys.argv[2])