blob: 5d536d5f20049fc40dd78880632ac10257bcd4c8 [file] [log] [blame] [edit]
# Copyright (c) 2012 The Chromium OS Authors.
#
# SPDX-License-Identifier: GPL-2.0+
#
import re
class Expr:
"""A single regular expression for matching boards to build"""
def __init__(self, expr):
"""Set up a new Expr object.
Args:
expr: String cotaining regular expression to store
"""
self._expr = expr
self._re = re.compile(expr)
def Matches(self, props):
"""Check if any of the properties match the regular expression.
Args:
props: List of properties to check
Returns:
True if any of the properties match the regular expression
"""
for prop in props:
if self._re.match(prop):
return True
return False
def __str__(self):
return self._expr
class Term:
"""A list of expressions each of which must match with properties.
This provides a list of 'AND' expressions, meaning that each must
match the board properties for that board to be built.
"""
def __init__(self):
self._expr_list = []
self._board_count = 0
def AddExpr(self, expr):
"""Add an Expr object to the list to check.
Args:
expr: New Expr object to add to the list of those that must
match for a board to be built.
"""
self._expr_list.append(Expr(expr))
def __str__(self):
"""Return some sort of useful string describing the term"""
return '&'.join([str(expr) for expr in self._expr_list])
def Matches(self, props):
"""Check if any of the properties match this term
Each of the expressions in the term is checked. All must match.
Args:
props: List of properties to check
Returns:
True if all of the expressions in the Term match, else False
"""
for expr in self._expr_list:
if not expr.Matches(props):
return False
return True
class Board:
"""A particular board that we can build"""
def __init__(self, status, arch, cpu, soc, vendor, board_name, target, options):
"""Create a new board type.
Args:
status: define whether the board is 'Active' or 'Orphaned'
arch: Architecture name (e.g. arm)
cpu: Cpu name (e.g. arm1136)
soc: Name of SOC, or '' if none (e.g. mx31)
vendor: Name of vendor (e.g. armltd)
board_name: Name of board (e.g. integrator)
target: Target name (use make <target>_defconfig to configure)
options: board-specific options (e.g. integratorcp:CM1136)
"""
self.target = target
self.arch = arch
self.cpu = cpu
self.board_name = board_name
self.vendor = vendor
self.soc = soc
self.props = [self.target, self.arch, self.cpu, self.board_name,
self.vendor, self.soc]
self.options = options
self.build_it = False
class Boards:
"""Manage a list of boards."""
def __init__(self):
# Use a simple list here, sinc OrderedDict requires Python 2.7
self._boards = []
def AddBoard(self, board):
"""Add a new board to the list.
The board's target member must not already exist in the board list.
Args:
board: board to add
"""
self._boards.append(board)
def ReadBoards(self, fname):
"""Read a list of boards from a board file.
Create a board object for each and add it to our _boards list.
Args:
fname: Filename of boards.cfg file
"""
with open(fname, 'r') as fd:
for line in fd:
if line[0] == '#':
continue
fields = line.split()
if not fields:
continue
for upto in range(len(fields)):
if fields[upto] == '-':
fields[upto] = ''
while len(fields) < 8:
fields.append('')
if len(fields) > 8:
fields = fields[:8]
board = Board(*fields)
self.AddBoard(board)
def GetList(self):
"""Return a list of available boards.
Returns:
List of Board objects
"""
return self._boards
def GetDict(self):
"""Build a dictionary containing all the boards.
Returns:
Dictionary:
key is board.target
value is board
"""
board_dict = {}
for board in self._boards:
board_dict[board.target] = board
return board_dict
def GetSelectedDict(self):
"""Return a dictionary containing the selected boards
Returns:
List of Board objects that are marked selected
"""
board_dict = {}
for board in self._boards:
if board.build_it:
board_dict[board.target] = board
return board_dict
def GetSelected(self):
"""Return a list of selected boards
Returns:
List of Board objects that are marked selected
"""
return [board for board in self._boards if board.build_it]
def GetSelectedNames(self):
"""Return a list of selected boards
Returns:
List of board names that are marked selected
"""
return [board.target for board in self._boards if board.build_it]
def _BuildTerms(self, args):
"""Convert command line arguments to a list of terms.
This deals with parsing of the arguments. It handles the '&'
operator, which joins several expressions into a single Term.
For example:
['arm & freescale sandbox', 'tegra']
will produce 3 Terms containing expressions as follows:
arm, freescale
sandbox
tegra
The first Term has two expressions, both of which must match for
a board to be selected.
Args:
args: List of command line arguments
Returns:
A list of Term objects
"""
syms = []
for arg in args:
for word in arg.split():
sym_build = []
for term in word.split('&'):
if term:
sym_build.append(term)
sym_build.append('&')
syms += sym_build[:-1]
terms = []
term = None
oper = None
for sym in syms:
if sym == '&':
oper = sym
elif oper:
term.AddExpr(sym)
oper = None
else:
if term:
terms.append(term)
term = Term()
term.AddExpr(sym)
if term:
terms.append(term)
return terms
def SelectBoards(self, args, exclude=[]):
"""Mark boards selected based on args
Args:
args: List of strings specifying boards to include, either named,
or by their target, architecture, cpu, vendor or soc. If
empty, all boards are selected.
exclude: List of boards to exclude, regardless of 'args'
Returns:
Dictionary which holds the number of boards which were selected
due to each argument, arranged by argument.
"""
result = {}
terms = self._BuildTerms(args)
result['all'] = 0
for term in terms:
result[str(term)] = 0
exclude_list = []
for expr in exclude:
exclude_list.append(Expr(expr))
for board in self._boards:
matching_term = None
build_it = False
if terms:
match = False
for term in terms:
if term.Matches(board.props):
matching_term = str(term)
build_it = True
break
else:
build_it = True
# Check that it is not specifically excluded
for expr in exclude_list:
if expr.Matches(board.props):
build_it = False
break
if build_it:
board.build_it = True
if matching_term:
result[matching_term] += 1
result['all'] += 1
return result