diff options
| author | David Lamparter <equinox@diac24.net> | 2020-04-15 10:27:49 +0200 | 
|---|---|---|
| committer | David Lamparter <equinox@diac24.net> | 2020-04-27 09:52:41 +0200 | 
| commit | 94cfb0692e0499e7ba40908db5259cd19c0e3d5e (patch) | |
| tree | 21dea4bef030b2e9170029235fe2385bda5cf90f /python | |
| parent | ec8f987e91678b50a4136459bd2351e623c6915d (diff) | |
build: make clippy Makefile rules nicer
These are easy to get subtly wrong, and doing so can cause
nondeterministic failures when racing in parallel builds.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'python')
| -rw-r--r-- | python/makefile.py | 100 | 
1 files changed, 100 insertions, 0 deletions
diff --git a/python/makefile.py b/python/makefile.py new file mode 100644 index 0000000000..9af397d373 --- /dev/null +++ b/python/makefile.py @@ -0,0 +1,100 @@ +#!/usr/bin/python3 +# +# FRR extended automake/Makefile functionality helper +# +# This script is executed on/after generating Makefile to add some pieces for +# clippy. + +import sys +import os +import subprocess +import re +import argparse +from string import Template + +argp = argparse.ArgumentParser(description = 'FRR Makefile extensions') +argp.add_argument('--dev-build', action = 'store_const', const = True, +            help = 'run additional developer checks') +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) + +clippy_scan = m.group(1).strip().split() +for clippy_file in clippy_scan: +    assert clippy_file.endswith('.c') + +# check for files using clippy but not listed in clippy_scan +if args.dev_build: +    basepath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +    if os.path.exists(os.path.join(basepath, '.git')): +        clippy_ref = subprocess.check_output([ +            'git', '-C', basepath, 'grep', '-l', '-P', '^#\s*include.*_clippy.c', '--', '**.c']).decode('US-ASCII') + +        clippy_ref = set(clippy_ref.splitlines()) +        missing = clippy_ref - set(clippy_scan) + +        if len(missing) > 0: +            sys.stderr.write('error: files seem to be using clippy, but not listed in "clippy_scan" in subdir.am:\n\t%s\n' % ('\n\t'.join(sorted(missing)))) +            sys.exit(1) + +clippydep = Template(''' +${clippybase}.$$(OBJEXT): ${clippybase}_clippy.c +${clippybase}.lo: ${clippybase}_clippy.c +${clippybase}_clippy.c: $$(CLIPPY_DEPS)''') + +clippyauxdep = Template('''# clippy{ +# auxiliary clippy target +${target}: ${clippybase}_clippy.c +# }clippy''') + +lines = before.splitlines() +autoderp = '#AUTODERP# ' +out_lines = [] +make_rule_re = re.compile('^([^:\s]+):\s*([^:\s]+)\s*($|\n)') + +while lines: +    line = lines.pop(0) +    if line.startswith(autoderp): +        line = line[len(autoderp):] + +    if line == '# clippy{': +        while lines: +            line = lines.pop(0) +            if line == '# }clippy': +                break +        continue + +    if line.startswith('#'): +        out_lines.append(line) +        continue + +    m = make_rule_re.match(line) +    if m is None: +        out_lines.append(line) +        continue + +    if m.group(2) in clippy_scan: +        out_lines.append(clippyauxdep.substitute(target=m.group(1), clippybase=m.group(2)[:-2])) + +    out_lines.append(line) + +out_lines.append('# clippy{\n# main clippy targets') +for clippy_file in clippy_scan: +    out_lines.append(clippydep.substitute(clippybase = clippy_file[:-2])) +out_lines.append('# }clippy') +out_lines.append('') + +after = '\n'.join(out_lines) +if after == before: +    sys.exit(0) + +with open('Makefile.pyout', 'w') as fd: +    fd.write(after) +os.rename('Makefile.pyout', 'Makefile')  | 
