blob: 3cb082831b34db082aa2768a802ef9276ba9196c [file] [log] [blame]
# Copyright 2015 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Utilities for updating and building in the chroot environment."""
import os
from typing import Dict, List, Optional, Set, Union
from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import sysroot_lib
from chromite.lib.telemetry import trace
if cros_build_lib.IsInsideChroot():
# These import libraries outside chromite.
from chromite.scripts import cros_list_modified_packages as workon
from chromite.scripts import cros_setup_toolchains as toolchain
tracer = trace.get_tracer(__name__)
def _GetToolchainPackages() -> List[str]:
"""Get a list of host toolchain packages."""
# Load crossdev cache first for faster performance.
toolchain.Crossdev.Load(False)
packages = toolchain.GetTargetPackages("host")
return [toolchain.GetPortagePackage("host", x) for x in packages]
def GetEmergeCommand(
sysroot: Optional[str] = None,
) -> List[Union[str, "os.PathLike[str]"]]:
"""Returns the emerge command to use for |sysroot| (host if None)."""
cmd: List[Union[str, "os.PathLike[str]"]] = [
constants.CHROMITE_BIN_DIR / "parallel_emerge"
]
if sysroot and sysroot != "/":
cmd.append(f"--sysroot={sysroot}")
return cmd
@tracer.start_as_current_span("chroot_util.Emerge")
def Emerge(
packages: List[str],
sysroot: str,
with_deps: bool = True,
rebuild_deps: bool = True,
use_binary: bool = True,
jobs: int = 0,
debug_output: bool = False,
) -> None:
"""Emerge the specified |packages|.
Args:
packages: List of packages to emerge.
sysroot: Path to the sysroot in which to emerge.
with_deps: Whether to include dependencies.
rebuild_deps: Whether to rebuild dependencies.
use_binary: Whether to use binary packages.
jobs: Number of jobs to run in parallel.
debug_output: Emit debug level output.
Raises:
cros_build_lib.RunCommandError: If emerge returns an error.
"""
cros_build_lib.AssertInsideChroot()
span = trace.get_current_span()
span.set_attributes(
{
"sysroot": sysroot,
"packages": packages,
"with_deps": with_deps,
"rebuild_deps": rebuild_deps,
"use_binary": use_binary,
"jobs": jobs,
}
)
if not packages:
raise ValueError("No packages provided")
cmd = GetEmergeCommand(sysroot)
cmd.append("-uNv")
modified_packages = workon.ListModifiedWorkonPackages(
sysroot_lib.Sysroot(sysroot)
)
if modified_packages is not None:
mod_pkg_list = " ".join(modified_packages)
cmd += [
"--reinstall-atoms=" + mod_pkg_list,
"--usepkg-exclude=" + mod_pkg_list,
]
cmd.append("--deep" if with_deps else "--nodeps")
if use_binary:
cmd += ["-g", "--with-bdeps=y"]
if sysroot == "/":
# Only update toolchains in the chroot when binpkgs are available.
# The toolchain rollout process only takes place when the chromiumos
# sdk builder finishes a successful build and pushes out binpkgs.
cmd += ["--useoldpkg-atoms=%s" % " ".join(_GetToolchainPackages())]
if rebuild_deps:
cmd.append("--rebuild-if-unbuilt")
if jobs:
cmd.append(f"--jobs={jobs}")
if debug_output:
cmd.append("--show-output")
# We might build chrome, in which case we need to pass 'CHROME_ORIGIN'.
cros_build_lib.sudo_run(cmd + packages, preserve_env=True)
@tracer.start_as_current_span("chroot_util.RunUnittests")
def RunUnittests(
sysroot: str,
packages: Set[str],
extra_env: Optional[Dict[str, str]] = None,
keep_going: bool = False,
verbose: bool = False,
jobs: int = 0,
) -> None:
"""Runs the unit tests for |packages|.
Args:
sysroot: Path to the sysroot to build the tests in.
packages: List of packages to test.
extra_env: Python dictionary containing the extra environment variable
to pass to the build command.
keep_going: Tolerate package failure from parallel_emerge.
verbose: If True, show the output from emerge, even when the tests
succeed.
jobs: Max number of parallel jobs. (optional)
Raises:
RunCommandError if the unit tests failed.
"""
span = trace.get_current_span()
span.set_attributes(
{
"sysroot": sysroot,
"packages": list(packages),
"keep_going": keep_going,
"jobs": jobs,
}
)
env = extra_env.copy() if extra_env else {}
if "FEATURES" in env:
env["FEATURES"] += " test"
else:
env["FEATURES"] = "test"
env["PKGDIR"] = os.path.join(sysroot, constants.UNITTEST_PKG_PATH)
command = [
constants.CHROMITE_BIN_DIR / "parallel_emerge",
"--sysroot=%s" % sysroot,
]
if keep_going:
command += ["--keep-going=y"]
if verbose:
command += ["--show-output"]
command += ["--verbose"]
if jobs:
command += [f"--jobs={jobs}"]
command += list(packages)
cros_build_lib.sudo_run(command, extra_env=env)