]> git.proxmox.com Git - mirror_frr.git/blob - python/makevars.py
bgpd: introduce LP_TYPE_NEXTHOP label type
[mirror_frr.git] / python / makevars.py
1 #
2 # helper class to grab variables from FRR's Makefile
3 #
4
5 import os
6 import subprocess
7 import re
8
9
10 class MakeVarsBase(object):
11 """
12 common code between MakeVars and MakeReVars
13 """
14
15 def __init__(self):
16 self._data = dict()
17
18 def __getitem__(self, k):
19 if k not in self._data:
20 self.getvars([k])
21 return self._data[k]
22
23 def get(self, k, defval=None):
24 if k not in self._data:
25 self.getvars([k])
26 return self._data.get(k) or defval
27
28
29 class MakeVars(MakeVarsBase):
30 """
31 makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile
32
33 This variant works by invoking make as a subprocess, i.e. Makefile must
34 be valid and working. (This is sometimes a problem if depfiles have not
35 been generated.)
36 """
37
38 def getvars(self, varlist):
39 """
40 get a batch list of variables from make. faster than individual calls.
41 """
42 rdfd, wrfd = os.pipe()
43
44 shvars = ["shvar-%s" % s for s in varlist]
45 make = subprocess.Popen(
46 ["make", "-s", "VARFD=%d" % wrfd] + shvars, pass_fds=[wrfd]
47 )
48 os.close(wrfd)
49 data = b""
50
51 rdf = os.fdopen(rdfd, "rb")
52 while True:
53 rdata = rdf.read()
54 if len(rdata) == 0:
55 break
56 data += rdata
57
58 del rdf
59 make.wait()
60
61 data = data.decode("US-ASCII").strip().split("\n")
62 for row in data:
63 k, v = row.split("=", 1)
64 v = v[1:-1]
65 self._data[k] = v
66
67
68 class MakeReVars(MakeVarsBase):
69 """
70 makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile
71
72 This variant works by regexing through Makefile. This means the Makefile
73 does not need to be fully working, but on the other hand it doesn't support
74 fancy complicated make expressions.
75 """
76
77 var_re = re.compile(
78 r"^([^=#\n\s]+)[ \t]*=[ \t]*([^#\n]*)(?:#.*)?$", flags=re.MULTILINE
79 )
80 repl_re = re.compile(r"\$(?:([A-Za-z])|\(([^\)]+)\))")
81
82 def __init__(self, maketext):
83 super(MakeReVars, self).__init__()
84 self._vars = dict(self.var_re.findall(maketext.replace("\\\n", "")))
85
86 def replacevar(self, match):
87 varname = match.group(1) or match.group(2)
88 return self._vars.get(varname, "")
89
90 def getvars(self, varlist):
91 for varname in varlist:
92 if varname not in self._vars:
93 continue
94
95 val, prevval = self._vars[varname], None
96 while val != prevval:
97 prevval = val
98 val = self.repl_re.sub(self.replacevar, val)
99
100 self._data[varname] = val