board.py 8.4 KB

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