# Copyright 2012 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""This script manages the installed toolchains in the chroot."""

import errno
import glob
import hashlib
import json
import logging
import os
import re
import shutil

from chromite.third_party import lddtree

from chromite.lib import commandline
from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import osutils
from chromite.lib import parallel
from chromite.lib import toolchain
from chromite.utils import key_value_store


if cros_build_lib.IsInsideChroot():
    # Only import portage after we've checked that we're inside the chroot.
    # Outside may not have portage, in which case the above may not happen.
    # We'll check in main() if the operation needs portage.
    # pylint: disable=import-error
    import portage


EMERGE_CMD = constants.CHROMITE_BIN_DIR / "parallel_emerge"
PACKAGE_STABLE = "[stable]"

CHROMIUMOS_OVERLAY = os.path.join(
    constants.CHROOT_SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
)
ECLASS_OVERLAY = os.path.join(
    constants.CHROOT_SOURCE_ROOT, constants.ECLASS_OVERLAY_DIR
)
STABLE_OVERLAY = os.path.join(
    constants.CHROOT_SOURCE_ROOT, constants.PORTAGE_STABLE_OVERLAY_DIR
)
CROSSDEV_OVERLAY = "/usr/local/portage/crossdev"


# The exact list of host toolchain packages we care about.  These are the
# packages that bots/devs install only from binpkgs and rely on the SDK bot
# (chromiumos-sdk) to validate+uprev.
#
# We don't use crossdev to manage the host toolchain for us, especially since
# we diverge significantly now (with llvm/clang/etc...), and we don't need or
# want crossdev managing /etc/portage config files for the sdk
HOST_PACKAGES = (
    "dev-lang/go",
    "dev-lang/rust-bootstrap",
    "dev-lang/rust-host",
    "dev-libs/elfutils",
    "sys-devel/binutils",
    "sys-devel/gcc",
    "sys-devel/llvm",
    "sys-kernel/linux-headers",
    "sys-libs/glibc",
    "sys-libs/libcxx",
    "sys-libs/llvm-libunwind",
)

# These packages are also installed into the host SDK.  However, they require
# the cross-compilers to be installed first (because they need them to actually
# build), so we have to delay their installation.
HOST_POST_CROSS_PACKAGES = (
    "dev-lang/rust",
    "virtual/target-sdk-post-cross",
    "dev-embedded/hps-sdk",
)

# New packages that we're in the process of adding to the SDK.  Since the SDK
# bot hasn't had a chance to run yet, there are no binary packages available,
# so we have to list them here and wait.  Once it completes, entries here can
# be removed so they'll end up on bots & dev's systems.
NEW_PACKAGES = ()

# Enable the Go compiler for these targets.
TARGET_GO_ENABLED = (
    "x86_64-cros-linux-gnu",
    "armv7a-cros-linux-gnueabi",
    "armv7a-cros-linux-gnueabihf",
    "aarch64-cros-linux-gnu",
)
CROSSDEV_GO_ARGS = ["--ex-pkg", "dev-lang/go"]

CROSSDEV_LIBXCRYPT_ARGS = ["--ex-pkg", "sys-libs/libxcrypt"]

# Enable llvm's compiler-rt for these targets.
TARGET_COMPILER_RT_ENABLED = (
    "armv7a-cros-linux-gnueabi",
    "armv7a-cros-linux-gnueabihf",
    "aarch64-cros-linux-gnu",
    "arm-none-eabi",
    "armv7m-cros-eabi",
)
CROSSDEV_COMPILER_RT_ARGS = ["--ex-pkg", "sys-libs/compiler-rt"]

TARGET_LLVM_PKGS_ENABLED = (
    "arm-none-eabi",
    "armv7m-cros-eabi",
    "armv7a-cros-linux-gnueabi",
    "armv7a-cros-linux-gnueabihf",
    "aarch64-cros-linux-gnu",
    "i686-cros-linux-gnu",
    "x86_64-cros-linux-gnu",
)

LLVM_PKGS_TABLE = {
    "ex_llvm-libunwind": ["--ex-pkg", "sys-libs/llvm-libunwind"],
    "ex_libcxx": ["--ex-pkg", "sys-libs/libcxx"],
}


