summaryrefslogtreecommitdiff
path: root/lib/make.py
blob: f722a93e2170ebbaf3f86aba1de29a672f9faf2c (plain)
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