Merge tag 'u-boot-rockchip-20200501' of https://gitlab.denx.de/u-boot/custodians...
[platform/kernel/u-boot.git] / tools / buildman / control.py
index 9787b86..071c261 100644 (file)
@@ -5,18 +5,18 @@
 import multiprocessing
 import os
 import shutil
+import subprocess
 import sys
 
-import board
-import bsettings
-from builder import Builder
-import gitutil
-import patchstream
-import terminal
-from terminal import Print
-import toolchain
-import command
-import subprocess
+from buildman import board
+from buildman import bsettings
+from buildman import toolchain
+from buildman.builder import Builder
+from patman import command
+from patman import gitutil
+from patman import patchstream
+from patman import terminal
+from patman.terminal import Print
 
 def GetPlural(count):
     """Returns a plural 's' if count is not 1"""
@@ -30,7 +30,7 @@ def GetActionSummary(is_summary, commits, selected, options):
     """
     if commits:
         count = len(commits)
-        count = (count + options.step - 1) / options.step
+        count = (count + options.step - 1) // options.step
         commit_str = '%d commit%s' % (count, GetPlural(count))
     else:
         commit_str = 'current source'
@@ -59,53 +59,55 @@ def ShowActions(series, why_selected, boards_selected, builder, options,
         board_warnings: List of warnings obtained from board selected
     """
     col = terminal.Color()
-    print 'Dry run, so not doing much. But I would do this:'
-    print
+    print('Dry run, so not doing much. But I would do this:')
+    print()
     if series:
         commits = series.commits
     else:
         commits = None
-    print GetActionSummary(False, commits, boards_selected,
-            options)
-    print 'Build directory: %s' % builder.base_dir
+    print(GetActionSummary(False, commits, boards_selected,
+            options))
+    print('Build directory: %s' % builder.base_dir)
     if commits:
         for upto in range(0, len(series.commits), options.step):
             commit = series.commits[upto]
-            print '   ', col.Color(col.YELLOW, commit.hash[:8], bright=False),
-            print commit.subject
-    print
+            print('   ', col.Color(col.YELLOW, commit.hash[:8], bright=False), end=' ')
+            print(commit.subject)
+    print()
     for arg in why_selected:
         if arg != 'all':
-            print arg, ': %d boards' % len(why_selected[arg])
+            print(arg, ': %d boards' % len(why_selected[arg]))
             if options.verbose:
-                print '   %s' % ' '.join(why_selected[arg])
-    print ('Total boards to build for each commit: %d\n' %
-            len(why_selected['all']))
+                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)
+            print(col.Color(col.YELLOW, warning))
 
-def CheckOutputDir(output_dir):
-    """Make sure that the output directory is not within the current directory
+def ShowToolchainPrefix(boards, toolchains):
+    """Show information about a the tool chain used by one or more boards
 
-    If we try to use an output directory which is within the current directory
-    (which is assumed to hold the U-Boot source) we may end up deleting the
-    U-Boot source code. Detect this and print an error in this case.
+    The function checks that all boards use the same toolchain, then prints
+    the correct value for CROSS_COMPILE.
 
     Args:
