]>
Commit | Line | Data |
---|---|---|
fc3fe1c2 SG |
1 | # Copyright (c) 2012 The Chromium OS Authors. |
2 | # | |
1a459660 | 3 | # SPDX-License-Identifier: GPL-2.0+ |
fc3fe1c2 SG |
4 | # |
5 | ||
8426d8b0 SW |
6 | import re |
7 | ||
6131beab SG |
8 | class Expr: |
9 | """A single regular expression for matching boards to build""" | |
10 | ||
11 | def __init__(self, expr): | |
12 | """Set up a new Expr object. | |
13 | ||
14 | Args: | |
15 | expr: String cotaining regular expression to store | |
16 | """ | |
17 | self._expr = expr | |
18 | self._re = re.compile(expr) | |
19 | ||
20 | def Matches(self, props): | |
21 | """Check if any of the properties match the regular expression. | |
22 | ||
23 | Args: | |
24 | props: List of properties to check | |
25 | Returns: | |
26 | True if any of the properties match the regular expression | |
27 | """ | |
28 | for prop in props: | |
29 | if self._re.match(prop): | |
30 | return True | |
31 | return False | |
32 | ||
33 | def __str__(self): | |
34 | return self._expr | |
35 | ||
36 | class Term: | |
37 | """A list of expressions each of which must match with properties. | |
38 | ||
39 | This provides a list of 'AND' expressions, meaning that each must | |
40 | match the board properties for that board to be built. | |
41 | """ | |
42 | def __init__(self): | |
43 | self._expr_list = [] | |
44 | self._board_count = 0 | |
45 | ||
46 | def AddExpr(self, expr): | |
47 | """Add an Expr object to the list to check. | |
48 | ||
49 | Args: | |
50 | expr: New Expr object to add to the list of those that must | |
51 | match for a board to be built. | |
52 | """ | |
53 | self._expr_list.append(Expr(expr)) | |
54 | ||
55 | def __str__(self): | |
56 | """Return some sort of useful string describing the term""" | |
57 | return '&'.join([str(expr) for expr in self._expr_list]) | |
58 | ||
59 | def Matches(self, props): | |
60 | """Check if any of the properties match this term | |
61 | ||
62 | Each of the expressions in the term is checked. All must match. | |
63 | ||
64 | Args: | |
65 | props: List of properties to check | |
66 | Returns: | |
67 | True if all of the expressions in the Term match, else False | |
68 | """ | |
69 | for expr in self._expr_list: | |
70 | if not expr.Matches(props): | |
71 | return False | |
72 | return True | |
73 | ||
fc3fe1c2 SG |
74 | class Board: |
75 | """A particular board that we can build""" | |
03c1bb24 | 76 | def __init__(self, status, arch, cpu, soc, vendor, board_name, target, options): |
fc3fe1c2 SG |
77 | """Create a new board type. |
78 | ||
79 | Args: | |
03c1bb24 | 80 | status: define whether the board is 'Active' or 'Orphaned' |
fc3fe1c2 SG |
81 | arch: Architecture name (e.g. arm) |
82 | cpu: Cpu name (e.g. arm1136) | |
fc3fe1c2 | 83 | soc: Name of SOC, or '' if none (e.g. mx31) |
03c1bb24 AB |
84 | vendor: Name of vendor (e.g. armltd) |
85 | board_name: Name of board (e.g. integrator) | |
73f30b9b | 86 | target: Target name (use make <target>_defconfig to configure) |
fc3fe1c2 SG |
87 | options: board-specific options (e.g. integratorcp:CM1136) |
88 | """ | |
89 | self.target = target | |
90 | self.arch = arch | |
91 | self.cpu = cpu | |
92 | self.board_name = board_name | |
93 | self.vendor = vendor | |
94 | self.soc = soc | |
fc3fe1c2 | 95 | self.options = options |
e0f2406e TR |
96 | self.props = [self.target, self.arch, self.cpu, self.board_name, |
97 | self.vendor, self.soc, self.options] | |
fc3fe1c2 SG |
98 | self.build_it = False |
99 | ||
100 | ||
101 | class Boards: | |
102 | """Manage a list of boards.""" | |
103 | def __init__(self): | |
104 | # Use a simple list here, sinc OrderedDict requires Python 2.7 | |
105 | self._boards = [] | |
106 | ||
107 | def AddBoard(self, board): | |
108 | """Add a new board to the list. | |
109 | ||
110 | The board's target member must not already exist in the board list. | |
111 | ||
112 | Args: | |
113 | board: board to add | |
114 | """ | |
115 | self._boards.append(board) | |
116 | ||
117 | def ReadBoards(self, fname): | |
118 | """Read a list of boards from a board file. | |
119 | ||
120 | Create a board object for each and add it to our _boards list. | |
121 | ||
122 | Args: | |
123 | fname: Filename of boards.cfg file | |
124 | """ | |
125 | with open(fname, 'r') as fd: | |
126 | for line in fd: | |
127 | if line[0] == '#': | |
128 | continue | |
129 | fields = line.split() | |
130 | if not fields: | |
131 | continue | |
132 | for upto in range(len(fields)): | |
133 | if fields[upto] == '-': | |
134 | fields[upto] = '' | |
03c1bb24 | 135 | while len(fields) < 8: |
fc3fe1c2 | 136 | fields.append('') |
03c1bb24 AB |
137 | if len(fields) > 8: |
138 | fields = fields[:8] | |
fc3fe1c2 SG |
139 | |
140 | board = Board(*fields) | |
141 | self.AddBoard(board) | |
142 | ||
143 | ||
144 | def GetList(self): | |
145 | """Return a list of available boards. | |
146 | ||
147 | Returns: | |
148 | List of Board objects | |
149 | """ | |
150 | return self._boards | |
151 | ||
152 | def GetDict(self): | |
153 | """Build a dictionary containing all the boards. | |
154 | ||
155 | Returns: | |
156 | Dictionary: | |
157 | key is board.target | |
158 | value is board | |
159 | """ | |
160 | board_dict = {} | |
161 | for board in self._boards: | |
162 | board_dict[board.target] = board | |
163 | return board_dict | |
164 | ||
165 | def GetSelectedDict(self): | |
166 | """Return a dictionary containing the selected boards | |
167 | ||
168 | Returns: | |
169 | List of Board objects that are marked selected | |
170 | """ | |
171 | board_dict = {} | |
172 | for board in self._boards: | |
173 | if board.build_it: | |
174 | board_dict[board.target] = board | |
175 | return board_dict | |
176 | ||
177 | def GetSelected(self): | |
178 | """Return a list of selected boards | |
179 | ||
180 | Returns: | |
181 | List of Board objects that are marked selected | |
182 | """ | |
183 | return [board for board in self._boards if board.build_it] | |
184 | ||
185 | def GetSelectedNames(self): | |
186 | """Return a list of selected boards | |
187 | ||
188 | Returns: | |
189 | List of board names that are marked selected | |
190 | """ | |
191 | return [board.target for board in self._boards if board.build_it] | |
192 | ||
6131beab SG |
193 | def _BuildTerms(self, args): |
194 | """Convert command line arguments to a list of terms. | |
195 | ||
196 | This deals with parsing of the arguments. It handles the '&' | |
197 | operator, which joins several expressions into a single Term. | |
198 | ||
199 | For example: | |
200 | ['arm & freescale sandbox', 'tegra'] | |
201 | ||
202 | will produce 3 Terms containing expressions as follows: | |
203 | arm, freescale | |
204 | sandbox | |
205 | tegra | |
206 | ||
207 | The first Term has two expressions, both of which must match for | |
208 | a board to be selected. | |
209 | ||
210 | Args: | |
211 | args: List of command line arguments | |
212 | Returns: | |
213 | A list of Term objects | |
214 | """ | |
215 | syms = [] | |
216 | for arg in args: | |
217 | for word in arg.split(): | |
218 | sym_build = [] | |
219 | for term in word.split('&'): | |
220 | if term: | |
221 | sym_build.append(term) | |
222 | sym_build.append('&') | |
223 | syms += sym_build[:-1] | |
224 | terms = [] | |
225 | term = None | |
226 | oper = None | |
227 | for sym in syms: | |
228 | if sym == '&': | |
229 | oper = sym | |
230 | elif oper: | |
231 | term.AddExpr(sym) | |
232 | oper = None | |
233 | else: | |
234 | if term: | |
235 | terms.append(term) | |
236 | term = Term() | |
237 | term.AddExpr(sym) | |
238 | if term: | |
239 | terms.append(term) | |
240 | return terms | |
241 | ||
3cf4ae6f | 242 | def SelectBoards(self, args, exclude=[]): |
fc3fe1c2 SG |
243 | """Mark boards selected based on args |
244 | ||
245 | Args: | |
3cf4ae6f SG |
246 | args: List of strings specifying boards to include, either named, |
247 | or by their target, architecture, cpu, vendor or soc. If | |
248 | empty, all boards are selected. | |
249 | exclude: List of boards to exclude, regardless of 'args' | |
fc3fe1c2 SG |
250 | |
251 | Returns: | |
8d7523c5 | 252 | Dictionary which holds the list of boards which were selected |
fc3fe1c2 SG |
253 | due to each argument, arranged by argument. |
254 | """ | |
255 | result = {} | |
6131beab SG |
256 | terms = self._BuildTerms(args) |
257 | ||
8d7523c5 | 258 | result['all'] = [] |
6131beab | 259 | for term in terms: |
8d7523c5 | 260 | result[str(term)] = [] |
fc3fe1c2 | 261 | |
3cf4ae6f SG |
262 | exclude_list = [] |
263 | for expr in exclude: | |
264 | exclude_list.append(Expr(expr)) | |
265 | ||
fc3fe1c2 | 266 | for board in self._boards: |
3cf4ae6f SG |
267 | matching_term = None |
268 | build_it = False | |
6131beab SG |
269 | if terms: |
270 | match = False | |
271 | for term in terms: | |
272 | if term.Matches(board.props): | |
3cf4ae6f SG |
273 | matching_term = str(term) |
274 | build_it = True | |
6131beab | 275 | break |
fc3fe1c2 | 276 | else: |
3cf4ae6f SG |
277 | build_it = True |
278 | ||
279 | # Check that it is not specifically excluded | |
280 | for expr in exclude_list: | |
281 | if expr.Matches(board.props): | |
282 | build_it = False | |
283 | break | |
284 | ||
285 | if build_it: | |
fc3fe1c2 | 286 | board.build_it = True |
3cf4ae6f | 287 | if matching_term: |
8d7523c5 SG |
288 | result[matching_term].append(board.target) |
289 | result['all'].append(board.target) | |
fc3fe1c2 SG |
290 | |
291 | return result |