blob: 57201995b07eb4e6351c3e828474c7fe7f38ff2e [file] [log] [blame]
# Copyright 2015 The Chromium OS Authors. All rights reserved.
# 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."""
from __future__ import print_function
import os
from chromite.cbuildbot import constants
from chromite.lib import brick_lib
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import sysroot_lib
if cros_build_lib.IsInsideChroot():
# These import libraries outside chromite. See brbug.com/472.
from chromite.scripts import cros_list_modified_packages as workon
from chromite.scripts import cros_setup_toolchains as toolchain
_HOST_PKGS = ('virtual/target-sdk', 'world',)
def _GetToolchainPackages():
"""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=None):
"""Returns the emerge command to use for |sysroot| (host if None)."""
cmd = [os.path.join(constants.CHROMITE_BIN_DIR, 'parallel_emerge')]
if sysroot and sysroot != '/':
cmd += ['--sysroot=%s' % sysroot]
return cmd
def Emerge(packages, sysroot, with_deps=True, rebuild_deps=True,
use_binary=True, jobs=None, debug_output=False):
"""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()
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:
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('--jobs=%d' % jobs)
if debug_output:
cmd.append('--show-output')
cros_build_lib.SudoRunCommand(cmd + packages)
def UpdateChroot(brick=None, board=None, update_host_packages=True):
"""Update the chroot."""
# Run chroot update hooks.
cmd = [os.path.join(constants.CROSUTILS_DIR, 'run_chroot_version_hooks')]
cros_build_lib.RunCommand(cmd, debug_level=logging.DEBUG)
# Update toolchains.
cmd = [os.path.join(constants.CHROMITE_BIN_DIR, 'cros_setup_toolchains')]
if brick:
cmd += ['--targets=bricks', '--include-bricks=%s' % brick.brick_locator]
elif board:
cmd += ['--targets=boards', '--include-boards=%s' % board]
cros_build_lib.SudoRunCommand(cmd, debug_level=logging.DEBUG)
# Update the host before updating the board.
if update_host_packages:
Emerge(list(_HOST_PKGS), '/')
# Automatically discard all CONFIG_PROTECT'ed files. Those that are
# protected should not be overwritten until the variable is changed.
# Autodiscard is option "-9" followed by the "YES" confirmation.
cros_build_lib.SudoRunCommand(['etc-update'], input='-9\nYES\n',
debug_level=logging.DEBUG)
def SetupBoard(brick=None, board=None, update_chroot=True,
update_host_packages=True, use_binary=True):
"""Set up a sysroot for |brick| or |board| (either must be provided).
This invokes UpdateChroot() with the given brick/board values, unless
otherwise instructed.
Args:
brick: Brick object we need to set up a sysroot for.
board: Board name to set up a sysroot for. Ignored if |brick| is provided.
update_chroot: Whether we should update the chroot first.
update_host_packages: Whether to update host packages in the chroot.
use_binary: If okay to use binary packages during the update.
"""
if update_chroot:
UpdateChroot(brick=brick, board=board,
update_host_packages=update_host_packages)
cmd = [os.path.join(constants.CROSUTILS_DIR, 'setup_board'),
'--skip_toolchain_update', '--skip_chroot_upgrade']
if brick:
brick.GeneratePortageConfig()
cmd.append('--brick=%s' % brick.brick_locator)
elif board:
cmd.append('--board=%s' % board)
else:
raise ValueError('Either brick or board must be provided')
if not use_binary:
cmd.append('--nousepkg')
cros_build_lib.RunCommand(cmd)
def InitializeSysroots(blueprint):
"""Initialize the sysroots needed by |blueprint|.
Args:
blueprint: a blueprint_lib.Blueprint object.
"""
bsp = brick_lib.Brick(blueprint.GetBSP())
bricks = [brick_lib.Brick(b) for b in blueprint.GetBricks()]
# Regenerate the portage configuration for all bricks used by this blueprint.
for b in blueprint.GetUsedBricks():
b.GeneratePortageConfig()
sysroot_path = cros_build_lib.GetSysroot(blueprint.FriendlyName())
sysroot = sysroot_lib.Sysroot(sysroot_path)
sysroot.CreateSkeleton()
# TODO(bsimonnet): Add support for multiple bricks. brbug.com/803
sysroot.WriteConfig(sysroot.GenerateBrickConfig(bricks[0], bsp))
sysroot.GeneratePortageConfig()
sysroot.UpdateToolchain()