]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - tools/buildman/control.py
Merge branch 'tx53-bugfix'
[karo-tx-uboot.git] / tools / buildman / control.py
index d98e50ac1f74619e32a036097c2da3c3d588a3d4..8b3cd30c00119aa990cc0dcc22aa627aa567b400 100644 (file)
@@ -5,6 +5,7 @@
 
 import multiprocessing
 import os
+import shutil
 import sys
 
 import board
@@ -13,6 +14,7 @@ from builder import Builder
 import gitutil
 import patchstream
 import terminal
+from terminal import Print
 import toolchain
 import command
 import subprocess
@@ -68,7 +70,7 @@ def ShowActions(series, why_selected, boards_selected, builder, options):
     if commits:
         for upto in range(0, len(series.commits), options.step):
             commit = series.commits[upto]
-            print '   ', col.Color(col.YELLOW, commit.hash, bright=False),
+            print '   ', col.Color(col.YELLOW, commit.hash[:8], bright=False),
             print commit.subject
     print
     for arg in why_selected:
@@ -77,40 +79,84 @@ def ShowActions(series, why_selected, boards_selected, builder, options):
     print ('Total boards to build for each commit: %d\n' %
             why_selected['all'])
 
-def DoBuildman(options, args):
+def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
+               clean_dir=False):
     """The main control code for buildman
 
     Args:
         options: Command line options object
         args: Command line arguments (list of strings)
+        toolchains: Toolchains to use - this should be a Toolchains()
+                object. If None, then it will be created and scanned
+        make_func: Make function to use for the builder. This is called
+                to execute 'make'. If this is None, the normal function
+                will be used, which calls the 'make' tool with suitable
+                arguments. This setting is useful for tests.
+        board: Boards() object to use, containing a list of available
+                boards. If this is None it will be created and scanned.
     """
+    global builder
+
+    if options.full_help:
+        pager = os.getenv('PAGER')
+        if not pager:
+            pager = 'more'
+        fname = os.path.join(os.path.dirname(sys.argv[0]), 'README')
+        command.Run(pager, fname)
+        return 0
+
     gitutil.Setup()
 
-    bsettings.Setup(options.config_file)
     options.git_dir = os.path.join(options.git, '.git')
 
-    toolchains = toolchain.Toolchains()
-    toolchains.Scan(options.list_tool_chains)
+    if not toolchains:
+        toolchains = toolchain.Toolchains()
+        toolchains.GetSettings()
+        toolchains.Scan(options.list_tool_chains)
     if options.list_tool_chains:
         toolchains.List()
         print
-        return
+        return 0
+
+    if options.fetch_arch:
+        if options.fetch_arch == 'list':
+            sorted_list = toolchains.ListArchs()
+            print 'Available architectures: %s\n' % ' '.join(sorted_list)
+            return 0
+        else:
+            fetch_arch = options.fetch_arch
+            if fetch_arch == 'all':
+                fetch_arch = ','.join(toolchains.ListArchs())
+                print 'Downloading toolchains: %s\n' % fetch_arch
+            for arch in fetch_arch.split(','):
+                ret = toolchains.FetchAndInstall(arch)
+                if ret:
+                    return ret
+            return 0
 
     # Work out how many commits to build. We want to build everything on the
     # branch. We also build the upstream commit as a control so we can see
     # problems introduced by the first commit on the branch.
     col = terminal.Color()
     count = options.count
+    has_range = options.branch and '..' in options.branch
     if count == -1:
         if not options.branch:
             count = 1
         else:
-            count = gitutil.CountCommitsInBranch(options.git_dir,
-                                                 options.branch)
+            if has_range:
+                count, msg = gitutil.CountCommitsInRange(options.git_dir,
+                                                         options.branch)
+            else:
+                count, msg = gitutil.CountCommitsInBranch(options.git_dir,
+                                                          options.branch)
             if count is None:
-                str = ("Branch '%s' not found or has no upstream" %
-                       options.branch)
-                sys.exit(col.Color(col.RED, str))
+                sys.exit(col.Color(col.RED, msg))
+            elif count == 0:
+                sys.exit(col.Color(col.RED, "Range '%s' has no commits" %
+                                   options.branch))
+            if msg:
+                print col.Color(col.YELLOW, msg)
             count += 1   # Build upstream commit also
 
     if not count:
@@ -119,17 +165,22 @@ def DoBuildman(options, args):
         sys.exit(col.Color(col.RED, str))
 
     # Work out what subset of the boards we are building
-    board_file = os.path.join(options.git, 'boards.cfg')
-    if not os.path.exists(board_file):
-        print 'Could not find %s' % board_file
+    if not boards:
+        board_file = os.path.join(options.git, 'boards.cfg')
         status = subprocess.call([os.path.join(options.git,
-                                               'tools/genboardscfg.py')])
+                                                'tools/genboardscfg.py')])
         if status != 0:
-            sys.exit("Failed to generate boards.cfg")
+                sys.exit("Failed to generate boards.cfg")
 
