diff options
-rw-r--r-- | tools/buildman/README | 9 | ||||
-rw-r--r-- | tools/buildman/board.py | 144 | ||||
-rw-r--r-- | tools/buildman/test.py | 48 |
3 files changed, 184 insertions, 17 deletions
diff --git a/tools/buildman/README b/tools/buildman/README index aaf0a10f8f7..d4e840480a0 100644 --- a/tools/buildman/README +++ b/tools/buildman/README @@ -108,6 +108,15 @@ behaviour is a superset of exact or substring matching. Examples are: * '^tegra[23]0$' All boards with either Tegra20 or Tegra30 SoC * 'powerpc' All PowerPC boards +While the default is to OR the terms together, you can also make use of +the '&' operator to limit the selection: + +* 'freescale & arm sandbox' All Freescale boards with ARM architecture, + plus sandbox + +It is convenient to use the -n option to see whaat will be built based on +the subset given. + Buildman does not store intermediate object files. It optionally copies the binary output into a directory when a build is successful. Size information is always recorded. It needs a fair bit of disk space to work, diff --git a/tools/buildman/board.py b/tools/buildman/board.py index 7bcc93262eb..a3332876240 100644 --- a/tools/buildman/board.py +++ b/tools/buildman/board.py @@ -5,6 +5,72 @@ 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): @@ -124,6 +190,55 @@ class Boards: """ 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): """Mark boards selected based on args @@ -137,26 +252,21 @@ class Boards: due to each argument, arranged by argument. """ result = {} - argres = {} - for arg in args: - result[arg] = 0 - argres[arg] = re.compile(arg) + terms = self._BuildTerms(args) + result['all'] = 0 + for term in terms: + result[str(term)] = 0 for board in self._boards: - if args: - for arg in args: - argre = argres[arg] - match = False - for prop in board.props: - match = argre.match(prop) - if match: - break - if match: - if not board.build_it: - board.build_it = True - result[arg] += 1 - result['all'] += 1 + if terms: + match = False + for term in terms: + if term.Matches(board.props): + board.build_it = True + result[str(term)] += 1 + result['all'] += 1 + break else: board.build_it = True result['all'] += 1 diff --git a/tools/buildman/test.py b/tools/buildman/test.py index 502c9b4e80b..a51c9429e91 100644 --- a/tools/buildman/test.py +++ b/tools/buildman/test.py @@ -165,5 +165,53 @@ class TestBuild(unittest.TestCase): args = ['tegra20'] control.DoBuildman(options, args) + def testBoardSingle(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['sandbox']), + {'all': 1, 'sandbox': 1}) + + def testBoardArch(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['arm']), + {'all': 2, 'arm': 2}) + + def testBoardArchSingle(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['arm sandbox']), + {'all': 3, 'arm': 2, 'sandbox' : 1}) + + def testBoardArchSingleMultiWord(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['arm', 'sandbox']), + {'all': 3, 'arm': 2, 'sandbox' : 1}) + + def testBoardSingleAnd(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['Tester & arm']), + {'all': 2, 'Tester&arm': 2}) + + def testBoardTwoAnd(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['Tester', '&', 'arm', + 'Tester' '&', 'powerpc', + 'sandbox']), + {'all': 5, 'Tester&powerpc': 2, 'Tester&arm': 2, + 'sandbox' : 1}) + + def testBoardAll(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards([]), {'all': 5}) + + def testBoardRegularExpression(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['T.*r&^Po']), + {'T.*r&^Po': 2, 'all': 2}) + + def testBoardDuplicate(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['sandbox sandbox', + 'sandbox']), + {'all': 1, 'sandbox': 1}) + if __name__ == "__main__": unittest.main() |