-        output_dir: Output directory path to check
+        boards: Boards object containing selected boards
+        toolchains: Toolchains object containing available toolchains
+
+    Return:
+        None on success, string error message otherwise
     """
-    path = os.path.realpath(output_dir)
-    cwd_path = os.path.realpath('.')
-    while True:
-        if os.path.realpath(path) == cwd_path:
-            Print("Cannot use output directory '%s' since it is within the current directory '%s'" %
-                  (path, cwd_path))
-            sys.exit(1)
-        parent = os.path.dirname(path)
-        if parent == path:
-            break
-        path = parent
+    boards = boards.GetSelectedDict()
+    tc_set = set()
+    for brd in boards.values():
+        tc_set.add(toolchains.Select(brd.arch))
+    if len(tc_set) != 1:
+        return 'Supplied boards must share one toolchain'
+        return False
+    tc = tc_set.pop()
+    print(tc.GetEnvArgs(toolchain.VAR_CROSS_COMPILE))
+    return None
 
 def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
                clean_dir=False):
@@ -146,17 +148,17 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
     if options.fetch_arch:
         if options.fetch_arch == 'list':
             sorted_list = toolchains.ListArchs()
-            print col.Color(col.BLUE, 'Available architectures: %s\n' %
-                            ' '.join(sorted_list))
+            print(col.Color(col.BLUE, '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 col.Color(col.CYAN, '\nDownloading toolchains: %s' %
-                                fetch_arch)
+                print(col.Color(col.CYAN, '\nDownloading toolchains: %s' %
+                                fetch_arch))
             for arch in fetch_arch.split(','):
-                print
+                print()
                 ret = toolchains.FetchAndInstall(arch)
                 if ret:
                     return ret
@@ -167,43 +169,24 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
         toolchains.Scan(options.list_tool_chains and options.verbose)
     if options.list_tool_chains:
         toolchains.List()
-        print
+        print()
         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.
-    count = options.count
-    has_range = options.branch and '..' in options.branch
-    if count == -1:
-        if not options.branch:
-            count = 1
-        else:
-            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:
-                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:
-        str = ("No commits found to process in branch '%s': "
-               "set branch's upstream or use -c flag" % options.branch)
-        sys.exit(col.Color(col.RED, str))
+    if options.incremental:
+        print(col.Color(col.RED,
+                        'Warning: -I has been removed. See documentation'))
+    if not options.output_dir:
+        if options.work_in_output:
+            sys.exit(col.Color(col.RED, '-w requires that you specify -o'))
+        options.output_dir = '..'
 
     # Work out what subset of the boards we are building
     if not boards:
+        if not os.path.exists(options.output_dir):
+            os.makedirs(options.output_dir)
         board_file = os.path.join(options.output_dir, 'boards.cfg')
         genboardscfg = os.path.join(options.git, 'tools/genboardscfg.py')
-        status = subprocess.call([genboardscfg, '-o', board_file])
+        status = subprocess.call([genboardscfg, '-q', '-o', board_file])
         if status != 0:
             sys.exit("Failed to generate boards.cfg")
 
@@ -215,7 +198,6 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
         for arg in options.exclude:
             exclude += arg.split(',')
 
-
     if options.boards:
         requested_boards = []
         for b in options.boards:
@@ -228,6 +210,48 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
     if not len(selected):
         sys.exit(col.Color(col.RED, 'No matching boards found'))
 
+    if options.print_prefix:
+        err = ShowToolchainPrefix(boards, toolchains)
+        if err:
+            sys.exit(col.Color(col.RED, err))
+        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.
+    count = options.count
+    has_range = options.branch and '..' in options.branch
+    if count == -1:
+        if not options.branch:
+            count = 1
+        else:
+            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:
+                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:
+        str = ("No commits found to process in branch '%s': "
+               "set branch's upstream or use -c flag" % options.branch)
+        sys.exit(col.Color(col.RED, str))
+    if options.work_in_output:
+        if len(selected) != 1:
+            sys.exit(col.Color(col.RED,
+                               '-w can only be used with a single board'))
+        if count != 1:
+            sys.exit(col.Color(col.RED,
+                               '-w can only be used with a single commit'))
+
     # Read the metadata from the commits. First look at the upstream commit,
     # then the ones in the branch. We would like to do something like
     # upstream/master~..branch but that isn't possible if upstream/master is
@@ -268,7 +292,7 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
         options.threads = min(multiprocessing.cpu_count(), len(selected))
     if not options.jobs:
         options.jobs = max(1, (multiprocessing.cpu_count() +
-                len(selected) - 1) / len(selected))
+                len(selected) - 1) // len(selected))
 
     if not options.step:
         options.step = len(series.commits) - 1
@@ -288,17 +312,17 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
             output_dir = os.path.join(options.output_dir, dirname)
         if clean_dir and os.path.exists(output_dir):
             shutil.rmtree(output_dir)
-    CheckOutputDir(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,
             no_subdirs=options.no_subdirs, full_path=options.full_path,
             verbose_build=options.verbose_build,
-            incremental=options.incremental,
+            mrproper=options.mrproper,
             per_board_out_dir=options.per_board_out_dir,
             config_only=options.config_only,
             squash_config_y=not options.preserve_config_y,
-            warnings_as_errors=options.warnings_as_errors)
+            warnings_as_errors=options.warnings_as_errors,
+            work_in_output=options.work_in_output)
     builder.force_config_on_failure = not options.quick
     if make_func:
         builder.do_make = make_func
@@ -325,23 +349,23 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None,
             commits = None
 
         Print(GetActionSummary(options.summary, commits, board_selected,
-                                options))
+                               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.list_error_boards,
-                                  options.show_config,
-                                  options.show_environment)
+        builder.SetDisplayOptions(
+            options.show_errors, options.show_sizes, options.show_detail,
+            options.show_bloat, options.list_error_boards, options.show_config,
+            options.show_environment, options.filter_dtb_warnings,
+            options.filter_migration_warnings)
         if options.summary:
             builder.ShowSummary(commits, board_selected)
         else:
             fail, warned = builder.BuildBoards(commits, board_selected,
                                 options.keep_outputs, options.verbose)
             if fail:
-                return 128
-            elif warned:
-                return 129
+                return 100
+            elif warned and not options.ignore_warnings:
+                return 101
     return 0