From 0689036a35296a3d51685a0b671f805818f94af7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 11 Jun 2018 23:26:46 -0600 Subject: [PATCH] buildman: Add a --boards option to specify particular boards to build At present 'buildman sandbox' will build all 5 boards for the sandbox architecture rather than the single board 'sandbox'. The only current way to exclude sandbox_spl, sandbox_noblk, etc. is to use -x which is a bit clumbsy. Add a --boards option to allow individual build targets to be specified. Signed-off-by: Simon Glass --- tools/buildman/README | 12 +++++++++++- tools/buildman/board.py | 28 ++++++++++++++++++++++++---- tools/buildman/cmdline.py | 4 +++- tools/buildman/control.py | 20 +++++++++++++++++--- tools/buildman/test.py | 31 +++++++++++++++++-------------- 5 files changed, 72 insertions(+), 23 deletions(-) diff --git a/tools/buildman/README b/tools/buildman/README index 7660190..5a709c6 100644 --- a/tools/buildman/README +++ b/tools/buildman/README @@ -114,6 +114,10 @@ a few commits or boards, it will be pretty slow. As a tip, if you don't plan to use your machine for anything else, you can use -T to increase the number of threads beyond the default. + +Selecting which boards to build +=============================== + Buildman lets you build all boards, or a subset. Specify the subset by passing command-line arguments that list the desired board name, architecture name, SOC name, or anything else in the boards.cfg file. Multiple arguments are @@ -138,11 +142,17 @@ You can also use -x to specifically exclude some boards. For example: means to build all arm boards except nvidia, freescale and anything ending with 'ball'. +For building specific boards you can use the --boards option, which takes a +comma-separated list of board target names and be used multiple times on +the command line: + + buidman --boards sandbox,snow --boards + It is convenient to use the -n option to see what will be built based on the subset given. Use -v as well to get an actual list of boards. Buildman does not store intermediate object files. It optionally copies -the binary output into a directory when a build is successful. Size +the binary output into a directory when a build is successful (-k). Size information is always recorded. It needs a fair bit of disk space to work, typically 250MB per thread. diff --git a/tools/buildman/board.py b/tools/buildman/board.py index 272bac0..2a1d021 100644 --- a/tools/buildman/board.py +++ b/tools/buildman/board.py @@ -237,20 +237,30 @@ class Boards: terms.append(term) return terms - def SelectBoards(self, args, exclude=[]): + def SelectBoards(self, args, exclude=[], boards=None): """Mark boards selected based on args + Normally either boards (an explicit list of boards) or args (a list of + terms to match against) is used. It is possible to specify both, in + which case they are additive. + + If boards and args are both empty, all boards are selected. + 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' + boards: List of boards to build Returns: - Dictionary which holds the list of boards which were selected - due to each argument, arranged by argument. + Tuple + Dictionary which holds the list of boards which were selected + due to each argument, arranged by argument. + List of errors found """ result = {} + warnings = [] terms = self._BuildTerms(args) result['all'] = [] @@ -261,6 +271,7 @@ class Boards: for expr in exclude: exclude_list.append(Expr(expr)) + found = [] for board in self._boards: matching_term = None build_it = False @@ -271,6 +282,10 @@ class Boards: matching_term = str(term) build_it = True break + elif boards: + if board.target in boards: + build_it = True + found.append(board.target) else: build_it = True @@ -286,4 +301,9 @@ class Boards: result[matching_term].append(board.target) result['all'].append(board.target) - return result + if boards: + remaining = set(boards) - set(found) + if remaining: + warnings.append('Boards not found: %s\n' % ', '.join(remaining)) + + return result, warnings diff --git a/tools/buildman/cmdline.py b/tools/buildman/cmdline.py index e493b1a..49a8a13 100644 --- a/tools/buildman/cmdline.py +++ b/tools/buildman/cmdline.py @@ -18,6 +18,8 @@ def ParseArgs(): parser.add_option('-B', '--bloat', dest='show_bloat', action='store_true', default=False, help='Show changes in function code size for each board') + parser.add_option('--boards', type='string', action='append', + help='List of board names to build separated by comma') parser.add_option('-c', '--count', dest='count', type='int', default=-1, help='Run build on the top n commits') parser.add_option('-C', '--force-reconfig', dest='force_reconfig', @@ -102,7 +104,7 @@ def ParseArgs(): type='string', action='append', help='Specify a list of boards to exclude, separated by comma') - parser.usage += """ + parser.usage += """ [list of target/arch/cpu/board/vendor/soc to build] Build U-Boot for all commits in a branch. Use -n to do a dry run""" diff --git a/tools/buildman/control.py b/tools/buildman/control.py index bc08197..96f8ccf 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -41,7 +41,8 @@ def GetActionSummary(is_summary, commits, selected, options): GetPlural(options.threads), options.jobs, GetPlural(options.jobs)) return str -def ShowActions(series, why_selected, boards_selected, builder, options): +def ShowActions(series, why_selected, boards_selected, builder, options, + board_warnings): """Display a list of actions that we would take, if not a dry run. Args: @@ -55,6 +56,7 @@ def ShowActions(series, why_selected, boards_selected, builder, options): value is Board object builder: The builder that will be used to build the commits options: Command line options object + board_warnings: List of warnings obtained from board selected """ col = terminal.Color() print 'Dry run, so not doing much. But I would do this:' @@ -79,6 +81,9 @@ def ShowActions(series, why_selected, boards_selected, builder, options): print ' %s' % ' '.join(why_selected[arg]) print ('Total boards to build for each commit: %d\n' % len(why_selected['all'])) + if board_warnings: + for warning in board_warnings: + print col.Color(col.YELLOW, warning) def CheckOutputDir(output_dir): """Make sure that the output directory is not within the current directory @@ -210,7 +215,15 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, for arg in options.exclude: exclude += arg.split(',') - why_selected = boards.SelectBoards(args, exclude) + + if options.boards: + requested_boards = [] + for b in options.boards: + requested_boards += b.split(',') + else: + requested_boards = None + why_selected, board_warnings = boards.SelectBoards(args, exclude, + requested_boards) selected = boards.GetSelected() if not len(selected): sys.exit(col.Color(col.RED, 'No matching boards found')) @@ -292,7 +305,8 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, # For a dry run, just show our actions as a sanity check if options.dry_run: - ShowActions(series, why_selected, selected, builder, options) + ShowActions(series, why_selected, selected, builder, options, + board_warnings) else: builder.force_build = options.force_build builder.force_build_failures = options.force_build_failures diff --git a/tools/buildman/test.py b/tools/buildman/test.py index e0c9d6d..61a4626 100644 --- a/tools/buildman/test.py +++ b/tools/buildman/test.py @@ -313,60 +313,63 @@ class TestBuild(unittest.TestCase): def testBoardSingle(self): """Test single board selection""" self.assertEqual(self.boards.SelectBoards(['sandbox']), - {'all': ['board4'], 'sandbox': ['board4']}) + ({'all': ['board4'], 'sandbox': ['board4']}, [])) def testBoardArch(self): """Test single board selection""" self.assertEqual(self.boards.SelectBoards(['arm']), - {'all': ['board0', 'board1'], - 'arm': ['board0', 'board1']}) + ({'all': ['board0', 'board1'], + 'arm': ['board0', 'board1']}, [])) def testBoardArchSingle(self): """Test single board selection""" self.assertEqual(self.boards.SelectBoards(['arm sandbox']), - {'sandbox': ['board4'], + ({'sandbox': ['board4'], 'all': ['board0', 'board1', 'board4'], - 'arm': ['board0', 'board1']}) + 'arm': ['board0', 'board1']}, [])) def testBoardArchSingleMultiWord(self): """Test single board selection""" self.assertEqual(self.boards.SelectBoards(['arm', 'sandbox']), - {'sandbox': ['board4'], 'all': ['board0', 'board1', 'board4'], 'arm': ['board0', 'board1']}) + ({'sandbox': ['board4'], + 'all': ['board0', 'board1', 'board4'], + 'arm': ['board0', 'board1']}, [])) def testBoardSingleAnd(self): """Test single board selection""" self.assertEqual(self.boards.SelectBoards(['Tester & arm']), - {'Tester&arm': ['board0', 'board1'], 'all': ['board0', 'board1']}) + ({'Tester&arm': ['board0', 'board1'], + 'all': ['board0', 'board1']}, [])) def testBoardTwoAnd(self): """Test single board selection""" self.assertEqual(self.boards.SelectBoards(['Tester', '&', 'arm', 'Tester' '&', 'powerpc', 'sandbox']), - {'sandbox': ['board4'], + ({'sandbox': ['board4'], 'all': ['board0', 'board1', 'board2', 'board3', 'board4'], 'Tester&powerpc': ['board2', 'board3'], - 'Tester&arm': ['board0', 'board1']}) + 'Tester&arm': ['board0', 'board1']}, [])) def testBoardAll(self): """Test single board selection""" self.assertEqual(self.boards.SelectBoards([]), - {'all': ['board0', 'board1', 'board2', 'board3', - 'board4']}) + ({'all': ['board0', 'board1', 'board2', 'board3', + 'board4']}, [])) def testBoardRegularExpression(self): """Test single board selection""" self.assertEqual(self.boards.SelectBoards(['T.*r&^Po']), - {'all': ['board2', 'board3'], - 'T.*r&^Po': ['board2', 'board3']}) + ({'all': ['board2', 'board3'], + 'T.*r&^Po': ['board2', 'board3']}, [])) def testBoardDuplicate(self): """Test single board selection""" self.assertEqual(self.boards.SelectBoards(['sandbox sandbox', 'sandbox']), - {'all': ['board4'], 'sandbox': ['board4']}) + ({'all': ['board4'], 'sandbox': ['board4']}, [])) def CheckDirs(self, build, dirname): self.assertEqual('base%s' % dirname, build._GetOutputDir(1)) self.assertEqual('base%s/fred' % dirname, -- 2.7.4