1fc3fe1c2SSimon Glass# Copyright (c) 2012 The Chromium OS Authors. 2fc3fe1c2SSimon Glass# 31a459660SWolfgang Denk# SPDX-License-Identifier: GPL-2.0+ 4fc3fe1c2SSimon Glass# 5fc3fe1c2SSimon Glass 68426d8b0SStephen Warrenimport re 78426d8b0SStephen Warren 86131beabSSimon Glassclass Expr: 96131beabSSimon Glass """A single regular expression for matching boards to build""" 106131beabSSimon Glass 116131beabSSimon Glass def __init__(self, expr): 126131beabSSimon Glass """Set up a new Expr object. 136131beabSSimon Glass 146131beabSSimon Glass Args: 156131beabSSimon Glass expr: String cotaining regular expression to store 166131beabSSimon Glass """ 176131beabSSimon Glass self._expr = expr 186131beabSSimon Glass self._re = re.compile(expr) 196131beabSSimon Glass 206131beabSSimon Glass def Matches(self, props): 216131beabSSimon Glass """Check if any of the properties match the regular expression. 226131beabSSimon Glass 236131beabSSimon Glass Args: 246131beabSSimon Glass props: List of properties to check 256131beabSSimon Glass Returns: 266131beabSSimon Glass True if any of the properties match the regular expression 276131beabSSimon Glass """ 286131beabSSimon Glass for prop in props: 296131beabSSimon Glass if self._re.match(prop): 306131beabSSimon Glass return True 316131beabSSimon Glass return False 326131beabSSimon Glass 336131beabSSimon Glass def __str__(self): 346131beabSSimon Glass return self._expr 356131beabSSimon Glass 366131beabSSimon Glassclass Term: 376131beabSSimon Glass """A list of expressions each of which must match with properties. 386131beabSSimon Glass 396131beabSSimon Glass This provides a list of 'AND' expressions, meaning that each must 406131beabSSimon Glass match the board properties for that board to be built. 416131beabSSimon Glass """ 426131beabSSimon Glass def __init__(self): 436131beabSSimon Glass self._expr_list = [] 446131beabSSimon Glass self._board_count = 0 456131beabSSimon Glass 466131beabSSimon Glass def AddExpr(self, expr): 476131beabSSimon Glass """Add an Expr object to the list to check. 486131beabSSimon Glass 496131beabSSimon Glass Args: 506131beabSSimon Glass expr: New Expr object to add to the list of those that must 516131beabSSimon Glass match for a board to be built. 526131beabSSimon Glass """ 536131beabSSimon Glass self._expr_list.append(Expr(expr)) 546131beabSSimon Glass 556131beabSSimon Glass def __str__(self): 566131beabSSimon Glass """Return some sort of useful string describing the term""" 576131beabSSimon Glass return '&'.join([str(expr) for expr in self._expr_list]) 586131beabSSimon Glass 596131beabSSimon Glass def Matches(self, props): 606131beabSSimon Glass """Check if any of the properties match this term 616131beabSSimon Glass 626131beabSSimon Glass Each of the expressions in the term is checked. All must match. 636131beabSSimon Glass 646131beabSSimon Glass Args: 656131beabSSimon Glass props: List of properties to check 666131beabSSimon Glass Returns: 676131beabSSimon Glass True if all of the expressions in the Term match, else False 686131beabSSimon Glass """ 696131beabSSimon Glass for expr in self._expr_list: 706131beabSSimon Glass if not expr.Matches(props): 716131beabSSimon Glass return False 726131beabSSimon Glass return True 736131beabSSimon Glass 74fc3fe1c2SSimon Glassclass Board: 75fc3fe1c2SSimon Glass """A particular board that we can build""" 7603c1bb24SAndreas Bießmann def __init__(self, status, arch, cpu, soc, vendor, board_name, target, options): 77fc3fe1c2SSimon Glass """Create a new board type. 78fc3fe1c2SSimon Glass 79fc3fe1c2SSimon Glass Args: 8003c1bb24SAndreas Bießmann status: define whether the board is 'Active' or 'Orphaned' 81fc3fe1c2SSimon Glass arch: Architecture name (e.g. arm) 82fc3fe1c2SSimon Glass cpu: Cpu name (e.g. arm1136) 83fc3fe1c2SSimon Glass soc: Name of SOC, or '' if none (e.g. mx31) 8403c1bb24SAndreas Bießmann vendor: Name of vendor (e.g. armltd) 8503c1bb24SAndreas Bießmann board_name: Name of board (e.g. integrator) 8673f30b9bSMasahiro Yamada target: Target name (use make <target>_defconfig to configure) 87fc3fe1c2SSimon Glass options: board-specific options (e.g. integratorcp:CM1136) 88fc3fe1c2SSimon Glass """ 89fc3fe1c2SSimon Glass self.target = target 90fc3fe1c2SSimon Glass self.arch = arch 91fc3fe1c2SSimon Glass self.cpu = cpu 92fc3fe1c2SSimon Glass self.board_name = board_name 93fc3fe1c2SSimon Glass self.vendor = vendor 94fc3fe1c2SSimon Glass self.soc = soc 95fc3fe1c2SSimon Glass self.options = options 96e0f2406eSTom Rini self.props = [self.target, self.arch, self.cpu, self.board_name, 97e0f2406eSTom Rini self.vendor, self.soc, self.options] 98fc3fe1c2SSimon Glass self.build_it = False 99fc3fe1c2SSimon Glass 100fc3fe1c2SSimon Glass 101fc3fe1c2SSimon Glassclass Boards: 102fc3fe1c2SSimon Glass """Manage a list of boards.""" 103fc3fe1c2SSimon Glass def __init__(self): 104fc3fe1c2SSimon Glass # Use a simple list here, sinc OrderedDict requires Python 2.7 105fc3fe1c2SSimon Glass self._boards = [] 106fc3fe1c2SSimon Glass 107fc3fe1c2SSimon Glass def AddBoard(self, board): 108fc3fe1c2SSimon Glass """Add a new board to the list. 109fc3fe1c2SSimon Glass 110fc3fe1c2SSimon Glass The board's target member must not already exist in the board list. 111fc3fe1c2SSimon Glass 112fc3fe1c2SSimon Glass Args: 113fc3fe1c2SSimon Glass board: board to add 114fc3fe1c2SSimon Glass """ 115fc3fe1c2SSimon Glass self._boards.append(board) 116fc3fe1c2SSimon Glass 117fc3fe1c2SSimon Glass def ReadBoards(self, fname): 118fc3fe1c2SSimon Glass """Read a list of boards from a board file. 119fc3fe1c2SSimon Glass 120fc3fe1c2SSimon Glass Create a board object for each and add it to our _boards list. 121fc3fe1c2SSimon Glass 122fc3fe1c2SSimon Glass Args: 123fc3fe1c2SSimon Glass fname: Filename of boards.cfg file 124fc3fe1c2SSimon Glass """ 125fc3fe1c2SSimon Glass with open(fname, 'r') as fd: 126fc3fe1c2SSimon Glass for line in fd: 127fc3fe1c2SSimon Glass if line[0] == '#': 128fc3fe1c2SSimon Glass continue 129fc3fe1c2SSimon Glass fields = line.split() 130fc3fe1c2SSimon Glass if not fields: 131fc3fe1c2SSimon Glass continue 132fc3fe1c2SSimon Glass for upto in range(len(fields)): 133fc3fe1c2SSimon Glass if fields[upto] == '-': 134fc3fe1c2SSimon Glass fields[upto] = '' 13503c1bb24SAndreas Bießmann while len(fields) < 8: 136fc3fe1c2SSimon Glass fields.append('') 13703c1bb24SAndreas Bießmann if len(fields) > 8: 13803c1bb24SAndreas Bießmann fields = fields[:8] 139fc3fe1c2SSimon Glass 140fc3fe1c2SSimon Glass board = Board(*fields) 141fc3fe1c2SSimon Glass self.AddBoard(board) 142fc3fe1c2SSimon Glass 143fc3fe1c2SSimon Glass 144fc3fe1c2SSimon Glass def GetList(self): 145fc3fe1c2SSimon Glass """Return a list of available boards. 146fc3fe1c2SSimon Glass 147fc3fe1c2SSimon Glass Returns: 148fc3fe1c2SSimon Glass List of Board objects 149fc3fe1c2SSimon Glass """ 150fc3fe1c2SSimon Glass return self._boards 151fc3fe1c2SSimon Glass 152fc3fe1c2SSimon Glass def GetDict(self): 153fc3fe1c2SSimon Glass """Build a dictionary containing all the boards. 154fc3fe1c2SSimon Glass 155fc3fe1c2SSimon Glass Returns: 156fc3fe1c2SSimon Glass Dictionary: 157fc3fe1c2SSimon Glass key is board.target 158fc3fe1c2SSimon Glass value is board 159fc3fe1c2SSimon Glass """ 160fc3fe1c2SSimon Glass board_dict = {} 161fc3fe1c2SSimon Glass for board in self._boards: 162fc3fe1c2SSimon Glass board_dict[board.target] = board 163fc3fe1c2SSimon Glass return board_dict 164fc3fe1c2SSimon Glass 165fc3fe1c2SSimon Glass def GetSelectedDict(self): 166fc3fe1c2SSimon Glass """Return a dictionary containing the selected boards 167fc3fe1c2SSimon Glass 168fc3fe1c2SSimon Glass Returns: 169fc3fe1c2SSimon Glass List of Board objects that are marked selected 170fc3fe1c2SSimon Glass """ 171fc3fe1c2SSimon Glass board_dict = {} 172fc3fe1c2SSimon Glass for board in self._boards: 173fc3fe1c2SSimon Glass if board.build_it: 174fc3fe1c2SSimon Glass board_dict[board.target] = board 175fc3fe1c2SSimon Glass return board_dict 176fc3fe1c2SSimon Glass 177fc3fe1c2SSimon Glass def GetSelected(self): 178fc3fe1c2SSimon Glass """Return a list of selected boards 179fc3fe1c2SSimon Glass 180fc3fe1c2SSimon Glass Returns: 181fc3fe1c2SSimon Glass List of Board objects that are marked selected 182fc3fe1c2SSimon Glass """ 183fc3fe1c2SSimon Glass return [board for board in self._boards if board.build_it] 184fc3fe1c2SSimon Glass 185fc3fe1c2SSimon Glass def GetSelectedNames(self): 186fc3fe1c2SSimon Glass """Return a list of selected boards 187fc3fe1c2SSimon Glass 188fc3fe1c2SSimon Glass Returns: 189fc3fe1c2SSimon Glass List of board names that are marked selected 190fc3fe1c2SSimon Glass """ 191fc3fe1c2SSimon Glass return [board.target for board in self._boards if board.build_it] 192fc3fe1c2SSimon Glass 1936131beabSSimon Glass def _BuildTerms(self, args): 1946131beabSSimon Glass """Convert command line arguments to a list of terms. 1956131beabSSimon Glass 1966131beabSSimon Glass This deals with parsing of the arguments. It handles the '&' 1976131beabSSimon Glass operator, which joins several expressions into a single Term. 1986131beabSSimon Glass 1996131beabSSimon Glass For example: 2006131beabSSimon Glass ['arm & freescale sandbox', 'tegra'] 2016131beabSSimon Glass 2026131beabSSimon Glass will produce 3 Terms containing expressions as follows: 2036131beabSSimon Glass arm, freescale 2046131beabSSimon Glass sandbox 2056131beabSSimon Glass tegra 2066131beabSSimon Glass 2076131beabSSimon Glass The first Term has two expressions, both of which must match for 2086131beabSSimon Glass a board to be selected. 2096131beabSSimon Glass 2106131beabSSimon Glass Args: 2116131beabSSimon Glass args: List of command line arguments 2126131beabSSimon Glass Returns: 2136131beabSSimon Glass A list of Term objects 2146131beabSSimon Glass """ 2156131beabSSimon Glass syms = [] 2166131beabSSimon Glass for arg in args: 2176131beabSSimon Glass for word in arg.split(): 2186131beabSSimon Glass sym_build = [] 2196131beabSSimon Glass for term in word.split('&'): 2206131beabSSimon Glass if term: 2216131beabSSimon Glass sym_build.append(term) 2226131beabSSimon Glass sym_build.append('&') 2236131beabSSimon Glass syms += sym_build[:-1] 2246131beabSSimon Glass terms = [] 2256131beabSSimon Glass term = None 2266131beabSSimon Glass oper = None 2276131beabSSimon Glass for sym in syms: 2286131beabSSimon Glass if sym == '&': 2296131beabSSimon Glass oper = sym 2306131beabSSimon Glass elif oper: 2316131beabSSimon Glass term.AddExpr(sym) 2326131beabSSimon Glass oper = None 2336131beabSSimon Glass else: 2346131beabSSimon Glass if term: 2356131beabSSimon Glass terms.append(term) 2366131beabSSimon Glass term = Term() 2376131beabSSimon Glass term.AddExpr(sym) 2386131beabSSimon Glass if term: 2396131beabSSimon Glass terms.append(term) 2406131beabSSimon Glass return terms 2416131beabSSimon Glass 2423cf4ae6fSSimon Glass def SelectBoards(self, args, exclude=[]): 243fc3fe1c2SSimon Glass """Mark boards selected based on args 244fc3fe1c2SSimon Glass 245fc3fe1c2SSimon Glass Args: 2463cf4ae6fSSimon Glass args: List of strings specifying boards to include, either named, 2473cf4ae6fSSimon Glass or by their target, architecture, cpu, vendor or soc. If 2483cf4ae6fSSimon Glass empty, all boards are selected. 2493cf4ae6fSSimon Glass exclude: List of boards to exclude, regardless of 'args' 250fc3fe1c2SSimon Glass 251fc3fe1c2SSimon Glass Returns: 252*8d7523c5SSimon Glass Dictionary which holds the list of boards which were selected 253fc3fe1c2SSimon Glass due to each argument, arranged by argument. 254fc3fe1c2SSimon Glass """ 255fc3fe1c2SSimon Glass result = {} 2566131beabSSimon Glass terms = self._BuildTerms(args) 2576131beabSSimon Glass 258*8d7523c5SSimon Glass result['all'] = [] 2596131beabSSimon Glass for term in terms: 260*8d7523c5SSimon Glass result[str(term)] = [] 261fc3fe1c2SSimon Glass 2623cf4ae6fSSimon Glass exclude_list = [] 2633cf4ae6fSSimon Glass for expr in exclude: 2643cf4ae6fSSimon Glass exclude_list.append(Expr(expr)) 2653cf4ae6fSSimon Glass 266fc3fe1c2SSimon Glass for board in self._boards: 2673cf4ae6fSSimon Glass matching_term = None 2683cf4ae6fSSimon Glass build_it = False 2696131beabSSimon Glass if terms: 2708426d8b0SStephen Warren match = False 2716131beabSSimon Glass for term in terms: 2726131beabSSimon Glass if term.Matches(board.props): 2733cf4ae6fSSimon Glass matching_term = str(term) 2743cf4ae6fSSimon Glass build_it = True 2756131beabSSimon Glass break 276fc3fe1c2SSimon Glass else: 2773cf4ae6fSSimon Glass build_it = True 2783cf4ae6fSSimon Glass 2793cf4ae6fSSimon Glass # Check that it is not specifically excluded 2803cf4ae6fSSimon Glass for expr in exclude_list: 2813cf4ae6fSSimon Glass if expr.Matches(board.props): 2823cf4ae6fSSimon Glass build_it = False 2833cf4ae6fSSimon Glass break 2843cf4ae6fSSimon Glass 2853cf4ae6fSSimon Glass if build_it: 286fc3fe1c2SSimon Glass board.build_it = True 2873cf4ae6fSSimon Glass if matching_term: 288*8d7523c5SSimon Glass result[matching_term].append(board.target) 289*8d7523c5SSimon Glass result['all'].append(board.target) 290fc3fe1c2SSimon Glass 291fc3fe1c2SSimon Glass return result 292