]>
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 | 15 | |
701a0192 | 16 | argp = argparse.ArgumentParser(description="FRR Makefile extensions") |
17 | argp.add_argument( | |
18 | "--dev-build", | |
19 | action="store_const", | |
20 | const=True, | |
21 | help="run additional developer checks", | |
22 | ) | |
94cfb069 DL |
23 | args = argp.parse_args() |
24 | ||
701a0192 | 25 | with open("Makefile", "r") as fd: |
94cfb069 DL |
26 | before = fd.read() |
27 | ||
59994395 | 28 | mv = MakeReVars(before) |
94cfb069 | 29 | |
701a0192 | 30 | clippy_scan = mv["clippy_scan"].strip().split() |
94cfb069 | 31 | for clippy_file in clippy_scan: |
701a0192 | 32 | assert clippy_file.endswith(".c") |
94cfb069 | 33 | |
a1e6ab1e | 34 | xref_targets = [] |
9cef17c7 DL |
35 | for varname in [ |
36 | "bin_PROGRAMS", | |
37 | "sbin_PROGRAMS", | |
38 | "lib_LTLIBRARIES", | |
39 | "module_LTLIBRARIES", | |
40 | ]: | |
a1e6ab1e DL |
41 | xref_targets.extend(mv[varname].strip().split()) |
42 | ||
94cfb069 DL |
43 | # check for files using clippy but not listed in clippy_scan |
44 | if args.dev_build: | |
45 | basepath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
701a0192 | 46 | if os.path.exists(os.path.join(basepath, ".git")): |
47 | clippy_ref = subprocess.check_output( | |
48 | [ | |
49 | "git", | |
50 | "-C", | |
51 | basepath, | |
52 | "grep", | |
53 | "-l", | |
54 | "-P", | |
55 | "^#\s*include.*_clippy.c", | |
56 | "--", | |
57 | "**.c", | |
58 | ] | |
59 | ).decode("US-ASCII") | |
94cfb069 DL |
60 | |
61 | clippy_ref = set(clippy_ref.splitlines()) | |
62 | missing = clippy_ref - set(clippy_scan) | |
63 | ||
64 | if len(missing) > 0: | |
701a0192 | 65 | sys.stderr.write( |
66 | 'error: files seem to be using clippy, but not listed in "clippy_scan" in subdir.am:\n\t%s\n' | |
67 | % ("\n\t".join(sorted(missing))) | |
68 | ) | |
94cfb069 DL |
69 | sys.exit(1) |
70 | ||
dd3689e2 DL |
71 | # this additional-dependency rule is stuck onto all compile targets that |
72 | # compile a file which uses clippy-generated input, so it has a dependency to | |
73 | # make that first. | |
701a0192 | 74 | clippydep = Template( |
75 | """ | |
94cfb069 DL |
76 | ${clippybase}.$$(OBJEXT): ${clippybase}_clippy.c |
77 | ${clippybase}.lo: ${clippybase}_clippy.c | |
701a0192 | 78 | ${clippybase}_clippy.c: $$(CLIPPY_DEPS)""" |
79 | ) | |
94cfb069 | 80 | |
dd3689e2 DL |
81 | # this one is used when one .c file is built multiple times with different |
82 | # CFLAGS | |
701a0192 | 83 | clippyauxdep = Template( |
84 | """# clippy{ | |
94cfb069 DL |
85 | # auxiliary clippy target |
86 | ${target}: ${clippybase}_clippy.c | |
701a0192 | 87 | # }clippy""" |
88 | ) | |
94cfb069 DL |
89 | |
90 | lines = before.splitlines() | |
701a0192 | 91 | autoderp = "#AUTODERP# " |
94cfb069 | 92 | out_lines = [] |
8fb40377 | 93 | bcdeps = [] |
701a0192 | 94 | make_rule_re = re.compile("^([^:\s]+):\s*([^:\s]+)\s*($|\n)") |
94cfb069 DL |
95 | |
96 | while lines: | |
97 | line = lines.pop(0) | |
98 | if line.startswith(autoderp): | |
701a0192 | 99 | line = line[len(autoderp) :] |
94cfb069 | 100 | |
dd3689e2 | 101 | # allow rerunning on already-clippified Makefile |
701a0192 | 102 | if line == "# clippy{": |
94cfb069 DL |
103 | while lines: |
104 | line = lines.pop(0) | |
701a0192 | 105 | if line == "# }clippy": |
94cfb069 DL |
106 | break |
107 | continue | |
108 | ||
701a0192 | 109 | if line.startswith("#"): |
94cfb069 DL |
110 | out_lines.append(line) |
111 | continue | |
112 | ||
06852b5b DL |
113 | full_line = line |
114 | full_lines = lines[:] | |
701a0192 | 115 | while full_line.endswith("\\"): |
06852b5b DL |
116 | full_line = full_line[:-1] + full_lines.pop(0) |
117 | ||
118 | m = make_rule_re.match(full_line) | |
94cfb069 DL |
119 | if m is None: |
120 | out_lines.append(line) | |
121 | continue | |
122 | ||
06852b5b DL |
123 | line, lines = full_line, full_lines |
124 | ||
8fb40377 DL |
125 | target, dep = m.group(1), m.group(2) |
126 | ||
e8422835 | 127 | filename = os.path.basename(target) |
9cef17c7 | 128 | if "-" in filename: |
dd3689e2 | 129 | # dashes in output filename = building same .c with different CFLAGS |
9cef17c7 | 130 | am_name, _ = filename.split("-", 1) |
e8422835 | 131 | am_name = os.path.join(os.path.dirname(target), am_name) |
9cef17c7 | 132 | am_name = am_name.replace("/", "_") |
e8422835 DL |
133 | extraflags = " $(%s_CFLAGS)" % (am_name,) |
134 | else: | |
dd3689e2 DL |
135 | # this path isn't really triggered because automake is using a generic |
136 | # .c => .o rule unless CFLAGS are customized for a target | |
e8422835 DL |
137 | extraflags = "" |
138 | ||
701a0192 | 139 | if target.endswith(".lo") or target.endswith(".o"): |
140 | if not dep.endswith(".h"): | |
dd3689e2 | 141 | # LLVM bitcode targets for analysis tools |
701a0192 | 142 | bcdeps.append("%s.bc: %s" % (target, target)) |
9cef17c7 DL |
143 | bcdeps.append( |
144 | "\t$(AM_V_LLVM_BC)$(COMPILE)%s -emit-llvm -c -o $@ %s" | |
145 | % (extraflags, dep) | |
146 | ) | |
94cfb069 | 147 | if m.group(2) in clippy_scan: |
dd3689e2 DL |
148 | # again - this is only hit for targets with custom CFLAGS, because |
149 | # automake uses a generic .c -> .o rule for standard CFLAGS | |
701a0192 | 150 | out_lines.append( |
151 | clippyauxdep.substitute(target=m.group(1), clippybase=m.group(2)[:-2]) | |
152 | ) | |
94cfb069 DL |
153 | |
154 | out_lines.append(line) | |
155 | ||
dd3689e2 | 156 | # now, cover all the .c files that don't have special build rules |
701a0192 | 157 | out_lines.append("# clippy{\n# main clippy targets") |
94cfb069 | 158 | for clippy_file in clippy_scan: |
701a0192 | 159 | out_lines.append(clippydep.substitute(clippybase=clippy_file[:-2])) |
8fb40377 | 160 | |
dd3689e2 | 161 | # combine daemon .xref files into frr.xref |
a1e6ab1e | 162 | out_lines.append("") |
fc84b6ee | 163 | xref_targets = [ |
00f0c399 DL |
164 | target |
165 | for target in xref_targets | |
166 | if target | |
167 | not in [ | |
3727be24 DL |
168 | "bgpd/rfp-example/rfptest/rfptest", |
169 | "pimd/mtracebis", | |
170 | "tools/ssd", | |
171 | "vtysh/vtysh", | |
172 | ] | |
fc84b6ee | 173 | ] |
9cef17c7 DL |
174 | out_lines.append( |
175 | "xrefs = %s" % (" ".join(["%s.xref" % target for target in xref_targets])) | |
176 | ) | |
a1e6ab1e DL |
177 | out_lines.append("frr.xref: $(xrefs)") |
178 | out_lines.append("") | |
179 | ||
dd3689e2 | 180 | # analog but slower way to get the same frr.xref |
9cef17c7 DL |
181 | # frr.xref: $(bin_PROGRAMS) $(sbin_PROGRAMS) $(lib_LTLIBRARIES) $(module_LTLIBRARIES) |
182 | # $(AM_V_XRELFO) $(CLIPPY) $(top_srcdir)/python/xrelfo.py -o $@ $^ | |
a1e6ab1e | 183 | |
dd3689e2 | 184 | # LLVM bitcode link targets creating a .bc file for whole daemon or lib |
701a0192 | 185 | out_lines.append("") |
8fb40377 | 186 | out_lines.extend(bcdeps) |
701a0192 | 187 | out_lines.append("") |
8fb40377 | 188 | bc_targets = [] |
701a0192 | 189 | for varname in [ |
190 | "bin_PROGRAMS", | |
191 | "sbin_PROGRAMS", | |
192 | "lib_LTLIBRARIES", | |
193 | "module_LTLIBRARIES", | |
194 | "noinst_LIBRARIES", | |
195 | ]: | |
8fb40377 DL |
196 | bc_targets.extend(mv[varname].strip().split()) |
197 | for target in bc_targets: | |
701a0192 | 198 | amtgt = target.replace("/", "_").replace(".", "_").replace("-", "_") |
199 | objs = mv[amtgt + "_OBJECTS"].strip().split() | |
200 | objs = [obj + ".bc" for obj in objs] | |
201 | deps = mv.get(amtgt + "_DEPENDENCIES", "").strip().split() | |
202 | deps = [d + ".bc" for d in deps if d.endswith(".a")] | |
8fb40377 | 203 | objs.extend(deps) |
701a0192 | 204 | out_lines.append("%s.bc: %s" % (target, " ".join(objs))) |
205 | out_lines.append("\t$(AM_V_LLVM_LD)$(LLVM_LINK) -o $@ $^") | |
206 | out_lines.append("") | |
8fb40377 | 207 | |
701a0192 | 208 | out_lines.append("# }clippy") |
209 | out_lines.append("") | |
94cfb069 | 210 | |
701a0192 | 211 | after = "\n".join(out_lines) |
94cfb069 DL |
212 | if after == before: |
213 | sys.exit(0) | |
214 | ||
701a0192 | 215 | with open("Makefile.pyout", "w") as fd: |
94cfb069 | 216 | fd.write(after) |
701a0192 | 217 | os.rename("Makefile.pyout", "Makefile") |