X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=tools%2Fbuildman%2Fcontrol.py;h=a9c5022e48fb5b52c2e8bc56ad9f411adb714991;hb=7c66ead45267122c48bc854d1d5bd0d9a99bf943;hp=c2c54bf0e81b63676279391cec512358ee10bdcd;hpb=312a6c016a2d81aa3fbc605f5c0c315b6a4e3464;p=oweals%2Fu-boot.git diff --git a/tools/buildman/control.py b/tools/buildman/control.py index c2c54bf0e8..a9c5022e48 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -1,7 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ # Copyright (c) 2013 The Chromium OS Authors. # -# SPDX-License-Identifier: GPL-2.0+ -# import multiprocessing import os @@ -31,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' @@ -42,42 +41,71 @@ 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: series: Series object why_selected: Dictionary where each key is a buildman argument - provided by the user, and the value is the boards brought - in by that argument. For example, 'arm' might bring in - 400 boards, so in this case the key would be 'arm' and + provided by the user, and the value is the list of boards + brought in by that argument. For example, 'arm' might bring + in 400 boards, so in this case the key would be 'arm' and the value would be a list of board names. boards_selected: Dict of selected boards, key is target name, 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:' - 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' % why_selected[arg] - print ('Total boards to build for each commit: %d\n' % - why_selected['all']) + 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']))) + 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 + + 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. + + Args: + output_dir: Output directory path to check + """ + 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 def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, clean_dir=False): @@ -107,38 +135,74 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, return 0 gitutil.Setup() + col = terminal.Color() options.git_dir = os.path.join(options.git, '.git') - if not toolchains: - toolchains = toolchain.Toolchains() - toolchains.GetSettings() - toolchains.Scan(options.list_tool_chains) - if options.list_tool_chains: - toolchains.List() - print - return 0 + no_toolchains = toolchains is None + if no_toolchains: + toolchains = toolchain.Toolchains(options.override_toolchain) if options.fetch_arch: if options.fetch_arch == 'list': sorted_list = toolchains.ListArchs() - print '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 'Downloading toolchains: %s\n' % fetch_arch + print(col.Color(col.CYAN, '\nDownloading toolchains: %s' % + fetch_arch)) for arch in fetch_arch.split(','): + print() ret = toolchains.FetchAndInstall(arch) if ret: return ret return 0 + if no_toolchains: + toolchains.GetSettings() + toolchains.Scan(options.list_tool_chains and options.verbose) + if options.list_tool_chains: + toolchains.List() + print() + return 0 + + # 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, '-q', '-o', board_file]) + if status != 0: + sys.exit("Failed to generate boards.cfg") + + boards = board.Boards() + boards.ReadBoards(board_file) + + exclude = [] + if options.exclude: + for arg in options.exclude: + exclude += arg.split(',') + + 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')) + # 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: @@ -157,7 +221,7 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, sys.exit(col.Color(col.RED, "Range '%s' has no commits" % options.branch)) if msg: - print col.Color(col.YELLOW, msg) + print(col.Color(col.YELLOW, msg)) count += 1 # Build upstream commit also if not count: @@ -165,27 +229,6 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, "set branch's upstream or use -c flag" % options.branch) sys.exit(col.Color(col.RED, str)) - # Work out what subset of the boards we are building - if not boards: - board_file = os.path.join(options.git, 'boards.cfg') - status = subprocess.call([os.path.join(options.git, - 'tools/genboardscfg.py')]) - if status != 0: - sys.exit("Failed to generate boards.cfg") - - 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')) - # 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 @@ -215,9 +258,10 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, options.git_dir, count, series=None, allow_overwrite=True) else: series = None - options.verbose = True - if not options.summary: - options.show_errors = True + if not options.dry_run: + options.verbose = 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. @@ -225,13 +269,13 @@ 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 gnu_make = command.Output(os.path.join(options.git, - 'scripts/show-gnu-make')).rstrip() + 'scripts/show-gnu-make'), raise_on_error=False).rstrip() if not gnu_make: sys.exit('GNU Make not found') @@ -243,21 +287,27 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, # 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) + 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) + verbose_build=options.verbose_build, + incremental=options.incremental, + 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) 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: - 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 @@ -284,7 +334,8 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, builder.SetDisplayOptions(options.show_errors, options.show_sizes, options.show_detail, options.show_bloat, options.list_error_boards, - options.show_config) + options.show_config, + options.show_environment) if options.summary: builder.ShowSummary(commits, board_selected) else: