board.py 9.3 KB

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