class Crossdev:
    """Class for interacting with crossdev and caching its output."""

    _CACHE_FILE = os.path.join(CROSSDEV_OVERLAY, ".configured.json")
    _CACHE = {}
    # Packages that needs separate handling, in addition to what we have from
    # crossdev.
    MANUAL_PKGS = {
        "llvm": "sys-devel",
        "llvm-libunwind": "sys-libs",
        "libcxx": "sys-libs",
        "elfutils": "dev-libs",
        # b/269306499: note that rust and rust-host are shipped as a part of
        # this tarball on a best-effort basis. If you would like them to be
        # fully supported (with an SLA), please reach out to
        # chromeos-toolchain@google.com and chat with us.
        "rust": "dev-lang",
        "rust-host": "dev-lang",
    }

    @classmethod
    def Load(cls, reconfig):
        """Load crossdev cache from disk.

        We invalidate the cache when crossdev updates or this script changes.
        """
        crossdev_version = GetStablePackageVersion("sys-devel/crossdev", True)
        # If we run the compiled/cached .pyc file, we'll read/hash that when we
        # really always want to track the source .py file.
        script = os.path.abspath(__file__)
        if script.endswith(".pyc"):
            script = script[:-1]
        setup_toolchains_hash = hashlib.md5(
            osutils.ReadFile(script, mode="rb")
        ).hexdigest()

        cls._CACHE = {
            "crossdev_version": crossdev_version,
            "setup_toolchains_hash": setup_toolchains_hash,
        }

        logging.debug("cache: checking file: %s", cls._CACHE_FILE)
        if reconfig:
            logging.debug("cache: forcing regen due to reconfig")
            return

        try:
            file_data = osutils.ReadFile(cls._CACHE_FILE)
        except IOError as e:
            if e.errno != errno.ENOENT:
                logging.warning("cache: reading failed: %s", e)
                osutils.SafeUnlink(cls._CACHE_FILE)
            return

        try:
            data = json.loads(file_data)
        except ValueError as e:
            logging.warning("cache: ignoring invalid content: %s", e)
            return

        if crossdev_version != data.get("crossdev_version"):
            logging.debug("cache: rebuilding after crossdev upgrade")
        elif setup_toolchains_hash != data.get("setup_toolchains_hash"):
            logging.debug(
                "cache: rebuilding after cros_setup_toolchains change"
            )
        else:
            logging.debug("cache: content is up-to-date!")
            cls._CACHE = data

    @classmethod
    def Save(cls):
        """Store crossdev cache on disk."""
        # Save the cache from the successful run.
        with open(cls._CACHE_FILE, "w", encoding="utf-8") as f:
            json.dump(cls._CACHE, f)

    @classmethod
    def GetConfig(cls, target):
        """Returns a map of crossdev provided variables about a tuple."""
        CACHE_ATTR = "_target_tuple_map"

        val = cls._CACHE.setdefault(CACHE_ATTR, {})
        if not target in val:
            if target.startswith("host"):
                conf = {
                    "crosspkgs": [],
                    "target": toolchain.GetHostTuple(),
                }
                if target == "host":
                    packages_list = HOST_PACKAGES
                else:
                    packages_list = HOST_POST_CROSS_PACKAGES
                manual_pkgs = dict(
                    (pkg, cat)
                    for cat, pkg in [x.split("/") for x in packages_list]
                )
            else:
                # Build the crossdev command.
                cmd = ["crossdev", "--stable", "--show-target-cfg", "--ex-gdb"]
                # Enable libxcrypt for all linux-gnu targets.
                if "cros-linux-gnu" in target:
                    cmd.extend(CROSSDEV_LIBXCRYPT_ARGS)
                if target in TARGET_COMPILER_RT_ENABLED:
                    cmd.extend(CROSSDEV_COMPILER_RT_ARGS)
                if target in TARGET_LLVM_PKGS_ENABLED:
                    # TODO(b/236161656): Fix.
                    # pylint: disable-next=consider-using-dict-items
                    for pkg in LLVM_PKGS_TABLE:
                        cmd.extend(LLVM_PKGS_TABLE[pkg])
                if target in TARGET_GO_ENABLED:
                    cmd.extend(CROSSDEV_GO_ARGS)
                cmd.extend(["-t", target])
                # Catch output of crossdev.
                out = cros_build_lib.run(
                    cmd, print_cmd=False, stdout=True, encoding="utf-8"
                ).stdout.splitlines()
                # List of tuples split at the first '=', converted into dict.
                conf = dict(
                    (k, cros_build_lib.ShellUnquote(v))
                    for k, v in (x.split("=", 1) for x in out)
                )
                conf["crosspkgs"] = conf["crosspkgs"].split()

                manual_pkgs = cls.MANUAL_PKGS

            for pkg, cat in manual_pkgs.items():
                conf[pkg + "_pn"] = pkg
                conf[pkg + "_category"] = cat
                if pkg not in conf["crosspkgs"]:
                    conf["crosspkgs"].append(pkg)

            val[target] = conf

        return val[target]

    @classmethod
    def UpdateTargets(cls, targets, usepkg, config_only=False):
        """Calls crossdev to initialize a cross target.

        Args:
            targets: The dict of targets to initialize using crossdev.
            usepkg: Copies the commandline opts.
            config_only: Just update.
        """
        configured_targets = cls._CACHE.setdefault("configured_targets", [])
        started_targets = set()

        # Schedule all of the targets in parallel, and let them run.
        with parallel.BackgroundTaskRunner(cls._UpdateTarget) as queue:
            for target_name in targets:
                # We already started this target in this loop.
                if target_name in started_targets:
                    continue
                # The target is already configured.
                if config_only and target_name in configured_targets:
                    continue
                queue.put(
                    [target_name, targets[target_name], usepkg, config_only]
                )
                started_targets.add(target_name)

    @classmethod
    def _UpdateTarget(cls, target_name, target, usepkg, config_only):
        """Calls crossdev to initialize a cross target.

        Args:
            target_name: The name of the target to initialize.
            target: The target info for initializing.
            usepkg: Copies the commandline opts.
            config_only: Just update.
        """
        configured_targets = cls._CACHE.setdefault("configured_targets", [])
        cmdbase = ["crossdev", "--stable", "--show-fail-log"]
        cmdbase.extend(["--env", "FEATURES=splitdebug"])
        # Pick stable by default, and override as necessary.
        cmdbase.extend(["-P", "--oneshot"])
        if usepkg:
            cmdbase.extend(
                ["-P", "--getbinpkg", "-P", "--usepkgonly", "--without-headers"]
            )

        overlays = " ".join(
            (CHROMIUMOS_OVERLAY, ECLASS_OVERLAY, STABLE_OVERLAY)
        )
        cmdbase.extend(["--overlays", overlays])
        cmdbase.extend(["--ov-output", CROSSDEV_OVERLAY])

        cmd = cmdbase + ["-t", target_name]

        for pkg in GetTargetPackages(target_name):
            if pkg == "gdb":
                # Gdb does not have selectable versions.
                cmd.append("--ex-gdb")
            elif pkg == "ex_libxcrypt":
                cmd.extend(CROSSDEV_LIBXCRYPT_ARGS)
            elif pkg == "ex_compiler-rt":
                cmd.extend(CROSSDEV_COMPILER_RT_ARGS)
            elif pkg == "ex_go":
                # Go does not have selectable versions.
                cmd.extend(CROSSDEV_GO_ARGS)
            elif pkg in LLVM_PKGS_TABLE:
                cmd.extend(LLVM_PKGS_TABLE[pkg])
            elif pkg in cls.MANUAL_PKGS:
                pass
            else:
                # The first of the desired versions is the "primary" one.
                version = GetDesiredPackageVersions(target_name, pkg)[0]
                cmd.extend(["--%s" % pkg, version])

        cmd.extend(target["crossdev"].split())

        if config_only:
            # In this case we want to just quietly reinit
            cmd.append("--init-target")
            cros_build_lib.run(cmd, print_cmd=False, stdout=True)
        else:
            cros_build_lib.run(cmd)

        configured_targets.append(target_name)


def GetTargetPackages(target):
    """Returns a list of packages for a given target."""
    conf = Crossdev.GetConfig(target)
    # Undesired packages are denoted by empty ${pkg}_pn variable.
    return [x for x in conf["crosspkgs"] if conf.get(x + "_pn")]


# Portage helper functions:
def GetPortagePackage(target, package):
    """Returns a package name for the given target."""
    conf = Crossdev.GetConfig(target)
    # Portage category:
    if target.startswith("host") or package in Crossdev.MANUAL_PKGS:
        category = conf[package + "_category"]
    else:
        category = conf["category"]
    # Portage package:
    pn = conf[package + "_pn"]
    # Final package name:
    assert category
    assert pn
    return "%s/%s" % (category, pn)


def PortageTrees(root):
    """Return the portage trees for a given root."""
    if root == "/":
        return portage.db["/"]
    # The portage logic requires the path always end in a slash.
    root = root.rstrip("/") + "/"
    return portage.create_trees(target_root=root, config_root=root)[root]


