]> git.proxmox.com Git - mirror_frr.git/blame - python/makefile.py
python: fix for old (< 3.6) Python versions
[mirror_frr.git] / python / makefile.py
CommitLineData
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
8import sys
9import os
10import subprocess
11import re
12import argparse
13from string import Template
59994395 14from makevars import MakeReVars
94cfb069 15
701a0192 16argp = argparse.ArgumentParser(description="FRR Makefile extensions")
17argp.add_argument(
18 "--dev-build",
19 action="store_const",
20 const=True,
21 help="run additional developer checks",
22)
94cfb069
DL
23args = argp.parse_args()
24
701a0192 25with open("Makefile", "r") as fd:
94cfb069
DL
26 before = fd.read()
27
59994395 28mv = MakeReVars(before)
94cfb069 29
701a0192 30clippy_scan = mv["clippy_scan"].strip().split()
94cfb069 31for clippy_file in clippy_scan:
701a0192 32 assert clippy_file.endswith(".c")
94cfb069 33
a1e6ab1e 34xref_targets = []
9cef17c7
DL
35for 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
44if 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 74clippydep = 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 83clippyauxdep = Template(
84 """# clippy{
94cfb069
DL
85# auxiliary clippy target
86${target}: ${clippybase}_clippy.c
701a0192 87# }clippy"""
88)
94cfb069
DL
89
90lines = before.splitlines()
701a0192 91autoderp = "#AUTODERP# "
94cfb069 92out_lines = []
8fb40377 93bcdeps = []
701a0192 94make_rule_re = re.compile("^([^:\s]+):\s*([^:\s]+)\s*($|\n)")
94cfb069
DL
95
96while 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 157out_lines.append("# clippy{\n# main clippy targets")
94cfb069 158for 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 162out_lines.append("")
fc84b6ee
DL
163xref_targets = [
164 target for target in xref_targets if target not in ["tools/ssd", "vtysh/vtysh"]
165]
9cef17c7
DL
166out_lines.append(
167 "xrefs = %s" % (" ".join(["%s.xref" % target for target in xref_targets]))
168)
a1e6ab1e
DL
169out_lines.append("frr.xref: $(xrefs)")
170out_lines.append("")
171
dd3689e2 172# analog but slower way to get the same frr.xref
9cef17c7
DL
173# frr.xref: $(bin_PROGRAMS) $(sbin_PROGRAMS) $(lib_LTLIBRARIES) $(module_LTLIBRARIES)
174# $(AM_V_XRELFO) $(CLIPPY) $(top_srcdir)/python/xrelfo.py -o $@ $^
a1e6ab1e 175
dd3689e2 176# LLVM bitcode link targets creating a .bc file for whole daemon or lib
701a0192 177out_lines.append("")
8fb40377 178out_lines.extend(bcdeps)
701a0192 179out_lines.append("")
8fb40377 180bc_targets = []
701a0192 181for varname in [
182 "bin_PROGRAMS",
183 "sbin_PROGRAMS",
184 "lib_LTLIBRARIES",
185 "module_LTLIBRARIES",
186 "noinst_LIBRARIES",
187]:
8fb40377
DL
188 bc_targets.extend(mv[varname].strip().split())
189for target in bc_targets:
701a0192 190 amtgt = target.replace("/", "_").replace(".", "_").replace("-", "_")
191 objs = mv[amtgt + "_OBJECTS"].strip().split()
192 objs = [obj + ".bc" for obj in objs]
193 deps = mv.get(amtgt + "_DEPENDENCIES", "").strip().split()
194 deps = [d + ".bc" for d in deps if d.endswith(".a")]
8fb40377 195 objs.extend(deps)
701a0192 196 out_lines.append("%s.bc: %s" % (target, " ".join(objs)))
197 out_lines.append("\t$(AM_V_LLVM_LD)$(LLVM_LINK) -o $@ $^")
198 out_lines.append("")
8fb40377 199
701a0192 200out_lines.append("# }clippy")
201out_lines.append("")
94cfb069 202
701a0192 203after = "\n".join(out_lines)
94cfb069
DL
204if after == before:
205 sys.exit(0)
206
701a0192 207with open("Makefile.pyout", "w") as fd:
94cfb069 208 fd.write(after)
701a0192 209os.rename("Makefile.pyout", "Makefile")