buildman: Convert to argparse

Use argparse to parse the arguments, since OptionParser is deprecated now.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/buildman/cmdline.py b/tools/buildman/cmdline.py
index 660a83b..a5febe9 100644
--- a/tools/buildman/cmdline.py
+++ b/tools/buildman/cmdline.py
@@ -7,7 +7,7 @@
 This creates the argument parser and uses it to parse the arguments passed in
 """
 
-from optparse import OptionParser
+import argparse
 import os
 import pathlib
 
@@ -22,137 +22,141 @@
             options: command line options
             args: command lin arguments
     """
-    parser = OptionParser()
-    parser.add_option('-a', '--adjust-cfg', type=str, action='append',
+    epilog = """ [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"""
+
+    parser = argparse.ArgumentParser(epilog=epilog)
+    parser.add_argument('-a', '--adjust-cfg', type=str, action='append',
           help='Adjust the Kconfig settings in .config before building')
-    parser.add_option('-A', '--print-prefix', action='store_true',
+    parser.add_argument('-A', '--print-prefix', action='store_true',
           help='Print the tool-chain prefix for a board (CROSS_COMPILE=)')
-    parser.add_option('-b', '--branch', type='string',
+    parser.add_argument('-b', '--branch', type=str,
           help='Branch name to build, or range of commits to build')
-    parser.add_option('-B', '--bloat', dest='show_bloat',
+    parser.add_argument('-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',
+    parser.add_argument('--boards', type=str, action='append',
           help='List of board names to build separated by comma')
-    parser.add_option('-c', '--count', dest='count', type='int',
+    parser.add_argument('-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',
+    parser.add_argument('-C', '--force-reconfig', dest='force_reconfig',
           action='store_true', default=False,
           help='Reconfigure for every commit (disable incremental build)')
-    parser.add_option('-d', '--detail', dest='show_detail',
+    parser.add_argument('-d', '--detail', dest='show_detail',
           action='store_true', default=False,
           help='Show detailed size delta for each board in the -S summary')
-    parser.add_option('-D', '--config-only', action='store_true', default=False,
+    parser.add_argument('-D', '--config-only', action='store_true',
+                        default=False,
           help="Don't build, just configure each commit")
-    parser.add_option('--debug', action='store_true',
+    parser.add_argument('--debug', action='store_true',
         help='Enabling debugging (provides a full traceback on error)')
-    parser.add_option('-e', '--show_errors', action='store_true',
+    parser.add_argument('-e', '--show_errors', action='store_true',
           default=False, help='Show errors and warnings')
-    parser.add_option('-E', '--warnings-as-errors', action='store_true',
+    parser.add_argument('-E', '--warnings-as-errors', action='store_true',
           default=False, help='Treat all compiler warnings as errors')
-    parser.add_option('-f', '--force-build', dest='force_build',
+    parser.add_argument('-f', '--force-build', dest='force_build',
           action='store_true', default=False,
           help='Force build of boards even if already built')
-    parser.add_option('-F', '--force-build-failures', dest='force_build_failures',
+    parser.add_argument('-F', '--force-build-failures', dest='force_build_failures',
           action='store_true', default=False,
           help='Force build of previously-failed build')
-    parser.add_option('--fetch-arch', type='string',
+    parser.add_argument('--fetch-arch', type=str,
           help="Fetch a toolchain for architecture FETCH_ARCH ('list' to list)."
               ' You can also fetch several toolchains separate by comma, or'
               " 'all' to download all")
-    parser.add_option('-g', '--git', type='string',
+    parser.add_argument('-g', '--git', type=str,
           help='Git repo containing branch to build', default='.')
-    parser.add_option('-G', '--config-file', type='string',
+    parser.add_argument('-G', '--config-file', type=str,
           help='Path to buildman config file', default='')
-    parser.add_option('-H', '--full-help', action='store_true', dest='full_help',
+    parser.add_argument('-H', '--full-help', action='store_true', dest='full_help',
           default=False, help='Display the README file')
-    parser.add_option('-i', '--in-tree', dest='in_tree',
+    parser.add_argument('-i', '--in-tree', dest='in_tree',
           action='store_true', default=False,
           help='Build in the source tree instead of a separate directory')
-    parser.add_option('-I', '--ide', action='store_true', default=False,
+    parser.add_argument('-I', '--ide', action='store_true', default=False,
           help='Create build output that can be parsed by an IDE')
-    parser.add_option('-j', '--jobs', dest='jobs', type='int',
+    parser.add_argument('-j', '--jobs', dest='jobs', type=int,
           default=None, help='Number of jobs to run at once (passed to make)')
-    parser.add_option('-k', '--keep-outputs', action='store_true',
+    parser.add_argument('-k', '--keep-outputs', action='store_true',
           default=False, help='Keep all build output files (e.g. binaries)')
-    parser.add_option('-K', '--show-config', action='store_true',
+    parser.add_argument('-K', '--show-config', action='store_true',
           default=False,
           help='Show configuration changes in summary (both board config files and Kconfig)')
-    parser.add_option('--preserve-config-y', action='store_true',
+    parser.add_argument('--preserve-config-y', action='store_true',
           default=False, help="Don't convert y to 1 in configs")
-    parser.add_option('-l', '--list-error-boards', action='store_true',
+    parser.add_argument('-l', '--list-error-boards', action='store_true',
           default=False, help='Show a list of boards next to each error/warning')
-    parser.add_option('-L', '--no-lto', action='store_true',
+    parser.add_argument('-L', '--no-lto', action='store_true',
           default=False, help='Disable Link-time Optimisation (LTO) for builds')
-    parser.add_option('--list-tool-chains', action='store_true', default=False,
+    parser.add_argument('--list-tool-chains', action='store_true', default=False,
           help='List available tool chains (use -v to see probing detail)')
-    parser.add_option('-m', '--mrproper', action='store_true',
+    parser.add_argument('-m', '--mrproper', action='store_true',
           default=False, help="Run 'make mrproper before reconfiguring")
-    parser.add_option(
+    parser.add_argument(
           '-M', '--allow-missing', action='store_true', default=False,
           help='Tell binman to allow missing blobs and generate fake ones as needed')
-    parser.add_option('--maintainer-check', action='store_true',
-                      help='Check that maintainer entries exist for each board')
-    parser.add_option(
+    parser.add_argument(
+          '--maintainer-check', action='store_true',
+          help='Check that maintainer entries exist for each board')
+    parser.add_argument(
           '--no-allow-missing', action='store_true', default=False,
           help='Disable telling binman to allow missing blobs')
-    parser.add_option('-n', '--dry-run', action='store_true', dest='dry_run',
+    parser.add_argument('-n', '--dry-run', action='store_true', dest='dry_run',
           default=False, help="Do a dry run (describe actions, but do nothing)")
-    parser.add_option('-N', '--no-subdirs', action='store_true', dest='no_subdirs',
+    parser.add_argument('-N', '--no-subdirs', action='store_true', dest='no_subdirs',
           default=False,
           help="Don't create subdirectories when building current source for a single board")
-    parser.add_option('-o', '--output-dir', type='string', dest='output_dir',
+    parser.add_argument('-o', '--output-dir', type=str, dest='output_dir',
           help='Directory where all builds happen and buildman has its workspace (default is ../)')
-    parser.add_option('-O', '--override-toolchain', type='string',
+    parser.add_argument('-O', '--override-toolchain', type=str,
           help="Override host toochain to use for sandbox (e.g. 'clang-7')")
-    parser.add_option('-Q', '--quick', action='store_true',
+    parser.add_argument('-Q', '--quick', action='store_true',
           default=False, help='Do a rough build, with limited warning resolution')
-    parser.add_option('-p', '--full-path', action='store_true',
+    parser.add_argument('-p', '--full-path', action='store_true',
           default=False, help="Use full toolchain path in CROSS_COMPILE")
-    parser.add_option('-P', '--per-board-out-dir', action='store_true',
+    parser.add_argument('-P', '--per-board-out-dir', action='store_true',
           default=False, help="Use an O= (output) directory per board rather than per thread")
-    parser.add_option('-r', '--reproducible-builds', action='store_true',
+    parser.add_argument('-r', '--reproducible-builds', action='store_true',
           help='Set SOURCE_DATE_EPOCH=0 to suuport a reproducible build')
-    parser.add_option('-R', '--regen-board-list', type='string',
+    parser.add_argument('-R', '--regen-board-list', type=str,
           help='Force regeneration of the list of boards, like the old boards.cfg file')
-    parser.add_option('-s', '--summary', action='store_true',
+    parser.add_argument('-s', '--summary', action='store_true',
           default=False, help='Show a build summary')
-    parser.add_option('-S', '--show-sizes', action='store_true',
+    parser.add_argument('-S', '--show-sizes', action='store_true',
           default=False, help='Show image size variation in summary')
-    parser.add_option('--step', type='int',
+    parser.add_argument('--step', type=int,
           default=1, help='Only build every n commits (0=just first and last)')
     if HAS_TESTS:
-        parser.add_option('--skip-net-tests', action='store_true', default=False,
+        parser.add_argument('--skip-net-tests', action='store_true', default=False,
                           help='Skip tests which need the network')
-        parser.add_option('-t', '--test', action='store_true', dest='test',
+        parser.add_argument('-t', '--test', action='store_true', dest='test',
                           default=False, help='run tests')
-    parser.add_option('-T', '--threads', type='int',
+    parser.add_argument('-T', '--threads', type=int,
           default=None,
           help='Number of builder threads to use (0=single-thread)')
-    parser.add_option('-u', '--show_unknown', action='store_true',
+    parser.add_argument('-u', '--show_unknown', action='store_true',
           default=False, help='Show boards with unknown build result')
-    parser.add_option('-U', '--show-environment', action='store_true',
+    parser.add_argument('-U', '--show-environment', action='store_true',
           default=False, help='Show environment changes in summary')
-    parser.add_option('-v', '--verbose', action='store_true',
+    parser.add_argument('-v', '--verbose', action='store_true',
           default=False, help='Show build results while the build progresses')
-    parser.add_option('-V', '--verbose-build', action='store_true',
+    parser.add_argument('-V', '--verbose-build', action='store_true',
           default=False, help='Run make with V=1, logging all output')
-    parser.add_option('-w', '--work-in-output', action='store_true',
+    parser.add_argument('-w', '--work-in-output', action='store_true',
           default=False, help='Use the output directory as the work directory')
-    parser.add_option('-W', '--ignore-warnings', action='store_true',
+    parser.add_argument('-W', '--ignore-warnings', action='store_true',
           default=False, help='Return success even if there are warnings')
-    parser.add_option('-x', '--exclude', dest='exclude',
-          type='string', action='append',
+    parser.add_argument('-x', '--exclude', dest='exclude',
+          type=str, action='append',
           help='Specify a list of boards to exclude, separated by comma')
-    parser.add_option('-y', '--filter-dtb-warnings', action='store_true',
+    parser.add_argument('-y', '--filter-dtb-warnings', action='store_true',
           default=False,
           help='Filter out device-tree-compiler warnings from output')
-    parser.add_option('-Y', '--filter-migration-warnings', action='store_true',
+    parser.add_argument('-Y', '--filter-migration-warnings', action='store_true',
           default=False,
           help='Filter out migration warnings from output')
-
-    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"""
+    parser.add_argument('terms', type=str, nargs='*',
+                        help='Board / SoC names to build')
 
     return parser.parse_args()
diff --git a/tools/buildman/control.py b/tools/buildman/control.py
index 3a9454c..cda2d40 100644
--- a/tools/buildman/control.py
+++ b/tools/buildman/control.py
@@ -429,35 +429,35 @@
     return selected, why_selected, board_warnings
 
 
-def adjust_options(options, series, selected):
-    """Adjust options according to various constraints
+def adjust_args(args, series, selected):
+    """Adjust arguments according to various constraints
 
     Updates verbose, show_errors, threads, jobs and step
 
     Args:
-        options (Options): Options object to adjust
+        args (Namespace): Namespace object to adjust
         series (Series): Series being built / summarised
         selected (list of Board): List of Board objects that are marked
     """
-    if not series and not options.dry_run:
-        options.verbose = True
-        if not options.summary:
-            options.show_errors = True
+    if not series and not args.dry_run:
+        args.verbose = True
+        if not args.summary:
+            args.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.
-    if options.threads is None:
-        options.threads = min(multiprocessing.cpu_count(), len(selected))
-    if not options.jobs:
-        options.jobs = max(1, (multiprocessing.cpu_count() +
+    if args.threads is None:
+        args.threads = min(multiprocessing.cpu_count(), len(selected))
+    if not args.jobs:
+        args.jobs = max(1, (multiprocessing.cpu_count() +
                 len(selected) - 1) // len(selected))
 
-    if not options.step:
-        options.step = len(series.commits) - 1
+    if not args.step:
+        args.step = len(series.commits) - 1
 
     # We can't show function sizes without board details at present
-    if options.show_bloat:
-        options.show_detail = True
+    if args.show_bloat:
+        args.show_detail = True
 
 
 def setup_output_dir(output_dir, work_in_output, branch, no_subdirs, col,
@@ -489,7 +489,7 @@
     return output_dir
 
 
-def run_builder(builder, commits, board_selected, options):
+def run_builder(builder, commits, board_selected, args):
     """Run the builder or show the summary
 
     Args:
@@ -497,37 +497,37 @@
         boards_selected (dict): Dict of selected boards:
             key: target name
             value: Board object
-        options (Options): Options to use
+        args (Namespace): Namespace to use
 
     Returns:
         int: Return code for buildman
     """
-    gnu_make = command.output(os.path.join(options.git,
+    gnu_make = command.output(os.path.join(args.git,
             'scripts/show-gnu-make'), raise_on_error=False).rstrip()
     if not gnu_make:
         sys.exit('GNU Make not found')
     builder.gnu_make = gnu_make
 
-    if not options.ide:
-        commit_count = count_build_commits(commits, options.step)
-        tprint(get_action_summary(options.summary, commit_count, board_selected,
-                                  options.threads, options.jobs))
+    if not args.ide:
+        commit_count = count_build_commits(commits, args.step)
+        tprint(get_action_summary(args.summary, commit_count, board_selected,
+                                  args.threads, args.jobs))
 
     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, options.ide)
-    if options.summary:
+        args.show_errors, args.show_sizes, args.show_detail,
+        args.show_bloat, args.list_error_boards, args.show_config,
+        args.show_environment, args.filter_dtb_warnings,
+        args.filter_migration_warnings, args.ide)
+    if args.summary:
         builder.ShowSummary(commits, board_selected)
     else:
         fail, warned, excs = builder.BuildBoards(
-            commits, board_selected, options.keep_outputs, options.verbose)
+            commits, board_selected, args.keep_outputs, args.verbose)
         if excs:
             return 102
         if fail:
             return 100
-        if warned and not options.ignore_warnings:
+        if warned and not args.ignore_warnings:
             return 101
     return 0
 
@@ -556,12 +556,12 @@
     return adjust_cfg
 
 
-def do_buildman(options, args, toolchains=None, make_func=None, brds=None,
+def do_buildman(args, toolchains=None, make_func=None, brds=None,
                 clean_dir=False, test_thread_exceptions=False):
     """The main control code for buildman
 
     Args:
-        options: Command line options object
+        args: ArgumentParser 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
@@ -583,68 +583,67 @@
     gitutil.setup()
     col = terminal.Color()
 
-    git_dir = os.path.join(options.git, '.git')
+    git_dir = os.path.join(args.git, '.git')
 
-    toolchains = get_toolchains(toolchains, col, options.override_toolchain,
-                                options.fetch_arch, options.list_tool_chains,
-                                options.verbose)
+    toolchains = get_toolchains(toolchains, col, args.override_toolchain,
+                                args.fetch_arch, args.list_tool_chains,
+                                args.verbose)
     output_dir = setup_output_dir(
-        options.output_dir, options.work_in_output, options.branch,
-        options.no_subdirs, col, clean_dir)
+        args.output_dir, args.work_in_output, args.branch,
+        args.no_subdirs, col, clean_dir)
 
     # Work out what subset of the boards we are building
     if not brds:
-        brds = get_boards_obj(output_dir, options.regen_board_list,
-                              options.maintainer_check, options.threads,
-                              options.verbose)
+        brds = get_boards_obj(output_dir, args.regen_board_list,
+                              args.maintainer_check, args.threads, args.verbose)
         if isinstance(brds, int):
             return brds
 
     selected, why_selected, board_warnings = determine_boards(
-        brds, args, col, options.boards, options.exclude)
+        brds, args.terms, col, args.boards, args.exclude)
 
-    if options.print_prefix:
+    if args.print_prefix:
         show_toolchain_prefix(brds, toolchains)
         return 0
 
-    series = determine_series(selected, col, git_dir, options.count,
-                              options.branch, options.work_in_output)
+    series = determine_series(selected, col, git_dir, args.count,
+                              args.branch, args.work_in_output)
 
-    adjust_options(options, series, selected)
+    adjust_args(args, series, selected)
 
     # For a dry run, just show our actions as a sanity check
-    if options.dry_run:
+    if args.dry_run:
         show_actions(series, why_selected, selected, output_dir, board_warnings,
-                     options.step, options.threads, options.jobs,
-                     options.verbose)
+                     args.step, args.threads, args.jobs,
+                     args.verbose)
         return 0
 
-    # Create a new builder with the selected options
+    # Create a new builder with the selected args
     builder = Builder(toolchains, output_dir, git_dir,
-            options.threads, options.jobs, 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,
-            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,
-            work_in_output=options.work_in_output,
+            args.threads, args.jobs, checkout=True,
+            show_unknown=args.show_unknown, step=args.step,
+            no_subdirs=args.no_subdirs, full_path=args.full_path,
+            verbose_build=args.verbose_build,
+            mrproper=args.mrproper,
+            per_board_out_dir=args.per_board_out_dir,
+            config_only=args.config_only,
+            squash_config_y=not args.preserve_config_y,
+            warnings_as_errors=args.warnings_as_errors,
+            work_in_output=args.work_in_output,
             test_thread_exceptions=test_thread_exceptions,
-            adjust_cfg=calc_adjust_cfg(options.adjust_cfg,
-                                       options.reproducible_builds),
-            allow_missing=get_allow_missing(options.allow_missing,
-                                            options.no_allow_missing,
-                                            len(selected), options.branch),
-            no_lto=options.no_lto,
-            reproducible_builds=options.reproducible_builds,
-            force_build = options.force_build,
-            force_build_failures = options.force_build_failures,
-            force_reconfig = options.force_reconfig, in_tree = options.in_tree,
-            force_config_on_failure=not options.quick, make_func=make_func)
+            adjust_cfg=calc_adjust_cfg(args.adjust_cfg,
+                                       args.reproducible_builds),
+            allow_missing=get_allow_missing(args.allow_missing,
+                                            args.no_allow_missing,
+                                            len(selected), args.branch),
+            no_lto=args.no_lto,
+            reproducible_builds=args.reproducible_builds,
+            force_build = args.force_build,
+            force_build_failures = args.force_build_failures,
+            force_reconfig = args.force_reconfig, in_tree = args.in_tree,
+            force_config_on_failure=not args.quick, make_func=make_func)
 
     TEST_BUILDER = builder
 
     return run_builder(builder, series.commits if series else None,
-                       brds.get_selected_dict(), options)
+                       brds.get_selected_dict(), args)
diff --git a/tools/buildman/func_test.py b/tools/buildman/func_test.py
index aaf4cde..fe11917 100644
--- a/tools/buildman/func_test.py
+++ b/tools/buildman/func_test.py
@@ -252,12 +252,12 @@
             result code from buildman
         """
         sys.argv = [sys.argv[0]] + list(args)
-        options, args = cmdline.parse_args()
+        args = cmdline.parse_args()
         if brds == False:
             brds = self._boards
         result = control.do_buildman(
-            options, args, toolchains=self._toolchains,
-            make_func=self._HandleMake, brds=brds, clean_dir=clean_dir,
+            args, toolchains=self._toolchains, make_func=self._HandleMake,
+            brds=brds, clean_dir=clean_dir,
             test_thread_exceptions=test_thread_exceptions)
         if get_builder:
             self._builder = control.TEST_BUILDER
diff --git a/tools/buildman/main.py b/tools/buildman/main.py
index 70ab9a4..097e059 100755
--- a/tools/buildman/main.py
+++ b/tools/buildman/main.py
@@ -41,7 +41,7 @@
     from buildman import func_test
     from buildman import test
 
-    test_name = args and args[0] or None
+    test_name = args.terms and args.terms[0] or None
     if skip_net_tests:
         test.use_network = False
 
@@ -60,23 +60,22 @@
     This is the main program. It collects arguments and runs either the tests or
     the control module.
     """
-    options, args = cmdline.parse_args()
+    args = cmdline.parse_args()
 
-    if not options.debug:
+    if not args.debug:
         sys.tracebacklimit = 0
 
     # Run our meagre tests
-    if cmdline.HAS_TESTS and options.test:
-        return run_tests(options.skip_net_tests, options.debug, options.verbose,
-                         args)
+    if cmdline.HAS_TESTS and args.test:
+        return run_tests(args.skip_net_tests, args.debug, args.verbose, args)
 
-    elif options.full_help:
+    elif args.full_help:
         tools.print_full_help(str(files('buildman').joinpath('README.rst')))
 
     # Build selected commits for selected boards
     else:
-        bsettings.Setup(options.config_file)
-        ret_code = control.do_buildman(options, args)
+        bsettings.Setup(args.config_file)
+        ret_code = control.do_buildman(args)
         return ret_code