def GetInstalledPackageVersions(atom, root="/"):
    """Extracts the list of current versions of a target, package pair.

    Args:
        atom: The atom to operate on (e.g. sys-devel/gcc)
        root: The root to check for installed packages.

    Returns:
        The list of versions of the package currently installed.
    """
    versions = []
    for pkg in PortageTrees(root)["vartree"].dbapi.match(atom, use_cache=0):
        version = portage.versions.cpv_getversion(pkg)
        versions.append(version)
    return versions


def GetStablePackageVersion(atom, installed, root="/"):
    """Extracts the current stable version for a given package.

    Args:
        atom: The target/package to operate on e.g. i686-cros-linux-gnu/gcc
        installed: Whether we want installed packages or ebuilds
        root: The root to use when querying packages.

    Returns:
        A string containing the latest version.
    """
    pkgtype = "vartree" if installed else "porttree"
    cpv = portage.best(
        PortageTrees(root)[pkgtype].dbapi.match(atom, use_cache=0)
    )
    return portage.versions.cpv_getversion(cpv) if cpv else None


def VersionListToNumeric(target, package, versions, installed, root="/"):
    """Resolves keywords in a given version list for a particular package.

    Resolving means replacing PACKAGE_STABLE with the actual number.

    Args:
        target: The target to operate on (e.g. i686-cros-linux-gnu)
        package: The target/package to operate on (e.g. gcc)
        versions: List of versions to resolve
        installed: Query installed packages
        root: The install root to use; ignored if |installed| is False.

    Returns:
        List of purely numeric versions equivalent to argument
    """
    resolved = []
    atom = GetPortagePackage(target, package)
    if not installed:
        root = "/"
    for version in versions:
        if version == PACKAGE_STABLE:
            resolved.append(GetStablePackageVersion(atom, installed, root=root))
        else:
            resolved.append(version)
    return resolved


def GetDesiredPackageVersions(target, package):
    """Produces the list of desired versions for each target, package pair.

    The first version in the list is implicitly treated as primary, ie.
    the version that will be initialized by crossdev and selected.

    If the version is PACKAGE_STABLE, it really means the current version which
    is emerged by using the package atom with no particular version key.
    Since crossdev unmasks all packages by default, this will actually
    mean 'unstable' in most cases.

    Args:
        target: The target to operate on (e.g. i686-cros-linux-gnu)
        package: The target/package to operate on (e.g. gcc)

    Returns:
        A list composed of either a version string, PACKAGE_STABLE
    """
    if package in GetTargetPackages(target):
        return [PACKAGE_STABLE]
    else:
        return []


def TargetIsInitialized(target):
    """Verifies if the given list of targets has been correctly initialized.

    This determines whether we have to call crossdev while emerging
    toolchain packages or can do it using emerge. Emerge is naturally
    preferred, because all packages can be updated in a single pass.

    Args:
        target: The target to operate on (e.g. i686-cros-linux-gnu)

    Returns:
        True if |target| is completely initialized, else False
    """
    # Check if packages for the given target all have a proper version.
    try:
        for package in GetTargetPackages(target):
            atom = GetPortagePackage(target, package)
            # Do we even want this package && is it initialized?
            if not (
                GetStablePackageVersion(atom, True)
                and GetStablePackageVersion(atom, False)
            ):
                return False
        return True
    except cros_build_lib.RunCommandError:
        # Fails - The target has likely never been initialized before.
        return False


def RemovePackageMask(target):
    """Removes a package.mask file for the given platform.

    The pre-existing package.mask files can mess with the keywords.

    Args:
        target: The target to operate on (e.g. i686-cros-linux-gnu)
    """
    maskfile = os.path.join("/etc/portage/package.mask", "cross-" + target)
    osutils.SafeUnlink(maskfile)


# Main functions performing the actual update steps.
def RebuildLibtool(root="/"):
    """Rebuild libtool as needed

    Libtool hardcodes full paths to internal gcc files, so whenever we upgrade
    gcc, libtool will break.  We can't use binary packages either as those will
    most likely be compiled against the previous version of gcc.

    Args:
        root: The install root where we want libtool rebuilt.
    """
    needs_update = False
    with open(os.path.join(root, "usr/bin/libtool"), encoding="utf-8") as f:
        for line in f:
            # Look for a line like:
            #   sys_lib_search_path_spec="..."
            # It'll be a list of paths and gcc will be one of them.
            if line.startswith("sys_lib_search_path_spec="):
                line = line.rstrip()
                for path in line.split("=", 1)[1].strip('"').split():
                    root_path = os.path.join(root, path.lstrip(os.path.sep))
                    logging.debug("Libtool: checking %s", root_path)
                    if not os.path.exists(root_path):
                        logging.info("Rebuilding libtool after gcc upgrade")
                        logging.info(" %s", line)
                        logging.info(" missing path: %s", path)
                        needs_update = True
                        break

            if needs_update:
                break

    if needs_update:
        cmd = [EMERGE_CMD, "--oneshot"]
        if root != "/":
            cmd.extend(["--sysroot=%s" % root, "--root=%s" % root])
        cmd.append("sys-devel/libtool")
        cros_build_lib.run(cmd)
    else:
        logging.debug("Libtool is up-to-date; no need to rebuild")


def UpdateTargets(targets, usepkg, root="/"):
    """Determines which packages need update/unmerge and defers to portage.

    Args:
        targets: The list of targets to update
        usepkg: Copies the commandline option
        root: The install root in which we want packages updated.
    """
    # For each target, we do two things. Figure out the list of updates,
    # and figure out the appropriate keywords/masks. Crossdev will initialize
    # these, but they need to be regenerated on every update.
    logging.info("Determining required toolchain updates...")
    mergemap = {}
    # Used to keep track of post-cross packages. These are allowed to have
    # implicit dependencies on toolchain packages, and therefore need to
    # be built last.
    post_cross_pkgs = set()
    for target in targets:
        is_post_cross_target = target.endswith("-post-cross")
        logging.debug("Updating target %s", target)
        # Record the highest needed version for each target, for masking
        # purposes.
        RemovePackageMask(target)
        for package in GetTargetPackages(target):
            # Portage name for the package
            logging.debug("   Checking package %s", package)
            pkg = GetPortagePackage(target, package)
            current = GetInstalledPackageVersions(pkg, root=root)
            desired = GetDesiredPackageVersions(target, package)
            desired_num = VersionListToNumeric(target, package, desired, False)
            if pkg in NEW_PACKAGES and usepkg:
                # Skip this binary package (for now).
                continue
            mergemap[pkg] = set(desired_num).difference(current)
            logging.debug("      %s -> %s", current, desired_num)
            if is_post_cross_target:
                post_cross_pkgs.add(pkg)

    packages = [pkg for pkg, vers in mergemap.items() if vers]
    if not packages:
        logging.info("Nothing to update!")
        return False

    logging.info("Updating packages:")
    logging.info("%s", packages)

    cmd = [EMERGE_CMD, "--oneshot", "--update"]
    if usepkg:
        cmd.extend(["--getbinpkg", "--usepkgonly"])
    if root != "/":
        cmd.extend(["--sysroot=%s" % root, "--root=%s" % root])

    if usepkg:
        # Since we are not building from source, we can handle
        # all packages in one go.
        cmd.extend(packages)
        cros_build_lib.run(cmd)
    else:
        pre_cross_items = [
            pkg for pkg in packages if pkg not in post_cross_pkgs
        ]
        if pre_cross_items:
            cros_build_lib.run(cmd + pre_cross_items)
        post_cross_items = [pkg for pkg in packages if pkg in post_cross_pkgs]
        if post_cross_items:
            cros_build_lib.run(cmd + post_cross_items)
    return True


