Formatting: Format all python code with black.
This CL is probably not what you're looking for, it's only
automated formatting. Ignore it with
`git blame --ignore-rev <revision>` for this commit.
BUG=b:233893248
TEST=CQ
Change-Id: I66591d7a738d241aed3290138c0f68065ab10a6d
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/3879174
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Tested-by: Alex Klein <saklein@chromium.org>
diff --git a/scripts/cros_setup_toolchains.py b/scripts/cros_setup_toolchains.py
index 712394a..d029c94 100644
--- a/scripts/cros_setup_toolchains.py
+++ b/scripts/cros_setup_toolchains.py
@@ -25,23 +25,26 @@
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
+ # 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 = os.path.join(constants.CHROMITE_BIN_DIR, 'parallel_emerge')
-PACKAGE_STABLE = '[stable]'
+EMERGE_CMD = os.path.join(constants.CHROMITE_BIN_DIR, "parallel_emerge")
+PACKAGE_STABLE = "[stable]"
CHROMIUMOS_OVERLAY = os.path.join(
- constants.CHROOT_SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR)
+ constants.CHROOT_SOURCE_ROOT, constants.CHROMIUMOS_OVERLAY_DIR
+)
ECLASS_OVERLAY = os.path.join(
- constants.CHROOT_SOURCE_ROOT, constants.ECLASS_OVERLAY_DIR)
+ 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'
+ 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
@@ -52,28 +55,28 @@
# 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',
+ "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/coreboot-sdk',
- 'dev-embedded/hps-sdk',
- 'dev-embedded/ti50-sdk',
+ "dev-lang/rust",
+ "virtual/target-sdk-post-cross",
+ "dev-embedded/coreboot-sdk",
+ "dev-embedded/hps-sdk",
+ "dev-embedded/ti50-sdk",
)
# New packages that we're in the process of adding to the SDK. Since the SDK
@@ -84,1328 +87,1469 @@
# 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',
+ "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_GO_ARGS = ["--ex-pkg", "dev-lang/go"]
-CROSSDEV_LIBXCRYPT_ARGS = ['--ex-pkg', 'sys-libs/libxcrypt']
+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',
+ "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']
+CROSSDEV_COMPILER_RT_ARGS = ["--ex-pkg", "sys-libs/compiler-rt"]
TARGET_LLVM_PKGS_ENABLED = (
- 'armv7m-cros-eabi',
- 'armv7a-cros-linux-gnueabi',
- 'armv7a-cros-linux-gnueabihf',
- 'aarch64-cros-linux-gnu',
- 'i686-cros-linux-gnu',
- 'x86_64-cros-linux-gnu',
+ "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'],
+ "ex_llvm-libunwind": ["--ex-pkg", "sys-libs/llvm-libunwind"],
+ "ex_libcxx": ["--ex-pkg", "sys-libs/libcxx"],
}
+
class Crossdev(object):
- """Class for interacting with crossdev and caching its output."""
+ """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 = {
- 'rust': 'dev-lang',
- 'llvm': 'sys-devel',
- 'llvm-libunwind': 'sys-libs',
- 'libcxx': 'sys-libs',
- 'elfutils': 'dev-libs',
- }
-
- @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,
+ _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 = {
+ "rust": "dev-lang",
+ "llvm": "sys-devel",
+ "llvm-libunwind": "sys-libs",
+ "libcxx": "sys-libs",
+ "elfutils": "dev-libs",
}
- logging.debug('cache: checking file: %s', cls._CACHE_FILE)
- if reconfig:
- logging.debug('cache: forcing regen due to reconfig')
- return
+ @classmethod
+ def Load(cls, reconfig):
+ """Load crossdev cache from disk.
- 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
+ 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()
- 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') 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(),
+ cls._CACHE = {
+ "crossdev_version": crossdev_version,
+ "setup_toolchains_hash": setup_toolchains_hash,
}
- if target == 'host':
- packages_list = HOST_PACKAGES
+
+ 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:
- 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', '--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:
- 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()
+ logging.debug("cache: content is up-to-date!")
+ cls._CACHE = data
- manual_pkgs = cls.MANUAL_PKGS
+ @classmethod
+ def Save(cls):
+ """Store crossdev cache on disk."""
+ # Save the cache from the successful run.
+ with open(cls._CACHE_FILE, "w") as f:
+ json.dump(cls._CACHE, f)
- 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)
+ @classmethod
+ def GetConfig(cls, target):
+ """Returns a map of crossdev provided variables about a tuple."""
+ CACHE_ATTR = "_target_tuple_map"
- val[target] = conf
+ 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", "--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:
+ 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()
- return val[target]
+ manual_pkgs = cls.MANUAL_PKGS
- @classmethod
- def UpdateTargets(cls, targets, usepkg, config_only=False):
- """Calls crossdev to initialize a cross target.
+ 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)
- 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()
+ val[target] = conf
- # 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)
+ return val[target]
- @classmethod
- def _UpdateTarget(cls, target_name, target, usepkg, config_only):
- """Calls crossdev to initialize a cross target.
+ @classmethod
+ def UpdateTargets(cls, targets, usepkg, config_only=False):
+ """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', '--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'])
+ 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()
- overlays = ' '.join((CHROMIUMOS_OVERLAY, ECLASS_OVERLAY, STABLE_OVERLAY))
- cmdbase.extend(['--overlays', overlays])
- cmdbase.extend(['--ov-output', CROSSDEV_OVERLAY])
+ # 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)
- cmd = cmdbase + ['-t', target_name]
+ @classmethod
+ def _UpdateTarget(cls, target_name, target, usepkg, config_only):
+ """Calls crossdev to initialize a cross target.
- 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])
+ 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", "--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"]
+ )
- cmd.extend(target['crossdev'].split())
+ overlays = " ".join(
+ (CHROMIUMOS_OVERLAY, ECLASS_OVERLAY, STABLE_OVERLAY)
+ )
+ cmdbase.extend(["--overlays", overlays])
+ cmdbase.extend(["--ov-output", CROSSDEV_OVERLAY])
- 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)
+ cmd = cmdbase + ["-t", target_name]
- configured_targets.append(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')]
+ """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)
+ """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]
+ """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.
+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.
+ 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
+ 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.
+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.
+ 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
+ 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.
+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.
+ 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.
+ 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
+ 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.
+ """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.
+ 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.
+ 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)
+ 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 []
+ 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.
+ """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.
+ 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)
+ 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)):
+ 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
- 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.
+ """Removes a package.mask file for the given platform.
- The pre-existing package.mask files can mess with the keywords.
+ 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)
+ 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
+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.
+ 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')) 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
+ Args:
+ root: The install root where we want libtool rebuilt.
+ """
+ needs_update = False
+ with open(os.path.join(root, "usr/bin/libtool")) 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:
+ 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')
+ 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.
+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']:
+ 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:
- # 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
+ 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)
- # 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]
+ packages = [pkg for pkg, vers in mergemap.items() if vers]
+ if not packages:
+ logging.info("Nothing to update!")
+ return False
- if target.startswith('host'):
- # *-config is the only tool treating host identically (by tuple).
- target = toolchain.GetHostTuple()
+ logging.info("Updating packages:")
+ logging.info("%s", packages)
- # And finally, attach target to it.
- desired = '%s-%s' % (target, desired)
+ cmd = [EMERGE_CMD, "--oneshot", "--update"]
+ if usepkg:
+ cmd.extend(["--getbinpkg", "--usepkgonly"])
+ if root != "/":
+ cmd.extend(["--sysroot=%s" % root, "--root=%s" % root])
- 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]
+ 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
- # Do not reconfig when the current is live or nothing needs to be done.
- extra_env = {'ROOT': root} if root != '/' else None
- if current != desired and current != '9999':
- cmd = [package + '-config', desired]
- cros_build_lib.run(cmd, print_cmd=False, extra_env=extra_env)
+
+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 != desired and current != "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
+ """Expand any possible toolchain aliases into full targets
- This will expand 'all' and 'sdk' into the respective toolchain tuples.
+ This will expand 'all' and 'sdk' into the respective toolchain tuples.
- Args:
- targets_wanted: The targets specified by the user.
+ 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 {}
+ 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)
+ 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}
+ # 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.
+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)
+ 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]
+ # 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))
+ # 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)
+ # 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'] = {}
+ # 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'] = {}
+ # 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)
+ # 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)
+ 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)
+ # 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|
+ """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))))
+ 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
+ """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.
+ 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)),
- }
+ 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
+ # 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)
+"""
+ % 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++
+ """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].
+ 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.
+ 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.
+ 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.
+ 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)
+ 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++')
+ 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 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))
+ # 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++'))
+ # 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
+ """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.
+ 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
+ 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')
+ 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?
+ """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.
+ 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`)
+ 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
+ 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))
+ 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|
+ """Like os.readlink(), but relative to a |root|
- Args:
- path: The symlink to read
- root: The path to use for resolving absolute symlinks
+ 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
+ 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|
+def _GetFilesForTarget(target, root="/"):
+ """Locate all the files to package for |target|
- This does not cover ELF dependencies.
+ This does not cover ELF dependencies.
- Args:
- target: The toolchain target name
- root: The root path to pull all packages from
+ 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()
+ 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):
+ # 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
+ # 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'
+ # 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:
- new_target = 'armv7a-cros-linux-gnueabihf'
- atom = GetPortagePackage(new_target, pkg)
- else:
- atom = GetPortagePackage(target, pkg)
+ atom = GetPortagePackage(target, pkg)
- cat, pn = atom.split('/')
- ver = GetInstalledPackageVersions(atom, root=root)[0]
- logging.info('packaging %s-%s', atom, ver)
+ 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
+ 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)
+ 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
+ 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
+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.
+ 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))
+ 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
+ # 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
+ # 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)
+ 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$')
- for elf in elfs:
- e = lddtree.ParseELF(elf, root=root, ldpaths=ldpaths)
- logging.debug('Parsed elf %s data: %s', elf, e)
- interp = e['interp']
+ # 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$")
+ 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(crbug.com/917193): Drop this hack once libopcodes linkage is fixed.
- if os.path.basename(elf).startswith('libopcodes-'):
- continue
+ # TODO(crbug.com/917193): 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
+ # 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)
+ # 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)
+ # 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)
+ # 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)
+ 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))
+ # 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)
+ # 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
+ """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
+ 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]
+ 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 + '-')
+ """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
+ # 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))
+ 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)
+ 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
+ """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.
+ """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')
+ # 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++')
+ """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'))
+ """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
+ """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))
+ 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))
+ # 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') as f:
- f.writelines('%s\n' % line for line in toolchain_inputs)
+ with open(os.path.join(clang_path, "remote_toolchain_inputs"), "w") 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
+ """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.
+ Args:
+ target: The toolchain target name
+ output_dir: The output directory to clean up
"""
- 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)
+ _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)
- # 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)
+ osutils.RmDir(os.path.join(output_dir, "etc"))
-def CreatePackages(targets_wanted, output_dir, root='/'):
- """Create redistributable cross-compiler packages for the specified targets
+def CreatePackagableRoot(target, output_dir, ldpaths, root="/"):
+ """Setup a tree from the packages for the specified target
- This creates toolchain packages that should be usable in conjunction with
- a downloaded sysroot (created elsewhere).
+ This populates a path with all the files from toolchain packages so that
+ a tarball can easily be generated from the result.
- Tarballs (one per target) will be created in $PWD.
+ 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)
- 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)
+ # 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
- with osutils.TempDir(prefix='create-packages') as tempdir:
- logging.debug('Using tempdir: %s', tempdir)
+ 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
- # 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])
+ _BuildInitialPackageRoot(
+ output_dir,
+ paths,
+ elfs,
+ ldpaths,
+ path_rewrite_func=MoveUsrBinToBin,
+ root=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)])
+ # 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)
+
+ with osutils.TempDir(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
+ """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()
+ 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')
+ # 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())
+ 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')
+ 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()
+ 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
+ return 0