]>
Commit | Line | Data |
---|---|---|
94cfb069 DL |
1 | #!/usr/bin/python3 |
2 | # | |
3 | # FRR extended automake/Makefile functionality helper | |
4 | # | |
5 | # This script is executed on/after generating Makefile to add some pieces for | |
6 | # clippy. | |
7 | ||
8 | import sys | |
9 | import os | |
10 | import subprocess | |
11 | import re | |
12 | import argparse | |
13 | from string import Template | |
59994395 | 14 | from makevars import MakeReVars |
94cfb069 DL |
15 | |
16 | argp = argparse.ArgumentParser(description = 'FRR Makefile extensions') | |
17 | argp.add_argument('--dev-build', action = 'store_const', const = True, | |
18 | help = 'run additional developer checks') | |
19 | args = argp.parse_args() | |
20 | ||
21 | with open('Makefile', 'r') as fd: | |
22 | before = fd.read() | |
23 | ||
59994395 | 24 | mv = MakeReVars(before) |
94cfb069 | 25 | |
59994395 | 26 | clippy_scan = mv['clippy_scan'].strip().split() |
94cfb069 DL |
27 | for clippy_file in clippy_scan: |
28 | assert clippy_file.endswith('.c') | |
29 | ||
30 | # check for files using clippy but not listed in clippy_scan | |
31 | if args.dev_build: | |
32 | basepath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
33 | if os.path.exists(os.path.join(basepath, '.git')): | |
34 | clippy_ref = subprocess.check_output([ | |
35 | 'git', '-C', basepath, 'grep', '-l', '-P', '^#\s*include.*_clippy.c', '--', '**.c']).decode('US-ASCII') | |
36 | ||
37 | clippy_ref = set(clippy_ref.splitlines()) | |
38 | missing = clippy_ref - set(clippy_scan) | |
39 | ||
40 | if len(missing) > 0: | |
41 | 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)))) | |
42 | sys.exit(1) | |
43 | ||
44 | clippydep = Template(''' | |
45 | ${clippybase}.$$(OBJEXT): ${clippybase}_clippy.c | |
46 | ${clippybase}.lo: ${clippybase}_clippy.c | |
47 | ${clippybase}_clippy.c: $$(CLIPPY_DEPS)''') | |
48 | ||
49 | clippyauxdep = Template('''# clippy{ | |
50 | # auxiliary clippy target | |
51 | ${target}: ${clippybase}_clippy.c | |
52 | # }clippy''') | |
53 | ||
54 | lines = before.splitlines() | |
55 | autoderp = '#AUTODERP# ' | |
56 | out_lines = [] | |
8fb40377 | 57 | bcdeps = [] |
94cfb069 DL |
58 | make_rule_re = re.compile('^([^:\s]+):\s*([^:\s]+)\s*($|\n)') |
59 | ||
60 | while lines: | |
61 | line = lines.pop(0) | |
62 | if line.startswith(autoderp): | |
63 | line = line[len(autoderp):] | |
64 | ||
65 | if line == '# clippy{': | |
66 | while lines: | |
67 | line = lines.pop(0) | |
68 | if line == '# }clippy': | |
69 | break | |
70 | continue | |
71 | ||
72 | if line.startswith('#'): | |
73 | out_lines.append(line) | |
74 | continue | |
75 | ||
06852b5b DL |
76 | full_line = line |
77 | full_lines = lines[:] | |
78 | while full_line.endswith('\\'): | |
79 | full_line = full_line[:-1] + full_lines.pop(0) | |
80 | ||
81 | m = make_rule_re.match(full_line) | |
94cfb069 DL |
82 | if m is None: |
83 | out_lines.append(line) | |
84 | continue | |
85 | ||
06852b5b DL |
86 | line, lines = full_line, full_lines |
87 | ||
8fb40377 DL |
88 | target, dep = m.group(1), m.group(2) |
89 | ||
90 | if target.endswith('.lo') or target.endswith('.o'): | |
91 | if not dep.endswith('.h'): | |
92 | bcdeps.append('%s.bc: %s' % (target, target)) | |
93 | bcdeps.append('\t$(AM_V_LLVM_BC)$(COMPILE) -emit-llvm -c -o $@ %s' % (dep)) | |
94cfb069 DL |
94 | if m.group(2) in clippy_scan: |
95 | out_lines.append(clippyauxdep.substitute(target=m.group(1), clippybase=m.group(2)[:-2])) | |
96 | ||
97 | out_lines.append(line) | |
98 | ||
99 | out_lines.append('# clippy{\n# main clippy targets') | |
100 | for clippy_file in clippy_scan: | |
101 | out_lines.append(clippydep.substitute(clippybase = clippy_file[:-2])) | |
8fb40377 DL |
102 | |
103 | out_lines.append('') | |
104 | out_lines.extend(bcdeps) | |
105 | out_lines.append('') | |
106 | bc_targets = [] | |
107 | for varname in ['bin_PROGRAMS', 'sbin_PROGRAMS', 'lib_LTLIBRARIES', 'module_LTLIBRARIES', 'noinst_LIBRARIES']: | |
108 | bc_targets.extend(mv[varname].strip().split()) | |
109 | for target in bc_targets: | |
110 | amtgt = target.replace('/', '_').replace('.', '_').replace('-', '_') | |
111 | objs = mv[amtgt + '_OBJECTS'].strip().split() | |
112 | objs = [obj + '.bc' for obj in objs] | |
113 | deps = mv.get(amtgt + '_DEPENDENCIES', '').strip().split() | |
114 | deps = [d + '.bc' for d in deps if d.endswith('.a')] | |
115 | objs.extend(deps) | |
116 | out_lines.append('%s.bc: %s' % (target, ' '.join(objs))) | |
117 | out_lines.append('\t$(AM_V_LLVM_LD)$(LLVM_LINK) -o $@ $^') | |
118 | out_lines.append('') | |
119 | ||
94cfb069 DL |
120 | out_lines.append('# }clippy') |
121 | out_lines.append('') | |
122 | ||
123 | after = '\n'.join(out_lines) | |
124 | if after == before: | |
125 | sys.exit(0) | |
126 | ||
127 | with open('Makefile.pyout', 'w') as fd: | |
128 | fd.write(after) | |
129 | os.rename('Makefile.pyout', 'Makefile') |