def CleanTargets(targets, root="/"):
    """Unmerges old packages that are assumed unnecessary.

    Args:
        targets: The list of targets to clean up.
        root: The install root in which we want packages cleaned up.
    """
    unmergemap = {}
    for target in targets:
        logging.debug("Cleaning target %s", target)
        for package in GetTargetPackages(target):
            logging.debug("   Cleaning package %s", package)
            pkg = GetPortagePackage(target, package)
            current = GetInstalledPackageVersions(pkg, root=root)
            desired = GetDesiredPackageVersions(target, package)
            # NOTE: This refers to installed packages (vartree) rather than the
            # Portage version (porttree and/or bintree) when determining the
            # current version. While this isn't the most accurate thing to do,
            # it is probably a good simple compromise, which should have the
            # desired result of uninstalling everything but the latest installed
            # version. In particular, using the bintree (--usebinpkg) requires a
            # non-trivial binhost sync and is probably more complex than useful.
            desired_num = VersionListToNumeric(target, package, desired, True)
            if not set(desired_num).issubset(current):
                logging.warning(
                    "Error detecting stable version for %s, " "skipping clean!",
                    pkg,
                )
                return
            unmergemap[pkg] = set(current).difference(desired_num)

    # Cleaning doesn't care about consistency and rebuilding package.* files.
    packages = []
    for pkg, vers in unmergemap.items():
        packages.extend("=%s-%s" % (pkg, ver) for ver in vers if ver != "9999")

    if packages:
        logging.info("Cleaning packages:")
        logging.info("%s", packages)
        cmd = [EMERGE_CMD, "--unmerge"]
        if root != "/":
            cmd.extend(["--sysroot=%s" % root, "--root=%s" % root])
        cmd.extend(packages)
        cros_build_lib.run(cmd)
    else:
        logging.info("Nothing to clean!")


def SelectActiveToolchains(targets, root="/"):
    """Runs gcc-config and binutils-config to select the desired.

    Args:
        targets: The targets to select
        root: The root where we want to select toolchain versions.
    """
    for package in ["gcc", "binutils"]:
        for target in targets:
            # See if this package is part of this target.
            if package not in GetTargetPackages(target):
                logging.debug("%s: %s is not used", target, package)
                continue

            # Pick the first version in the numbered list as the selected one.
            desired = GetDesiredPackageVersions(target, package)
            desired_num = VersionListToNumeric(
                target, package, desired, True, root=root
            )
            desired = desired_num[0]
            # *-config does not play revisions, strip them, keep just PV.
            desired = portage.versions.pkgsplit("%s-%s" % (package, desired))[1]

            if target.startswith("host"):
                # *-config is the only tool treating host identically (by
                # tuple).
                target = toolchain.GetHostTuple()

            # And finally, attach target to it.
            desired = "%s-%s" % (target, desired)

            extra_env = {"CHOST": target}
            if root != "/":
                extra_env["ROOT"] = root
            cmd = ["%s-config" % package, "-c", target]
            result = cros_build_lib.run(
                cmd,
                print_cmd=False,
                stdout=True,
                encoding="utf-8",
                extra_env=extra_env,
            )
            current = result.stdout.splitlines()[0]

            # Do not reconfig when the current is live or nothing needs to be
            # done.
            extra_env = {"ROOT": root} if root != "/" else None
            if current not in (desired, "9999"):
                cmd = [package + "-config", desired]
                cros_build_lib.run(cmd, print_cmd=False, extra_env=extra_env)


def ExpandTargets(targets_wanted):
    """Expand any possible toolchain aliases into full targets

    This will expand 'all' and 'sdk' into the respective toolchain tuples.

    Args:
        targets_wanted: The targets specified by the user.

    Returns:
        Dictionary of concrete targets and their toolchain tuples.
    """
    targets_wanted = set(targets_wanted)
    if targets_wanted == set(["boards"]):
        # Only pull targets from the included boards.
        return {}

    all_targets = toolchain.GetAllTargets()
    if targets_wanted == set(["all"]):
        return all_targets
    if targets_wanted == set(["sdk"]):
        # Filter out all the non-sdk toolchains as we don't want to mess
        # with those in all of our builds.
        return toolchain.FilterToolchains(all_targets, "sdk", True)

    # Verify user input.
    nonexistent = targets_wanted.difference(all_targets)
    if nonexistent:
        raise ValueError("Invalid targets: %s" % (",".join(nonexistent),))
    return {t: all_targets[t] for t in targets_wanted}


def UpdateToolchains(
    usepkg,
    deleteold,
    hostonly,
    reconfig,
    targets_wanted,
    boards_wanted,
    root="/",
):
    """Performs all steps to create a synchronized toolchain enviroment.

    Args:
        usepkg: Use prebuilt packages
        deleteold: Unmerge deprecated packages
        hostonly: Only setup the host toolchain
        reconfig: Reload crossdev config and reselect toolchains
        targets_wanted: All the targets to update
        boards_wanted: Load targets from these boards
        root: The root in which to install the toolchains.
    """
    targets, crossdev_targets, reconfig_targets = {}, {}, {}
    if not hostonly:
        # For hostonly, we can skip most of the below logic, much of which won't
        # work on bare systems where this is useful.
        targets = ExpandTargets(targets_wanted)

        # Filter out toolchains that don't (yet) have a binpkg available.
        if usepkg:
            for target in list(targets.keys()):
                if not targets[target]["have-binpkg"]:
                    del targets[target]

        # Now re-add any targets that might be from this board. This is to
        # allow unofficial boards to declare their own toolchains.
        for board in boards_wanted:
            targets.update(toolchain.GetToolchainsForBoard(board))

        # First check and initialize all cross targets that need to be.
        for target in targets:
            if TargetIsInitialized(target):
                reconfig_targets[target] = targets[target]
            else:
                crossdev_targets[target] = targets[target]
        if crossdev_targets:
            logging.info("The following targets need to be re-initialized:")
            logging.info("%s", crossdev_targets)
            Crossdev.UpdateTargets(crossdev_targets, usepkg)
        # Those that were not initialized may need a config update.
        Crossdev.UpdateTargets(reconfig_targets, usepkg, config_only=True)

        # If we're building a subset of toolchains for a board, we might not
        # have all the tuples that the packages expect.  We don't define the
        # "full" set of tuples currently other than "whatever the full sdk has
        # normally".
        if usepkg or set(("all", "sdk")) & targets_wanted:
            # Since we have cross-compilers now, we can update these packages.
            targets["host-post-cross"] = {}

    # We want host updated.
    targets["host"] = {}

    # Now update all packages.
    if (
        UpdateTargets(targets, usepkg, root=root)
        or crossdev_targets
        or reconfig
    ):
        SelectActiveToolchains(targets, root=root)

    if deleteold:
        CleanTargets(targets, root=root)

    # Now that we've cleared out old versions, see if we need to rebuild
    # anything.  Can't do this earlier as it might not be broken.
    RebuildLibtool(root=root)


