-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathupdate_boarddb.py
166 lines (134 loc) · 5.21 KB
/
update_boarddb.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/usr/bin/env python3
import argparse
from pathlib import Path
from jinja2 import Environment, FileSystemLoader
from parse_boards import parse_file
def get_fpconf(config):
fpu = (config.build.get("fpu") or "-mfpu=").rsplit("=", 1)[1]
abi = (config.build.get("float-abi") or "-mfloat-abi=").rsplit("=", 1)[1]
return f"{fpu}-{abi}"
def boardstxt_filter(key):
# Remove menu entry labels and oopenocd config if any
# In our data model, they conflict with the actual configuration
# they are associated to
# i.e. Nucleo_144.menu.pnum.NUCLEO_F207ZG would be both
# a string ("Nucleo F207ZG")
# and a dict (.build.variant_h=..., .upload.maximum_size=...)
if key[-1] == "svd_file":
return True
if len(key) >= 5 and key[-2] == "scripts" and key[-3] == "openocd":
return True
if key[0] == "menu":
# menu.xserial=U(S)ART support
return True
if len(key) == 4 and key[1] == "menu":
# Nucleo_144.menu.pnum.NUCLEO_F207ZG=Nucleo F207ZG
# Midatronics.menu.upload_method.MassStorage=Mass Storage
return True
# keep bootloader flags that impact the build
if len(key) >= 6 and key[1] == "menu" and key[2] == "upload_method":
if key[3] != "build":
return False
return True
return False
def platformtxt_filter(key):
# reject everything except build.**, vid.** and pid.**
# Note that build.info is also rejected
# (it is specific to the build system, it will be hard-coded)
# nothing else is needed from platform.txt
# +additional stuff might confuse later parts of the script
# e.g.:
# compiler.warning_flags=-w
# compiler.warning_flags.none=-w
# compiler.warning_flags.default=
# compiler.warning_flags.more=-Wall
# compiler.warning_flags.all=-Wall -Wextra
if key[0] == "build" and key[1] != "info":
return False
if key[0] == "vid" or key[0] == "pid":
return False
return True
def regenerate_template(config, infile, outfile):
j2_env = Environment(
loader=FileSystemLoader(str(infile.parent)),
trim_blocks=True,
lstrip_blocks=True,
)
cmake_template = j2_env.get_template(infile.name)
with open(outfile, "w") as out:
out.write(
cmake_template.render(
allcfg=config,
)
)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"-b", "--boards", type=Path, required=True, help="path to boards.txt"
)
parser.add_argument(
"-p",
"--platform",
type=Path,
required=True,
help="path to platform.txt",
)
parser.add_argument(
"-t",
"--template",
type=Path,
required=True,
help="path to the jinja template",
)
parser.add_argument(
"-o",
"--outfile",
type=Path,
required=True,
help="path to the cmake database to generate",
)
shargs = parser.parse_args()
platformtxt_cfg = parse_file(shargs.platform, reject=platformtxt_filter)
# whitelist what we need
platformtxt_cfg = {
"build": platformtxt_cfg["build"],
"vid": platformtxt_cfg["vid"],
"pid": platformtxt_cfg["pid"],
}
boardstxt_cfg = parse_file(shargs.boards, reject=boardstxt_filter)
del boardstxt_cfg["menu"] # blacklist what we don't need
# these are optional features to be picked out by the user
BOARD_FEATURES = ["enable_virtio", "enable_usb", "usb_speed", "xSerial"]
allboards = dict()
for fam, famcfg in boardstxt_cfg.items():
famcfg.set_default_entries(platformtxt_cfg)
inherit_fam = famcfg.copy()
# shallow copy;
# we don't want to impact famcfg so we have to copy before edit/del
inherit_fam["menu"] = inherit_fam["menu"].copy()
# del what you iterate over (otherwise you get infinite nesting)
del inherit_fam["menu"]["pnum"]
for u_meth, u_meth_cfg in inherit_fam.menu.upload_method.copy().items():
if "build" not in u_meth_cfg.keys():
del inherit_fam.menu.upload_method[u_meth]
for board, boardcfg in famcfg.menu.pnum.items():
boardcfg["_fpconf"] = get_fpconf(boardcfg)
boardcfg.set_default_entries(inherit_fam)
inherit_board = boardcfg.copy()
del inherit_board["menu"]
board_feature_names = tuple(boardcfg["menu"].keys())
for fname in board_feature_names:
for label, labelcfg in boardcfg["menu"][fname].items():
labelcfg.set_default_entries(inherit_board)
labelcfg.evaluate_entries()
# base config won't manage all the board features,
# we thus have to mask them out
for feat in BOARD_FEATURES:
boardcfg.build[feat] = ""
boardcfg.evaluate_entries()
allboards[board] = boardcfg
for mth, mthcfg in boardcfg.menu.upload_method.items():
if mth.startswith(("hid", "dfuo", "dfu2")):
mth = mth.removesuffix("Method")
allboards[f"{board}_{mth}"] = mthcfg
regenerate_template(allboards, shargs.template, shargs.outfile)