mirror of
https://github.com/FRRouting/frr.git
synced 2026-01-16 23:14:01 +00:00
These files are completely authored by either me personally or other people working for NetDEF, Inc., as such I'm authorized to stick copyright headers (or rather SPDX tags) on them. (this is by "git blame" and to a 100% line count.) Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
218 lines
6.2 KiB
Python
218 lines
6.2 KiB
Python
#!/usr/bin/python3
|
|
# SPDX-License-Identifier: ISC
|
|
#
|
|
# 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
|
|
from makevars import MakeReVars
|
|
|
|
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()
|
|
|
|
mv = MakeReVars(before)
|
|
|
|
clippy_scan = mv["clippy_scan"].strip().split()
|
|
for clippy_file in clippy_scan:
|
|
assert clippy_file.endswith(".c")
|
|
|
|
xref_targets = []
|
|
for varname in [
|
|
"bin_PROGRAMS",
|
|
"sbin_PROGRAMS",
|
|
"lib_LTLIBRARIES",
|
|
"module_LTLIBRARIES",
|
|
]:
|
|
xref_targets.extend(mv[varname].strip().split())
|
|
|
|
# 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",
|
|
r"^#\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)
|
|
|
|
# this additional-dependency rule is stuck onto all compile targets that
|
|
# compile a file which uses clippy-generated input, so it has a dependency to
|
|
# make that first.
|
|
clippydep = Template(
|
|
"""
|
|
${clippybase}.$$(OBJEXT): ${clippybase}_clippy.c
|
|
${clippybase}.lo: ${clippybase}_clippy.c
|
|
${clippybase}_clippy.c: $$(CLIPPY_DEPS)"""
|
|
)
|
|
|
|
# this one is used when one .c file is built multiple times with different
|
|
# CFLAGS
|
|
clippyauxdep = Template(
|
|
"""# clippy{
|
|
# auxiliary clippy target
|
|
${target}: ${clippybase}_clippy.c
|
|
# }clippy"""
|
|
)
|
|
|
|
lines = before.splitlines()
|
|
autoderp = "#AUTODERP# "
|
|
out_lines = []
|
|
bcdeps = []
|
|
make_rule_re = re.compile(r"^([^:\s]+):\s*([^:\s]+)\s*($|\n)")
|
|
|
|
while lines:
|
|
line = lines.pop(0)
|
|
if line.startswith(autoderp):
|
|
line = line[len(autoderp) :]
|
|
|
|
# allow rerunning on already-clippified Makefile
|
|
if line == "# clippy{":
|
|
while lines:
|
|
line = lines.pop(0)
|
|
if line == "# }clippy":
|
|
break
|
|
continue
|
|
|
|
if line.startswith("#"):
|
|
out_lines.append(line)
|
|
continue
|
|
|
|
full_line = line
|
|
full_lines = lines[:]
|
|
while full_line.endswith("\\"):
|
|
full_line = full_line[:-1] + full_lines.pop(0)
|
|
|
|
m = make_rule_re.match(full_line)
|
|
if m is None:
|
|
out_lines.append(line)
|
|
continue
|
|
|
|
line, lines = full_line, full_lines
|
|
|
|
target, dep = m.group(1), m.group(2)
|
|
|
|
filename = os.path.basename(target)
|
|
if "-" in filename:
|
|
# dashes in output filename = building same .c with different CFLAGS
|
|
am_name, _ = filename.split("-", 1)
|
|
am_name = os.path.join(os.path.dirname(target), am_name)
|
|
am_name = am_name.replace("/", "_")
|
|
extraflags = " $(%s_CFLAGS)" % (am_name,)
|
|
else:
|
|
# this path isn't really triggered because automake is using a generic
|
|
# .c => .o rule unless CFLAGS are customized for a target
|
|
extraflags = ""
|
|
|
|
if target.endswith(".lo") or target.endswith(".o"):
|
|
if not dep.endswith(".h"):
|
|
# LLVM bitcode targets for analysis tools
|
|
bcdeps.append("%s.bc: %s" % (target, target))
|
|
bcdeps.append(
|
|
"\t$(AM_V_LLVM_BC)$(COMPILE)%s -emit-llvm -c -o $@ %s"
|
|
% (extraflags, dep)
|
|
)
|
|
if m.group(2) in clippy_scan:
|
|
# again - this is only hit for targets with custom CFLAGS, because
|
|
# automake uses a generic .c -> .o rule for standard CFLAGS
|
|
out_lines.append(
|
|
clippyauxdep.substitute(target=m.group(1), clippybase=m.group(2)[:-2])
|
|
)
|
|
|
|
out_lines.append(line)
|
|
|
|
# now, cover all the .c files that don't have special build rules
|
|
out_lines.append("# clippy{\n# main clippy targets")
|
|
for clippy_file in clippy_scan:
|
|
out_lines.append(clippydep.substitute(clippybase=clippy_file[:-2]))
|
|
|
|
# combine daemon .xref files into frr.xref
|
|
out_lines.append("")
|
|
xref_targets = [
|
|
target
|
|
for target in xref_targets
|
|
if target
|
|
not in [
|
|
"bgpd/rfp-example/rfptest/rfptest",
|
|
"pimd/mtracebis",
|
|
"tools/ssd",
|
|
"vtysh/vtysh",
|
|
]
|
|
]
|
|
out_lines.append(
|
|
"xrefs = %s" % (" ".join(["%s.xref" % target for target in xref_targets]))
|
|
)
|
|
out_lines.append("frr.xref: $(xrefs)")
|
|
out_lines.append("")
|
|
|
|
# analog but slower way to get the same frr.xref
|
|
# frr.xref: $(bin_PROGRAMS) $(sbin_PROGRAMS) $(lib_LTLIBRARIES) $(module_LTLIBRARIES)
|
|
# $(AM_V_XRELFO) $(CLIPPY) $(top_srcdir)/python/xrelfo.py -o $@ $^
|
|
|
|
# LLVM bitcode link targets creating a .bc file for whole daemon or lib
|
|
out_lines.append("")
|
|
out_lines.extend(bcdeps)
|
|
out_lines.append("")
|
|
bc_targets = []
|
|
for varname in [
|
|
"bin_PROGRAMS",
|
|
"sbin_PROGRAMS",
|
|
"lib_LTLIBRARIES",
|
|
"module_LTLIBRARIES",
|
|
"noinst_LIBRARIES",
|
|
]:
|
|
bc_targets.extend(mv[varname].strip().split())
|
|
for target in bc_targets:
|
|
amtgt = target.replace("/", "_").replace(".", "_").replace("-", "_")
|
|
objs = mv[amtgt + "_OBJECTS"].strip().split()
|
|
objs = [obj + ".bc" for obj in objs]
|
|
deps = mv.get(amtgt + "_DEPENDENCIES", "").strip().split()
|
|
deps = [d + ".bc" for d in deps if d.endswith(".a")]
|
|
objs.extend(deps)
|
|
out_lines.append("%s.bc: %s" % (target, " ".join(objs)))
|
|
out_lines.append("\t$(AM_V_LLVM_LD)$(LLVM_LINK) -o $@ $^")
|
|
out_lines.append("")
|
|
|
|
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")
|