def ShowConfig(name):
    """Show the toolchain tuples used by |name|

    Args:
        name: The board name to query.
    """
    toolchains = toolchain.GetToolchainsForBoard(name)
    # Make sure we display the default toolchain first.
    # Note: Do not use logging here as this is meant to be used by other tools.
    print(
        ",".join(
            list(toolchain.FilterToolchains(toolchains, "default", True))
            + list(toolchain.FilterToolchains(toolchains, "default", False))
        )
    )


def GeneratePathWrapper(root, wrappath, path):
    """Generate a shell script to execute another shell script

    Since we can't symlink a wrapped ELF (see GenerateLdsoWrapper) because the
    argv[0] won't be pointing to the correct path, generate a shell script that
    just executes another program with its full path.

    Args:
        root: The root tree to generate scripts inside of
        wrappath: The full path (inside |root|) to create the wrapper
        path: The target program which this wrapper will execute
    """
    replacements = {
        "path": path,
        "relroot": os.path.relpath("/", os.path.dirname(wrappath)),
    }

    # Do not use exec here, because exec invokes script with absolute path in
    # argv0. Keeping relativeness allows us to remove abs path from compile
    # result and leads directory independent build cache sharing in some
    # distributed build system.
    wrapper = (
        """#!/bin/sh
basedir=$(dirname "$0")
"${basedir}/%(relroot)s%(path)s" "$@"
exit "$?"
"""
        % replacements
    )
    root_wrapper = root + wrappath
    if os.path.islink(root_wrapper):
        os.unlink(root_wrapper)
    else:
        osutils.SafeMakedirs(os.path.dirname(root_wrapper))
    osutils.WriteFile(root_wrapper, wrapper)
    os.chmod(root_wrapper, 0o755)


def FixClangXXWrapper(root, path):
    """Fix wrapper shell scripts and symlinks for invoking clang++

    In a typical installation, clang++ symlinks to clang, which symlinks to the
    elf executable. The executable distinguishes between clang and clang++ based
    on argv[0].

    When invoked through the LdsoWrapper, argv[0] always contains the path to
    the executable elf file, making clang/clang++ invocations indistinguishable.

    This function detects if the elf executable being wrapped is clang-X.Y, and
    fixes wrappers/symlinks as necessary so that clang++ will work correctly.

    The calling sequence now becomes:
    -) clang++ invocation turns into clang++-3.9 (which is a copy of clang-3.9,
       the Ldsowrapper).
    -) clang++-3.9 uses the Ldso to invoke clang++-3.9.elf, which is a symlink
       to the original clang-3.9 elf.
    -) The difference this time is that inside the elf file execution, $0 is
       set as .../usr/bin/clang++-3.9.elf, which contains 'clang++' in the name.

    Update: Starting since clang 7, the clang and clang++ are symlinks to
    clang-7 binary, not clang-7.0. The pattern match is extended to handle
    both clang-7 and clang-7.0 cases for now. (https://crbug.com/837889)

    Args:
        root: The root tree to generate scripts / symlinks inside of
        path: The target elf for which LdsoWrapper was created
    """
    if re.match(r"/usr/bin/clang-\d+(\.\d+)*$", path):
        logging.info("fixing clang++ invocation for %s", path)
        clangdir = os.path.dirname(root + path)
        clang = os.path.basename(path)
        clangxx = clang.replace("clang", "clang++")

        # Create a symlink clang++-X.Y.elf to point to clang-X.Y.elf
        os.symlink(clang + ".elf", os.path.join(clangdir, clangxx + ".elf"))

        # Create a hardlink clang++-X.Y pointing to clang-X.Y
        os.link(os.path.join(clangdir, clang), os.path.join(clangdir, clangxx))

        # Adjust the clang++ symlink to point to clang++-X.Y
        os.unlink(os.path.join(clangdir, "clang++"))
        os.symlink(clangxx, os.path.join(clangdir, "clang++"))


def FileIsCrosSdkElf(elf):
    """Determine if |elf| is an ELF that we execute in the cros_sdk

    We don't need this to be perfect, just quick.  It makes sure the ELF
    is a 64bit LSB x86_64 ELF.  That is the native type of cros_sdk.

    Args:
        elf: The file to check

    Returns:
        True if we think |elf| is a native ELF
    """
    with open(elf, "rb") as f:
        data = f.read(20)
        # Check the magic number, EI_CLASS, EI_DATA, and e_machine.
        return (
            data[0:4] == b"\x7fELF"
            and data[4:5] == b"\x02"
            and data[5:6] == b"\x01"
            and data[18:19] == b"\x3e"
        )


def IsPathPackagable(ptype, path):
    """Should the specified file be included in a toolchain package?

    We only need to handle files as we'll create dirs as we need them.

    Further, trim files that won't be useful:
     - non-english translations (.mo) since it'd require env vars
     - debug files since these are for the host compiler itself
     - info/man pages as they're big, and docs are online, and the
       native docs should work fine for the most part (`man gcc`)

    Args:
        ptype: A string describing the path type (i.e. 'file' or 'dir' or 'sym')
        path: The full path to inspect

    Returns:
        True if we want to include this path in the package
    """
    return not (
        ptype in ("dir",)
        or path.startswith("/usr/lib/debug/")
        or os.path.splitext(path)[1] == ".mo"
        or ("/man/" in path or "/info/" in path)
    )


def ReadlinkRoot(path, root):
    """Like os.readlink(), but relative to a |root|

    Args:
        path: The symlink to read
        root: The path to use for resolving absolute symlinks

    Returns:
        A fully resolved symlink path
    """
    while os.path.islink(root + path):
        path = os.path.join(os.path.dirname(path), os.readlink(root + path))
    return path


