board.py 8.4 KB

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