diff options
| author | David Lamparter <equinox@diac24.net> | 2020-05-01 15:22:05 +0200 | 
|---|---|---|
| committer | David Lamparter <equinox@diac24.net> | 2020-05-05 14:06:42 +0200 | 
| commit | 599943954969adb2b69618b943e44c62ae3ce4d2 (patch) | |
| tree | a6344db264ac0215afbfb97acafb5650fcb53c1a /python | |
| parent | 15e9c561b2a10e90b1370e7a8d43d02ffde9e61a (diff) | |
build: rework Makefile var extraction... again
*sigh* I can't seem to catch a break on this.  Add a regex variant.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'python')
| -rw-r--r-- | python/makefile.py | 9 | ||||
| -rw-r--r-- | python/makevars.py | 60 | 
2 files changed, 53 insertions, 16 deletions
diff --git a/python/makefile.py b/python/makefile.py index 9af397d373..e60c8aadbc 100644 --- a/python/makefile.py +++ b/python/makefile.py @@ -11,6 +11,7 @@ import subprocess  import re  import argparse  from string import Template +from makevars import MakeReVars  argp = argparse.ArgumentParser(description = 'FRR Makefile extensions')  argp.add_argument('--dev-build', action = 'store_const', const = True, @@ -20,13 +21,9 @@ args = argp.parse_args()  with open('Makefile', 'r') as fd:      before = fd.read() -nolinecont = before.replace('\\\n', '') -m = re.search('^clippy_scan\s*=([^#]*)(?:#.*)?$', nolinecont, flags=re.MULTILINE) -if m is None: -    sys.stderr.write('failed to parse Makefile.in\n') -    sys.exit(2) +mv = MakeReVars(before) -clippy_scan = m.group(1).strip().split() +clippy_scan = mv['clippy_scan'].strip().split()  for clippy_file in clippy_scan:      assert clippy_file.endswith('.c') diff --git a/python/makevars.py b/python/makevars.py index e0e2031a0d..1a85fbd6f5 100644 --- a/python/makevars.py +++ b/python/makevars.py @@ -4,14 +4,33 @@  import os  import subprocess +import re -class MakeVars(object): +class MakeVarsBase(object):      ''' -    makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile +    common code between MakeVars and MakeReVars      '''      def __init__(self):          self._data = dict() +    def __getitem__(self, k): +        if k not in self._data: +            self.getvars([k]) +        return self._data[k] + +    def get(self, k, defval = None): +        if k not in self._data: +            self.getvars([k]) +        return self._data.get(k) or defval + +class MakeVars(MakeVarsBase): +    ''' +    makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile + +    This variant works by invoking make as a subprocess, i.e. Makefile must +    be valid and working.  (This is sometimes a problem if depfiles have not +    been generated.) +    '''      def getvars(self, varlist):          '''          get a batch list of variables from make.  faster than individual calls. @@ -39,12 +58,33 @@ class MakeVars(object):              v = v[1:-1]              self._data[k] = v -    def __getitem__(self, k): -        if k not in self._data: -            self.getvars([k]) -        return self._data[k] +class MakeReVars(MakeVarsBase): +    ''' +    makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile -    def get(self, k, defval = None): -        if k not in self._data: -            self.getvars([k]) -        return self._data[k] or defval +    This variant works by regexing through Makefile.  This means the Makefile +    does not need to be fully working, but on the other hand it doesn't support +    fancy complicated make expressions. +    ''' +    var_re = re.compile(r'^([^=#\n\s]+)[ \t]*=[ \t]*([^#\n]*)(?:#.*)?$', flags=re.MULTILINE) +    repl_re = re.compile(r'\$(?:([A-Za-z])|\(([^\)]+)\))') + +    def __init__(self, maketext): +        super().__init__() +        self._vars = dict(self.var_re.findall(maketext.replace('\\\n', ''))) + +    def replacevar(self, match): +        varname = match.group(1) or match.group(2) +        return self._vars.get(varname, '') + +    def getvars(self, varlist): +        for varname in varlist: +            if varname not in self._vars: +                continue + +            val, prevval = self._vars[varname], None +            while val != prevval: +                prevval = val +                val = self.repl_re.sub(self.replacevar, val) + +            self._data[varname] = val  | 