def _GetFilesForTarget(target, root="/"):
    """Locate all the files to package for |target|

    This does not cover ELF dependencies.

    Args:
        target: The toolchain target name
        root: The root path to pull all packages from

    Returns:
        A tuple of a set of all packable paths, and a set of all paths which
        are also native ELFs
    """
    paths = set()
    elfs = set()

    # Find all the files owned by the packages for this target.
    for pkg in GetTargetPackages(target):
        # Skip Go compiler from redistributable packages.
        # The "go" executable has GOROOT=/usr/lib/go/${CTARGET} hardcoded
        # into it. Due to this, the toolchain cannot be unpacked anywhere
        # else and be readily useful. To enable packaging Go, we need to:
        # -) Tweak the wrappers/environment to override GOROOT
        #    automatically based on the unpack location.
        # -) Make sure the ELF dependency checking and wrapping logic
        #    below skips the Go toolchain executables and libraries.
        # -) Make sure the packaging process maintains the relative
        #    timestamps of precompiled standard library packages.
        #    (see dev-lang/go ebuild for details).
        if pkg == "ex_go":
            continue

        # Use armv7a-cros-linux-gnueabi/compiler-rt for
        # armv7a-cros-linux-gnueabihf/compiler-rt. Currently the
        # armv7a-cros-linux-gnueabi is actually the same as
        # armv7a-cros-linux-gnueabihf with different names. Because of that, for
        # compiler-rt, it generates the same binary in the same location. To
        # avoid the installation conflict, we do not install anything for
        # 'armv7a-cros-linux-gnueabihf'. This would cause problem if other
        # people try to use standalone armv7a-cros-linux-gnueabihf toolchain.
        if "compiler-rt" in pkg and "armv7a-cros-linux-gnueabi" in target:
            atom = GetPortagePackage(target, pkg)
            cat, pn = atom.split("/")
            ver = GetInstalledPackageVersions(atom, root=root)[0]
            dblink = portage.dblink(
                cat, pn + "-" + ver, myroot=root, settings=portage.settings
            )
            contents = dblink.getcontents()
            if not contents:
                if "hf" in target:
                    new_target = "armv7a-cros-linux-gnueabi"
                else:
                    new_target = "armv7a-cros-linux-gnueabihf"
                atom = GetPortagePackage(new_target, pkg)
        else:
            atom = GetPortagePackage(target, pkg)

        cat, pn = atom.split("/")
        ver = GetInstalledPackageVersions(atom, root=root)[0]
        logging.info("packaging %s-%s", atom, ver)

        dblink = portage.dblink(
            cat, pn + "-" + ver, myroot=root, settings=portage.settings
        )
        contents = dblink.getcontents()
        for obj in contents:
            ptype = contents[obj][0]
            if not IsPathPackagable(ptype, obj):
                continue

            if ptype == "obj":
                # For native ELFs, we need to pull in their dependencies too.
                if FileIsCrosSdkElf(obj):
                    logging.debug("Adding ELF %s", obj)
                    elfs.add(obj)
            logging.debug("Adding path %s", obj)
            paths.add(obj)

    return paths, elfs


def _BuildInitialPackageRoot(
    output_dir, paths, elfs, ldpaths, path_rewrite_func=lambda x: x, root="/"
):
    """Link in all packable files and their runtime dependencies

    This also wraps up executable ELFs with helper scripts.

    Args:
        output_dir: The output directory to store files
        paths: All the files to include
        elfs: All the files which are ELFs (a subset of |paths|)
        ldpaths: A dict of static ldpath information
        path_rewrite_func: User callback to rewrite paths in output_dir
        root: The root path to pull all packages/files from
    """
    # Link in all the files.
    sym_paths = {}
    for path in paths:
        new_path = path_rewrite_func(path)
        logging.debug("Transformed %s to %s", path, new_path)
        dst = output_dir + new_path
        osutils.SafeMakedirs(os.path.dirname(dst))

        # Is this a symlink which we have to rewrite or wrap?
        # Delay wrap check until after we have created all paths.
        src = root + path
        if os.path.islink(src):
            tgt = os.readlink(src)
            if os.path.sep in tgt:
                sym_paths[lddtree.normpath(ReadlinkRoot(src, root))] = new_path

                # Rewrite absolute links to relative and then generate the
                # symlink ourselves. All other symlinks can be hardlinked below.
                if tgt[0] == "/":
                    tgt = os.path.relpath(tgt, os.path.dirname(new_path))
                    os.symlink(tgt, dst)
                    continue

        logging.debug("Linking path %s -> %s", src, dst)
        os.link(src, dst)

    # Locate all the dependencies for all the ELFs.  Stick them all in the
    # top level "lib" dir to make the wrapper simpler.  This exact path does
    # not matter since we execute ldso directly, and we tell the ldso the
    # exact path to search for its libraries.
    libdir = os.path.join(output_dir, "lib")
    osutils.SafeMakedirs(libdir)
    donelibs = set()
    basenamelibs = set()
    glibc_re = re.compile(r"/lib(c|pthread)[0-9.-]*\.so[0-9.-]*")
    for elf in elfs:
        e = lddtree.ParseELF(elf, root=root, ldpaths=ldpaths)
        logging.debug("Parsed elf %s data: %s", elf, e)
        interp = e["interp"]

        # TODO(b/187786323): Drop this hack once libopcodes linkage is fixed.
        if os.path.basename(elf).startswith("libopcodes-"):
            continue

        # Copy all the dependencies before we copy the program & generate
        # wrappers.
        for lib, lib_data in e["libs"].items():
            src = path = lib_data["path"]
            if path is None:
                logging.warning("%s: could not locate %s", elf, lib)
                continue

            # No need to try and copy the same source lib multiple times.
            if path in donelibs:
                continue
            donelibs.add(path)

            # Die if we try to normalize different source libs with the same
            # basename.
            if lib in basenamelibs:
                logging.error(
                    "Multiple sources detected for %s:\n  new: %s\n  old: %s",
                    os.path.join("/lib", lib),
                    path,
                    " ".join(
                        x
                        for x in donelibs
                        if x != path and os.path.basename(x) == lib
                    ),
                )
                # TODO(crbug.com/917193): Make this fatal.
                # cros_build_lib.Die('Unable to resolve lib conflicts')
                continue
            basenamelibs.add(lib)

            # Needed libs are the SONAME, but that is usually a symlink, not a
            # real file.  So link in the target rather than the symlink itself.
            # We have to walk all the possible symlinks (SONAME could point to a
            # symlink which points to a symlink), and we have to handle absolute
            # ourselves (since we have a "root" argument).
            dst = os.path.join(libdir, os.path.basename(path))
            src = ReadlinkRoot(src, root)

            logging.debug("Linking lib %s -> %s", root + src, dst)
            os.link(root + src, dst)

        # Do not create wrapper for libc. crbug.com/766827
        if interp and not glibc_re.search(elf):
            # Generate a wrapper if it is executable.
            interp = os.path.join("/lib", os.path.basename(interp))
            lddtree.GenerateLdsoWrapper(
                output_dir,
                path_rewrite_func(elf),
                interp,
                libpaths=e["rpath"] + e["runpath"],
            )
            FixClangXXWrapper(output_dir, path_rewrite_func(elf))

            # Wrap any symlinks to the wrapper.
            if elf in sym_paths:
                link = sym_paths[elf]
                GeneratePathWrapper(output_dir, link, elf)


