1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
#
# Small helper library to read and manipulate kernel Makefiles
#
import os, re
obj_line = re.compile(r'^obj-(?P<dep>[^\s+:=]*)\s*[+:]?=\s*(?P<tgt>[^\\]*)\s*(?P<cont>\\?)')
class MakeTree(object):
def __init__(self, rootfile):
self.basedir = os.path.dirname(rootfile)
self.rootfile = os.path.basename(rootfile)
self._no_syms = []
self._walked = False
self._found_makefiles = []
def _check_for_sym(self, f, sym):
# re-read Makefile to see if it declared this symbol ...
r = re.compile('^%s-(y|objs)\s*[+:]?=' % sym)
for l in open(os.path.join(self.basedir, f), 'r'):
if r.match(l):
# FIXME: check if symbol dependencies can be satisfied!
return True
return False
def _walk(self, f=None, subdir='', sym=None):
if self._walked:
return
if not os.path.exists(os.path.join(self.basedir, subdir, f)):
#print "no %s" % os.path.join(self.basedir, subdir, f)
assert not sym is None
self._no_syms.append(sym)
return
self._found_makefiles.append(os.path.join(self.basedir, subdir, f))
for l in open(os.path.join(self.basedir, subdir, f), 'r'):
m = obj_line.match(l)
if not m:
continue
dep = m.group('dep')
if dep[:2] == '$(':
if dep[-1] != ')':
raise Exception("Couldn't parse make dependency %s" % dep)
dep = dep[2:-1]
tgt = m.group('tgt')
for t in tgt.strip().split():
t = t.strip()
if not t:
continue
if t[-1] == '/':
self._walk(f='Makefile', subdir=os.path.join(subdir, t), sym=dep)
elif t[-2:] == '.o':
t = t[:-2] + '.c'
if not os.path.exists(os.path.join(self.basedir, subdir, t)):
if not self._check_for_sym(os.path.join(subdir, f), t[:-2]):
self._no_syms.append(dep)
else:
assert False
# FIXME: consider continuation lines!
def get_impossible_symbols(self):
self._walk(self.rootfile)
return self._no_syms
def get_makefiles(self):
self._walk(self.rootfile)
return self._found_makefiles
|