-    boards = board.Boards()
-    boards.ReadBoards(os.path.join(options.git, 'boards.cfg'))
-    why_selected = boards.SelectBoards(args)
+        boards = board.Boards()
+        boards.ReadBoards(os.path.join(options.git, 'boards.cfg'))
+
+    exclude = []
+    if options.exclude:
+        for arg in options.exclude:
+            exclude += arg.split(',')
+
+    why_selected = boards.SelectBoards(args, exclude)
     selected = boards.GetSelected()
     if not len(selected):
         sys.exit(col.Color(col.RED, 'No matching boards found'))
@@ -139,30 +190,33 @@ def DoBuildman(options, args):
     # upstream/master~..branch but that isn't possible if upstream/master is
     # a merge commit (it will list all the commits that form part of the
     # merge)
+    # Conflicting tags are not a problem for buildman, since it does not use
+    # them. For example, Series-version is not useful for buildman. On the
+    # other hand conflicting tags will cause an error. So allow later tags
+    # to overwrite earlier ones by setting allow_overwrite=True
     if options.branch:
         if count == -1:
-            range_expr = gitutil.GetRangeInBranch(options.git_dir,
-                                                  options.branch)
+            if has_range:
+                range_expr = options.branch
+            else:
+                range_expr = gitutil.GetRangeInBranch(options.git_dir,
+                                                      options.branch)
             upstream_commit = gitutil.GetUpstream(options.git_dir,
                                                   options.branch)
             series = patchstream.GetMetaDataForList(upstream_commit,
-                options.git_dir, 1)
+                options.git_dir, 1, series=None, allow_overwrite=True)
 
-            # Conflicting tags are not a problem for buildman, since it does
-            # not use them. For example, Series-version is not useful for
-            # buildman. On the other hand conflicting tags will cause an
-            # error. So allow later tags to overwrite earlier ones.
-            series.allow_overwrite = True
             series = patchstream.GetMetaDataForList(range_expr,
-                                              options.git_dir, None, series)
+                    options.git_dir, None, series, allow_overwrite=True)
         else:
             # Honour the count
             series = patchstream.GetMetaDataForList(options.branch,
-                                                    options.git_dir, count)
+                    options.git_dir, count, series=None, allow_overwrite=True)
     else:
         series = None
         options.verbose = True
-        options.show_errors = True
+        if not options.summary:
+            options.show_errors = True
 
     # By default we have one thread per CPU. But if there are not enough jobs
     # we can have fewer threads and use a high '-j' value for make.
@@ -180,16 +234,25 @@ def DoBuildman(options, args):
     if not gnu_make:
         sys.exit('GNU Make not found')
 
-    # Create a new builder with the selected options
+    # Create a new builder with the selected options.
+    output_dir = options.output_dir
     if options.branch:
-        dirname = options.branch
-    else:
-        dirname = 'current'
-    output_dir = os.path.join(options.output_dir, dirname)
+        dirname = options.branch.replace('/', '_')
+        # As a special case allow the board directory to be placed in the
+        # output directory itself rather than any subdirectory.
+        if not options.no_subdirs:
+            output_dir = os.path.join(options.output_dir, dirname)
+    if (clean_dir and output_dir != options.output_dir and
+            os.path.exists(output_dir)):
+        shutil.rmtree(output_dir)
     builder = Builder(toolchains, output_dir, options.git_dir,
             options.threads, options.jobs, gnu_make=gnu_make, checkout=True,
-            show_unknown=options.show_unknown, step=options.step)
+            show_unknown=options.show_unknown, step=options.step,
+            no_subdirs=options.no_subdirs, full_path=options.full_path,
+            verbose_build=options.verbose_build)
     builder.force_config_on_failure = not options.quick
+    if make_func:
+        builder.do_make = make_func
 
     # For a dry run, just show our actions as a sanity check
     if options.dry_run:
@@ -205,19 +268,29 @@ def DoBuildman(options, args):
 
         if series:
             commits = series.commits
+            # Number the commits for test purposes
+            for commit in range(len(commits)):
+                commits[commit].sequence = commit
         else:
             commits = None
 
-        print GetActionSummary(options.summary, commits, board_selected,
-                               options)
+        Print(GetActionSummary(options.summary, commits, board_selected,
+                                options))
 
+        # We can't show function sizes without board details at present
+        if options.show_bloat:
+            options.show_detail = True
         builder.SetDisplayOptions(options.show_errors, options.show_sizes,
-                                  options.show_detail, options.show_bloat)
+                                  options.show_detail, options.show_bloat,
+                                  options.list_error_boards,
+                                  options.show_config)
         if options.summary:
-            # We can't show function sizes without board details at present
-            if options.show_bloat:
-                options.show_detail = True
             builder.ShowSummary(commits, board_selected)
         else:
-            builder.BuildBoards(commits, board_selected,
+            fail, warned = builder.BuildBoards(commits, board_selected,
                                 options.keep_outputs, options.verbose)
+            if fail:
+                return 128
+            elif warned:
+                return 129
+    return 0