Rename build_image to "cros build-image"
Move the build_image command as a cros subcommand (some restructuring
required) and add a wrapper which provides notice to the new command.
BUG=b:287468690
TEST=cros build-image --board betty test
build_image --board betty test
second invocation creates the expected notice
Change-Id: I9a6ee9c9535301b3b72d021cfbb0a9f8fa0db119
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/4621994
Reviewed-by: Sergey Frolov <sfrolov@google.com>
Tested-by: Jack Rosenthal <jrosenth@chromium.org>
Commit-Queue: Jack Rosenthal <jrosenth@chromium.org>
diff --git a/scripts/build_image.py b/scripts/build_image.py
index dff2279..a79d376 100644
--- a/scripts/build_image.py
+++ b/scripts/build_image.py
@@ -1,446 +1,28 @@
-# Copyright 2022 The ChromiumOS Authors
+# Copyright 2023 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-"""build_image is used to build a Chromium OS image.
+"""Wrapper to call "cros build-image".
-Chromium OS comes in many different forms. This script can be used to build
-the following:
-
-base - Pristine Chromium OS image. As similar to Chrome OS as possible.
-dev [default] - Developer image. Like base but with additional dev packages.
-test - Like dev, but with additional test specific packages and can be easily
- used for automated testing using scripts like test_that, etc.
-factory_install - Install shim for bootstrapping the factory test process.
- Cannot be built along with any other image.
-
-Examples:
-
-build_image --board=<board> dev test - builds developer and test images.
-build_image --board=<board> factory_install - builds a factory install shim.
-
-Note if you want to build an image with custom size partitions, either consider
-adding a new disk layout in build_library/legacy_disk_layout.json OR use
-adjust-part. Here are a few examples:
-
-adjust-part='STATE:+1G' -- add one GB to the size the stateful partition
-adjust-part='ROOT-A:-1G' -- remove one GB from the primary rootfs partition
-adjust-part='STATE:=1G' -- make the stateful partition 1 GB
+Eventually, this script will hard-error instead of calling "cros build-image"
+after the notice.
"""
-import argparse
-import os
-from pathlib import Path
+import logging
import sys
-from typing import List, Optional, Tuple
+from typing import List, Optional
-from chromite.lib import commandline
-from chromite.lib import constants
from chromite.lib import cros_build_lib
-from chromite.lib import namespaces
-from chromite.service import image
-from chromite.utils import timer
+from chromite.scripts import cros
-def build_shell_bool_style_args(
- parser: commandline.ArgumentParser,
- name: str,
- default_val: bool,
- help_str: str,
- deprecation_note: str,
- alternate_name: Optional[str] = None,
- additional_neg_options: Optional[List[str]] = None,
-) -> None:
- """Build the shell boolean input argument equivalent.
-
- There are two cases which we will need to handle,
- case 1: A shell boolean arg, which doesn't need to be re-worded in python.
- case 2: A shell boolean arg, which needs to be re-worded in python.
- Example below.
- For Case 1, for a given input arg name 'argA', we create three python
- arguments.
- --argA, --noargA, --no-argA. The arguments --argA and --no-argA will be
- retained after deprecating --noargA.
- For Case 2, for a given input arg name 'arg_A' we need to use alternate
- argument name 'arg-A'. we create four python arguments in this case.
- --arg_A, --noarg_A, --arg-A, --no-arg-A. The first two arguments will be
- deprecated later.
- TODO(b/232566937): Remove the creation of --noargA in case 1 and --arg_A and
- --noarg_A in case 2.
-
- Args:
- parser: The parser to update.
- name: The input argument name. This will be used as 'dest' variable
- name.
- default_val: The default value to assign.
- help_str: The help string for the input argument.
- deprecation_note: A deprecation note to use.
- alternate_name: Alternate argument to be used after deprecation.
- additional_neg_options: Additional negative alias options to use.
- """
- arg = f"--{name}"
- shell_narg = f"--no{name}"
- py_narg = f"--no-{name}"
- alt_arg = f"--{alternate_name}" if alternate_name else None
- alt_py_narg = f"--no-{alternate_name}" if alternate_name else None
- default_val_str = f"{help_str} (Default: %(default)s)."
-
- if alternate_name:
- _alternate_narg_list = [alt_py_narg]
- if additional_neg_options:
- _alternate_narg_list.extend(additional_neg_options)
-
- parser.add_argument(
- alt_arg,
- action="store_true",
- default=default_val,
- dest=name,
- help=default_val_str,
- )
- parser.add_argument(
- *_alternate_narg_list,
- action="store_false",
- dest=name,
- help="Don't " + help_str.lower(),
- )
-
- parser.add_argument(
- arg,
- action="store_true",
- default=default_val,
- dest=name,
- deprecated=deprecation_note % alt_arg if alternate_name else None,
- help=default_val_str if not alternate_name else argparse.SUPPRESS,
+def main(argv: Optional[List[str]]) -> Optional[int]:
+ """Wrapper main to call "cros build-image"."""
+ argv = argv or sys.argv[1:]
+ new_argv = ["build-image", *argv]
+ new_command_str = cros_build_lib.CmdToStr(["cros", *new_argv])
+ logging.notice(
+ "build_image has been renamed to `cros build-image`. Please call"
+ f" as `{new_command_str}`. This will eventually turn into an error."
)
- parser.add_argument(
- shell_narg,
- action="store_false",
- dest=name,
- deprecated=deprecation_note
- % (alt_py_narg if alternate_name else py_narg),
- help=argparse.SUPPRESS,
- )
-
- if not alternate_name:
- _py_narg_list = [py_narg]
- if additional_neg_options:
- _py_narg_list.extend(additional_neg_options)
-
- parser.add_argument(
- *_py_narg_list,
- action="store_false",
- dest=name,
- help="Don't " + help_str.lower(),
- )
-
-
-def build_shell_string_style_args(
- parser: commandline.ArgumentParser,
- name: str,
- default_val: Optional[str],
- help_str: str,
- deprecation_note: str,
- alternate_name: str,
-) -> None:
- """Build the shell string input argument equivalent.
-
- Args:
- parser: The parser to update.
- name: The input argument name. This will be used as 'dest' variable
- name.
- default_val: The default value to assign.
- help_str: The help string for the input argument.
- deprecation_note: A deprecation note to use.
- alternate_name: Alternate argument to be used after deprecation.
- """
- default_val_str = (
- f"{help_str} (Default: %(default)s)." if default_val else help_str
- )
-
- parser.add_argument(
- f"--{alternate_name}",
- dest=f"{name}",
- default=default_val,
- help=default_val_str,
- )
- parser.add_argument(
- f"--{name}",
- deprecated=deprecation_note % f"--{alternate_name}",
- help=argparse.SUPPRESS,
- )
-
-
-def get_parser() -> commandline.ArgumentParser:
- """Creates the cmdline argparser, populates the options and description.
-
- Returns:
- Argument parser.
- """
- deprecation_note = "Argument will be removed January, 2023. Use %s instead."
- parser = commandline.ArgumentParser(description=__doc__)
-
- parser.add_argument(
- "-b",
- "--board",
- "--build-target",
- dest="board",
- default=cros_build_lib.GetDefaultBoard(),
- help="The board to build images for.",
- )
- build_shell_string_style_args(
- parser,
- "adjust_part",
- None,
- "Adjustments to apply to partition table (LABEL:[+-=]SIZE) "
- "e.g. ROOT-A:+1G.",
- deprecation_note,
- "adjust-partition",
- )
- build_shell_string_style_args(
- parser,
- "output_root",
- Path(constants.DEFAULT_BUILD_ROOT) / "images",
- "Directory in which to place image result directories "
- "(named by version).",
- deprecation_note,
- "output-root",
- )
- build_shell_string_style_args(
- parser,
- "builder_path",
- None,
- "The build name to be installed on DUT during hwtest.",
- deprecation_note,
- "builder-path",
- )
- build_shell_string_style_args(
- parser,
- "disk_layout",
- "default",
- "The disk layout type to use for this image.",
- deprecation_note,
- "disk-layout",
- )
-
- # Kernel related options.
- group = parser.add_argument_group("Kernel Options")
- build_shell_string_style_args(
- group,
- "enable_serial",
- None,
- "Enable serial port for printks. Example values: ttyS0.",
- deprecation_note,
- "enable-serial",
- )
- group.add_argument(
- "--kernel-loglevel",
- type=int,
- default=7,
- help="The loglevel to add to the kernel command line. "
- "(Default: %(default)s).",
- )
- group.add_argument(
- "--loglevel",
- dest="kernel_loglevel",
- type=int,
- deprecated=deprecation_note % "kernel-loglevel",
- help=argparse.SUPPRESS,
- )
-
- # Bootloader related options.
- group = parser.add_argument_group("Bootloader Options")
- build_shell_string_style_args(
- group,
- "boot_args",
- "noinitrd",
- "Additional boot arguments to pass to the commandline.",
- deprecation_note,
- "boot-args",
- )
- build_shell_bool_style_args(
- group,
- "enable_bootcache",
- False,
- "Make all bootloaders to use boot cache.",
- deprecation_note,
- "enable-bootcache",
- )
- build_shell_bool_style_args(
- group,
- "enable_rootfs_verification",
- True,
- "Make all bootloaders to use kernel based root-fs integrity checking.",
- deprecation_note,
- "enable-rootfs-verification",
- ["-r"],
- )
-
- # Advanced options.
- group = parser.add_argument_group("Advanced Options")
- group.add_argument(
- "--build-attempt",
- type=int,
- default=1,
- help="The build attempt for this image build. (Default: %(default)s).",
- )
- group.add_argument(
- "--build_attempt",
- type=int,
- deprecated=deprecation_note % "build-attempt",
- help=argparse.SUPPRESS,
- )
- build_shell_string_style_args(
- group,
- "build_root",
- Path(constants.DEFAULT_BUILD_ROOT) / "images",
- "Directory in which to compose the image, before copying it to "
- "output_root.",
- deprecation_note,
- "build-root",
- )
- group.add_argument(
- "-j",
- "--jobs",
- dest="jobs",
- type=int,
- default=os.cpu_count(),
- help="Number of packages to build in parallel at maximum. "
- "(Default: %(default)s).",
- )
- build_shell_bool_style_args(
- group,
- "replace",
- False,
- "Overwrite existing output, if any.",
- deprecation_note,
- )
- group.add_argument(
- "--symlink",
- default="latest",
- help="Symlink name to use for this image. (Default: %(default)s).",
- )
- group.add_argument(
- "--version",
- default=None,
- help="Overrides version number in name to this version.",
- )
- build_shell_string_style_args(
- group,
- "output_suffix",
- None,
- "Add custom suffix to output directory.",
- deprecation_note,
- "output-suffix",
- )
- group.add_argument(
- "--eclean",
- action="store_true",
- default=True,
- dest="eclean",
- deprecated=(
- "eclean is being removed from build_images. Argument will be "
- "removed January, 2023."
- ),
- help=argparse.SUPPRESS,
- )
- group.add_argument(
- "--noeclean",
- action="store_false",
- dest="eclean",
- deprecated=(
- "eclean is being removed from build_images. Argument will be "
- "removed January, 2023."
- ),
- help=argparse.SUPPRESS,
- )
- group.add_argument(
- "--no-eclean",
- action="store_false",
- dest="eclean",
- deprecated=(
- "eclean is being removed from build_images. Argument will be "
- "removed January, 2023."
- ),
- help=argparse.SUPPRESS,
- )
-
- parser.add_argument(
- "images",
- nargs="*",
- default=["dev"],
- help="list of images to build. (Default: %(default)s).",
- )
-
- return parser
-
-
-def parse_args(
- argv: List[str],
-) -> Tuple[commandline.ArgumentParser, commandline.ArgumentNamespace]:
- """Parse and validate CLI arguments.
-
- Args:
- argv: Arguments passed via CLI.
-
- Returns:
- Tuple having the below two,
- Argument Parser
- Validated argument namespace.
- """
- parser = get_parser()
- opts = parser.parse_args(argv)
-
- opts.build_run_config = image.BuildConfig(
- adjust_partition=opts.adjust_part,
- output_root=opts.output_root,
- builder_path=opts.builder_path,
- disk_layout=opts.disk_layout,
- enable_serial=opts.enable_serial,
- kernel_loglevel=opts.kernel_loglevel,
- boot_args=opts.boot_args,
- enable_bootcache=opts.enable_bootcache,
- enable_rootfs_verification=opts.enable_rootfs_verification,
- build_attempt=opts.build_attempt,
- build_root=opts.build_root,
- jobs=opts.jobs,
- replace=opts.replace,
- symlink=opts.symlink,
- version=opts.version,
- output_dir_suffix=opts.output_suffix,
- )
- opts.Freeze()
-
- return parser, opts
-
-
-@timer.timed("Elapsed time (build_image)")
-def inner_main(argv: Optional[List[str]] = None):
- """Inner main that processes building the image."""
- parser, opts = parse_args(argv)
-
- # If the opts.board is not set, then it means user hasn't specified a
- # default board in 'src/scripts/.default_board' and didn't specify it as
- # input argument.
- if not opts.board:
- parser.error("--board is required")
-
- invalid_image = [
- x for x in opts.images if x not in constants.IMAGE_TYPE_TO_NAME
- ]
- if invalid_image:
- parser.error(f"Invalid image type argument(s) {invalid_image}")
-
- result = image.Build(opts.board, opts.images, opts.build_run_config)
- if result.run_error:
- cros_build_lib.Die(
- f"Error running build_image. Exit Code : {result.return_code}"
- )
-
-
-def main(argv: Optional[List[str]] = None) -> Optional[int]:
- commandline.RunInsideChroot()
-
- # Make sure we run with network disabled to prevent leakage.
- namespaces.ReExecuteWithNamespace(sys.argv, preserve_env=True)
-
- inner_main(argv)
+ return cros.main(new_argv)