def _EnvdGetVar(envd, var):
    """Given a Gentoo env.d file, extract a var from it

    Args:
        envd: The env.d file to load (may be a glob path)
        var: The var to extract

    Returns:
        The value of |var|
    """
    envds = glob.glob(envd)
    assert len(envds) == 1, "%s: should have exactly 1 env.d file" % envd
    envd = envds[0]
    return key_value_store.LoadFile(envd)[var]


def _ProcessBinutilsConfig(target, output_dir):
    """Do what binutils-config would have done"""
    binpath = os.path.join("/bin", target + "-")

    # Locate the bin dir holding the linker and perform some confidence checks
    binutils_bin_path = os.path.join(
        output_dir, "usr", toolchain.GetHostTuple(), target, "binutils-bin"
    )
    globpath = os.path.join(binutils_bin_path, "*")
    srcpath = glob.glob(globpath)
    assert len(srcpath) == 1, (
        "%s: matched more than one path. Is Gold enabled?" % globpath
    )
    srcpath = srcpath[0]
    ld_path = os.path.join(srcpath, "ld")
    assert os.path.exists(ld_path), "%s: linker is missing!" % ld_path
    ld_path = os.path.join(srcpath, "ld.bfd")
    assert os.path.exists(ld_path), "%s: linker is missing!" % ld_path

    srcpath = srcpath[len(output_dir) :]
    gccpath = os.path.join("/usr", "libexec", "gcc")
    for prog in os.listdir(output_dir + srcpath):
        # Skip binaries already wrapped.
        if not prog.endswith(".real"):
            GeneratePathWrapper(
                output_dir, binpath + prog, os.path.join(srcpath, prog)
            )
            GeneratePathWrapper(
                output_dir,
                os.path.join(gccpath, prog),
                os.path.join(srcpath, prog),
            )

    libpath = os.path.join("/usr", toolchain.GetHostTuple(), target, "lib")
    envd = os.path.join(output_dir, "etc", "env.d", "binutils", "*")
    srcpath = _EnvdGetVar(envd, "LIBPATH")
    os.symlink(
        os.path.relpath(srcpath, os.path.dirname(libpath)), output_dir + libpath
    )


def _ProcessGccConfig(target, output_dir):
    """Do what gcc-config would have done"""
    binpath = "/bin"
    envd = os.path.join(output_dir, "etc", "env.d", "gcc", "*")
    srcpath = _EnvdGetVar(envd, "GCC_PATH")
    for prog in os.listdir(output_dir + srcpath):
        # Skip binaries already wrapped.
        if (
            not prog.endswith(".real")
            and not prog.endswith(".elf")
            and prog.startswith(target)
        ):
            GeneratePathWrapper(
                output_dir,
                os.path.join(binpath, prog),
                os.path.join(srcpath, prog),
            )
    return srcpath


def _ProcessSysrootWrappers(_target, output_dir, srcpath):
    """Remove chroot-specific things from our sysroot wrappers"""
    # Disable ccache since we know it won't work outside of chroot.

    # Use the version of the wrapper that does not use ccache.
    for sysroot_wrapper in glob.glob(
        os.path.join(output_dir + srcpath, "sysroot_wrapper*.ccache")
    ):
        # Can't update the wrapper in place to not affect the chroot,
        # but only the extracted toolchain.
        os.unlink(sysroot_wrapper)
        shutil.copy(sysroot_wrapper[:-6] + "noccache", sysroot_wrapper)
        shutil.copy(
            sysroot_wrapper[:-6] + "noccache.elf", sysroot_wrapper + ".elf"
        )


def _ProcessClangWrappers(target, output_dir):
    """Remove chroot-specific things from our sysroot wrappers"""
    clang_bin_path = "/usr/bin"
    # Disable ccache from clang wrappers.
    _ProcessSysrootWrappers(target, output_dir, clang_bin_path)
    GeneratePathWrapper(
        output_dir, f"/bin/{target}-clang", f"/usr/bin/{target}-clang"
    )
    GeneratePathWrapper(
        output_dir, f"/bin/{target}-clang++", f"/usr/bin/{target}-clang++"
    )


def _CreateMainLibDir(target, output_dir):
    """Create some lib dirs so that compiler can get the right Gcc paths"""
    osutils.SafeMakedirs(os.path.join(output_dir, "usr", target, "lib"))
    osutils.SafeMakedirs(os.path.join(output_dir, "usr", target, "usr/lib"))


def _CreateRemoteToolchainFile(output_dir):
    """Create a remote_toolchain_inputs file for reclient/RBE"""
    # The inputs file lists all files/shared libraries needed to run clang.
    # All inputs are relative to location of clang binary and one input
    # location per line of file e.g.
    # clang-13.elf
    # clang++-13.elf
    # relative/path/to/clang/resource/directory

    clang_path = os.path.join(output_dir, "usr/bin")
    # Add needed shared libraries and internal files e.g. allowlists.
    toolchain_inputs = ["../../lib"]
    clang_shared_dirs = glob.glob(
        os.path.join(output_dir, "usr/lib64/clang/*/share")
    )
    for clang_dir in clang_shared_dirs:
        toolchain_inputs.append(os.path.relpath(clang_dir, clang_path))

    # Add actual clang binaries/wrappers.
    for clang_files in glob.glob(os.path.join(clang_path, "clang*-[0-9]*")):
        toolchain_inputs.append(os.path.basename(clang_files))

    with open(
        os.path.join(clang_path, "remote_toolchain_inputs"),
        "w",
        encoding="utf-8",
    ) as f:
        f.writelines("%s\n" % line for line in toolchain_inputs)


def _ProcessDistroCleanups(target, output_dir):
    """Clean up the tree and remove all distro-specific requirements

    Args:
        target: The toolchain target name
        output_dir: The output directory to clean up
    """
    _ProcessBinutilsConfig(target, output_dir)
    gcc_path = _ProcessGccConfig(target, output_dir)
    _ProcessSysrootWrappers(target, output_dir, gcc_path)
    _ProcessClangWrappers(target, output_dir)
    _CreateMainLibDir(target, output_dir)
    _CreateRemoteToolchainFile(output_dir)

    osutils.RmDir(os.path.join(output_dir, "etc"))


