]> git.proxmox.com Git - mirror_frr.git/blame - python/makefile.py
Merge pull request #12797 from jvidalallende/ubi8_minimal_dockerfile
[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 163xref_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
174out_lines.append(
175 "xrefs = %s" % (" ".join(["%s.xref" % target for target in xref_targets]))
176)
a1e6ab1e
DL
177out_lines.append("frr.xref: $(xrefs)")
178out_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 185out_lines.append("")
8fb40377 186out_lines.extend(bcdeps)
701a0192 187out_lines.append("")
8fb40377 188bc_targets = []
701a0192 189for 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())
197for 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 208out_lines.append("# }clippy")
209out_lines.append("")
94cfb069 210
701a0192 211after = "\n".join(out_lines)
94cfb069
DL
212if after == before:
213 sys.exit(0)
214
701a0192 215with open("Makefile.pyout", "w") as fd:
94cfb069 216 fd.write(after)
701a0192 217os.rename("Makefile.pyout", "Makefile")