def CreatePackagableRoot(target, output_dir, ldpaths, root="/"):
    """Setup a tree from the packages for the specified target

    This populates a path with all the files from toolchain packages so that
    a tarball can easily be generated from the result.

    Args:
        target: The target to create a packagable root from
        output_dir: The output directory to place all the files
        ldpaths: A dict of static ldpath information
        root: The root path to pull all packages/files from
    """
    # Find all the files owned by the packages for this target.
    paths, elfs = _GetFilesForTarget(target, root=root)

    # Link in all the package's files, any ELF dependencies, and wrap any
    # executable ELFs with helper scripts.
    def MoveUsrBinToBin(path):
        """Move /usr/bin to /bin so people can just use that toplevel dir

        Note we do not apply this to clang or rust; there is correlation between
        clang's search path for libraries / inclusion and its installation path.
        """
        NO_MOVE_PATTERNS = ("clang", "rust", "cargo", "sysroot_wrapper")
        if path.startswith("/usr/bin/") and not any(
            x in path for x in NO_MOVE_PATTERNS
        ):
            return path[4:]
        return path

    _BuildInitialPackageRoot(
        output_dir,
        paths,
        elfs,
        ldpaths,
        path_rewrite_func=MoveUsrBinToBin,
        root=root,
    )

    # The packages, when part of the normal distro, have helper scripts
    # that setup paths and such.  Since we are making this standalone, we
    # need to preprocess all that ourselves.
    _ProcessDistroCleanups(target, output_dir)


def CreatePackages(targets_wanted, output_dir, root="/"):
    """Create redistributable cross-compiler packages for the specified targets

    This creates toolchain packages that should be usable in conjunction with
    a downloaded sysroot (created elsewhere).

    Tarballs (one per target) will be created in $PWD.

    Args:
        targets_wanted: The targets to package up.
        output_dir: The directory to put the packages in.
        root: The root path to pull all packages/files from.
    """
    logging.info("Writing tarballs to %s", output_dir)
    osutils.SafeMakedirs(output_dir)
    ldpaths = lddtree.LoadLdpaths(root)
    targets = ExpandTargets(targets_wanted)

    # b/282231712: Stash temporary path structure at |root|, so we have control
    # over cross-device linking. The default base directory (/tmp) might be on
    # a different filesystem/mount, so hard links won't work.
    with osutils.TempDir(base_dir=root, prefix="create-packages") as tempdir:
        logging.debug("Using tempdir: %s", tempdir)

        # We have to split the root generation from the compression stages.
        # This is because we hardlink in all the files (to avoid overhead of
        # reading/writing the copies multiple times).  But tar gets angry if a
        # file's hardlink count changes from when it starts reading a file to
        # when it finishes.
        with parallel.BackgroundTaskRunner(CreatePackagableRoot) as queue:
            for target in targets:
                output_target_dir = os.path.join(tempdir, target)
                queue.put([target, output_target_dir, ldpaths, root])

        # Build the tarball.
        with parallel.BackgroundTaskRunner(
            cros_build_lib.CreateTarball
        ) as queue:
            for target in targets:
                tar_file = os.path.join(output_dir, target + ".tar.xz")
                queue.put([tar_file, os.path.join(tempdir, target)])


def GetParser():
    """Return a command line parser."""
    parser = commandline.ArgumentParser(description=__doc__)
    parser.add_argument(
        "-u",
        "--nousepkg",
        action="store_false",
        dest="usepkg",
        default=True,
        help="Do not use prebuilt packages",
    )
    parser.add_argument(
        "-d",
        "--deleteold",
        action="store_true",
        dest="deleteold",
        default=False,
        help="Unmerge deprecated packages",
    )
    parser.add_argument(
        "-t",
        "--targets",
        dest="targets",
        default="sdk",
        help="Comma separated list of tuples. Special keywords "
        "'host', 'sdk', 'boards', and 'all' are "
        "allowed. Defaults to 'sdk'.",
    )
    parser.add_argument(
        "--include-boards",
        default="",
        metavar="BOARDS",
        help="Comma separated list of boards whose toolchains we "
        "will always include. Default: none",
    )
    parser.add_argument(
        "--hostonly",
        dest="hostonly",
        default=False,
        action="store_true",
        help="Only setup the host toolchain. "
        "Useful for bootstrapping chroot",
    )
    parser.add_argument(
        "--show-board-cfg",
        "--show-cfg",
        dest="cfg_name",
        default=None,
        help="Board  to list toolchains tuples for",
    )
    parser.add_argument(
        "--show-packages",
        default=None,
        help="List all packages the specified target uses",
    )
    parser.add_argument(
        "--create-packages",
        action="store_true",
        default=False,
        help="Build redistributable packages",
    )
    parser.add_argument(
        "--output-dir",
        default=os.getcwd(),
        type="path",
        help="Output directory",
    )
    parser.add_argument(
        "--reconfig",
        default=False,
        action="store_true",
        help="Reload crossdev config and reselect toolchains",
    )
    parser.add_argument(
        "--sysroot",
        type="path",
        help="The sysroot in which to install the toolchains",
    )
    return parser


def main(argv):
    parser = GetParser()
    options = parser.parse_args(argv)
    options.Freeze()

    # Figure out what we're supposed to do and reject conflicting options.
    conflicting_options = (
        options.cfg_name,
        options.show_packages,
        options.create_packages,
    )
    if sum(bool(x) for x in conflicting_options) > 1:
        parser.error(
            "conflicting options: create-packages & show-packages & "
            "show-board-cfg"
        )

    targets_wanted = set(options.targets.split(","))
    boards_wanted = (
        set(options.include_boards.split(","))
        if options.include_boards
        else set()
    )

    if options.cfg_name:
        ShowConfig(options.cfg_name)
    elif options.show_packages is not None:
        cros_build_lib.AssertInsideChroot()
        target = options.show_packages
        Crossdev.Load(False)
        for package in GetTargetPackages(target):
            print(GetPortagePackage(target, package))
    elif options.create_packages:
        cros_build_lib.AssertInsideChroot()
        Crossdev.Load(False)
        CreatePackages(targets_wanted, options.output_dir)
    else:
        cros_build_lib.AssertInsideChroot()
        # This has to be always run as root.
        if osutils.IsNonRootUser():
            cros_build_lib.Die("this script must be run as root")

        Crossdev.Load(options.reconfig)
        root = options.sysroot or "/"
        UpdateToolchains(
            options.usepkg,
            options.deleteold,
            options.hostonly,
            options.reconfig,
            targets_wanted,
            boards_wanted,
            root=root,
        )
        Crossdev.Save()

    return 0
