blob: e64cb9dd0f26312f4f8389e7a1b4d43660c58136 [file] [log] [blame]
Zdenek Behan508dcce2011-12-05 15:39:32 +01001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Mike Frysinger750c5f52014-09-16 16:16:57 -04005"""This script manages the installed toolchains in the chroot."""
Zdenek Behan508dcce2011-12-05 15:39:32 +01006
Mike Frysinger383367e2014-09-16 15:06:17 -04007from __future__ import print_function
8
Zdenek Behan508dcce2011-12-05 15:39:32 +01009import copy
Mike Frysinger3ed47722017-08-08 14:59:08 -040010import errno
Mike Frysinger35247af2012-11-16 18:58:06 -050011import glob
Mike Frysinger3ed47722017-08-08 14:59:08 -040012import hashlib
Mike Frysinger7ccee992012-06-01 21:27:59 -040013import json
Zdenek Behan508dcce2011-12-05 15:39:32 +010014import os
Rahul Chaudhrya8127bb2016-07-22 15:53:17 -070015import re
Zdenek Behan508dcce2011-12-05 15:39:32 +010016
Aviv Keshetb7519e12016-10-04 00:50:00 -070017from chromite.lib import constants
Mike Frysinger506e75f2012-12-17 14:21:13 -050018from chromite.lib import commandline
Brian Harring503f3ab2012-03-09 21:39:41 -080019from chromite.lib import cros_build_lib
Ralph Nathan03047282015-03-23 11:09:32 -070020from chromite.lib import cros_logging as logging
Brian Harringaf019fb2012-05-10 15:06:13 -070021from chromite.lib import osutils
Mike Frysinger35247af2012-11-16 18:58:06 -050022from chromite.lib import parallel
David James27ac4ae2012-12-03 23:16:15 -080023from chromite.lib import toolchain
Mike Frysinger35247af2012-11-16 18:58:06 -050024
25# Needs to be after chromite imports.
26import lddtree
Zdenek Behan508dcce2011-12-05 15:39:32 +010027
Mike Frysinger31596002012-12-03 23:54:24 -050028if cros_build_lib.IsInsideChroot():
29 # Only import portage after we've checked that we're inside the chroot.
30 # Outside may not have portage, in which case the above may not happen.
31 # We'll check in main() if the operation needs portage.
Don Garrett25f309a2014-03-19 14:02:12 -070032 # pylint: disable=F0401
Mike Frysinger31596002012-12-03 23:54:24 -050033 import portage
Zdenek Behan508dcce2011-12-05 15:39:32 +010034
35
Matt Tennantf1e30972012-03-02 16:30:07 -080036EMERGE_CMD = os.path.join(constants.CHROMITE_BIN_DIR, 'parallel_emerge')
Zdenek Behan508dcce2011-12-05 15:39:32 +010037PACKAGE_STABLE = '[stable]'
38PACKAGE_NONE = '[none]'
39SRC_ROOT = os.path.realpath(constants.SOURCE_ROOT)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010040
41CHROMIUMOS_OVERLAY = '/usr/local/portage/chromiumos'
Christopher Wileyb22c0712015-06-02 10:37:03 -070042ECLASS_OVERLAY = '/usr/local/portage/eclass-overlay'
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010043STABLE_OVERLAY = '/usr/local/portage/stable'
44CROSSDEV_OVERLAY = '/usr/local/portage/crossdev'
Zdenek Behan508dcce2011-12-05 15:39:32 +010045
46
47# TODO: The versions are stored here very much like in setup_board.
48# The goal for future is to differentiate these using a config file.
49# This is done essentially by messing with GetDesiredPackageVersions()
50DEFAULT_VERSION = PACKAGE_STABLE
51DEFAULT_TARGET_VERSION_MAP = {
Zdenek Behan508dcce2011-12-05 15:39:32 +010052}
53TARGET_VERSION_MAP = {
Mike Frysingerd6e2df02014-11-26 02:55:04 -050054 'host' : {
55 'gdb' : PACKAGE_NONE,
56 },
Zdenek Behan508dcce2011-12-05 15:39:32 +010057}
Rahul Chaudhry4b803052015-05-13 15:25:56 -070058
59# Enable the Go compiler for these targets.
60TARGET_GO_ENABLED = (
61 'x86_64-cros-linux-gnu',
Rahul Chaudhry4b803052015-05-13 15:25:56 -070062 'armv7a-cros-linux-gnueabi',
63)
64CROSSDEV_GO_ARGS = ['--ex-pkg', 'dev-lang/go']
65
Manoj Gupta1b5642e2017-03-08 16:44:12 -080066# Enable llvm's compiler-rt for these targets.
67TARGET_COMPILER_RT_ENABLED = (
68 'armv7a-cros-linux-gnueabi',
Manoj Gupta946abb42017-04-12 14:27:19 -070069 'aarch64-cros-linux-gnu',
Manoj Gupta1b5642e2017-03-08 16:44:12 -080070)
71CROSSDEV_COMPILER_RT_ARGS = ['--ex-pkg', 'sys-libs/compiler-rt']
72
Manoj Gupta946abb42017-04-12 14:27:19 -070073TARGET_LLVM_PKGS_ENABLED = (
74 'armv7a-cros-linux-gnueabi',
75 'aarch64-cros-linux-gnu',
76 'x86_64-cros-linux-gnu',
77)
78
79LLVM_PKGS_TABLE = {
Yunlian Jiangbb2a3d32017-04-26 14:44:09 -070080 'ex_libcxxabi' : ['--ex-pkg', 'sys-libs/libcxxabi'],
81 'ex_libcxx' : ['--ex-pkg', 'sys-libs/libcxx'],
Manoj Gupta946abb42017-04-12 14:27:19 -070082}
83
Zdenek Behan508dcce2011-12-05 15:39:32 +010084# Overrides for {gcc,binutils}-config, pick a package with particular suffix.
85CONFIG_TARGET_SUFFIXES = {
Mike Frysingerd6e2df02014-11-26 02:55:04 -050086 'binutils' : {
Mike Frysinger8a83c622015-05-28 00:35:05 -040087 'armv6j-cros-linux-gnueabi': '-gold',
Han Shen43b84422015-02-19 11:38:13 -080088 'armv7a-cros-linux-gnueabi': '-gold',
Mike Frysingerd6e2df02014-11-26 02:55:04 -050089 'i686-pc-linux-gnu' : '-gold',
90 'x86_64-cros-linux-gnu' : '-gold',
91 },
Zdenek Behan508dcce2011-12-05 15:39:32 +010092}
Zdenek Behan508dcce2011-12-05 15:39:32 +010093# Global per-run cache that will be filled ondemand in by GetPackageMap()
94# function as needed.
95target_version_map = {
96}
97
98
David James66a09c42012-11-05 13:31:38 -080099class Crossdev(object):
100 """Class for interacting with crossdev and caching its output."""
101
102 _CACHE_FILE = os.path.join(CROSSDEV_OVERLAY, '.configured.json')
103 _CACHE = {}
Han Shene23782f2016-02-18 12:20:00 -0800104 # Packages that needs separate handling, in addition to what we have from
105 # crossdev.
106 MANUAL_PKGS = {
Manoj Guptaf0a602e2017-08-02 10:25:45 -0700107 'clang': 'sys-devel',
Han Shene23782f2016-02-18 12:20:00 -0800108 'llvm': 'sys-devel',
Manoj Gupta20cfc6c2017-07-19 15:49:55 -0700109 'libcxxabi': 'sys-libs',
110 'libcxx': 'sys-libs',
Han Shene23782f2016-02-18 12:20:00 -0800111 }
David James66a09c42012-11-05 13:31:38 -0800112
113 @classmethod
114 def Load(cls, reconfig):
Mike Frysinger3ed47722017-08-08 14:59:08 -0400115 """Load crossdev cache from disk.
116
117 We invalidate the cache when crossdev updates or this script changes.
118 """
David James90239b92012-11-05 15:31:34 -0800119 crossdev_version = GetStablePackageVersion('sys-devel/crossdev', True)
Mike Frysinger3ed47722017-08-08 14:59:08 -0400120 # If we run the compiled/cached .pyc file, we'll read/hash that when we
121 # really always want to track the source .py file.
122 script = os.path.abspath(__file__)
123 if script.endswith('.pyc'):
124 script = script[:-1]
125 setup_toolchains_hash = hashlib.md5(osutils.ReadFile(script)).hexdigest()
126
127 cls._CACHE = {
128 'crossdev_version': crossdev_version,
129 'setup_toolchains_hash': setup_toolchains_hash,
130 }
131
132 logging.debug('cache: checking file: %s', cls._CACHE_FILE)
133 if reconfig:
134 logging.debug('cache: forcing regen due to reconfig')
135 return
136
137 try:
138 file_data = osutils.ReadFile(cls._CACHE_FILE)
139 except IOError as e:
140 if e.errno != errno.ENOENT:
141 logging.warning('cache: reading failed: %s', e)
142 osutils.SafeUnlink(cls._CACHE_FILE)
143 return
144
145 try:
146 data = json.loads(file_data)
147 except ValueError as e:
148 logging.warning('cache: ignoring invalid content: %s', e)
149 return
150
151 if crossdev_version != data.get('crossdev_version'):
152 logging.debug('cache: rebuilding after crossdev upgrade')
153 elif setup_toolchains_hash != data.get('setup_toolchains_hash'):
154 logging.debug('cache: rebuilding after cros_setup_toolchains change')
155 else:
156 logging.debug('cache: content is up-to-date!')
157 cls._CACHE = data
David James66a09c42012-11-05 13:31:38 -0800158
159 @classmethod
160 def Save(cls):
161 """Store crossdev cache on disk."""
162 # Save the cache from the successful run.
163 with open(cls._CACHE_FILE, 'w') as f:
164 json.dump(cls._CACHE, f)
165
166 @classmethod
167 def GetConfig(cls, target):
168 """Returns a map of crossdev provided variables about a tuple."""
169 CACHE_ATTR = '_target_tuple_map'
170
171 val = cls._CACHE.setdefault(CACHE_ATTR, {})
172 if not target in val:
173 # Find out the crossdev tuple.
174 target_tuple = target
175 if target == 'host':
David James27ac4ae2012-12-03 23:16:15 -0800176 target_tuple = toolchain.GetHostTuple()
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700177 # Build the crossdev command.
178 cmd = ['crossdev', '--show-target-cfg', '--ex-gdb']
Manoj Gupta1b5642e2017-03-08 16:44:12 -0800179 if target in TARGET_COMPILER_RT_ENABLED:
180 cmd.extend(CROSSDEV_COMPILER_RT_ARGS)
Manoj Guptab8181562017-05-21 10:18:59 -0700181 if target in TARGET_GO_ENABLED:
182 cmd.extend(CROSSDEV_GO_ARGS)
Manoj Gupta946abb42017-04-12 14:27:19 -0700183 if target in TARGET_LLVM_PKGS_ENABLED:
184 for pkg in LLVM_PKGS_TABLE:
185 cmd.extend(LLVM_PKGS_TABLE[pkg])
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700186 cmd.extend(['-t', target_tuple])
David James66a09c42012-11-05 13:31:38 -0800187 # Catch output of crossdev.
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700188 out = cros_build_lib.RunCommand(cmd, print_cmd=False,
189 redirect_stdout=True).output.splitlines()
David James66a09c42012-11-05 13:31:38 -0800190 # List of tuples split at the first '=', converted into dict.
Han Shene23782f2016-02-18 12:20:00 -0800191 conf = dict((k, cros_build_lib.ShellUnquote(v))
192 for k, v in (x.split('=', 1) for x in out))
193 conf['crosspkgs'] = conf['crosspkgs'].split()
194
195 for pkg, cat in cls.MANUAL_PKGS.iteritems():
Mike Frysinger3bba5032016-09-20 14:15:04 -0400196 conf[pkg + '_pn'] = pkg
197 conf[pkg + '_category'] = cat
198 if pkg not in conf['crosspkgs']:
199 conf['crosspkgs'].append(pkg)
Han Shene23782f2016-02-18 12:20:00 -0800200
201 val[target] = conf
202
David James66a09c42012-11-05 13:31:38 -0800203 return val[target]
204
205 @classmethod
206 def UpdateTargets(cls, targets, usepkg, config_only=False):
207 """Calls crossdev to initialize a cross target.
208
209 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700210 targets: The list of targets to initialize using crossdev.
211 usepkg: Copies the commandline opts.
212 config_only: Just update.
David James66a09c42012-11-05 13:31:38 -0800213 """
214 configured_targets = cls._CACHE.setdefault('configured_targets', [])
215
216 cmdbase = ['crossdev', '--show-fail-log']
217 cmdbase.extend(['--env', 'FEATURES=splitdebug'])
218 # Pick stable by default, and override as necessary.
219 cmdbase.extend(['-P', '--oneshot'])
220 if usepkg:
221 cmdbase.extend(['-P', '--getbinpkg',
222 '-P', '--usepkgonly',
223 '--without-headers'])
224
Christopher Wileyb22c0712015-06-02 10:37:03 -0700225 overlays = ' '.join((CHROMIUMOS_OVERLAY, ECLASS_OVERLAY, STABLE_OVERLAY))
David James66a09c42012-11-05 13:31:38 -0800226 cmdbase.extend(['--overlays', overlays])
227 cmdbase.extend(['--ov-output', CROSSDEV_OVERLAY])
228
229 for target in targets:
230 if config_only and target in configured_targets:
231 continue
232
233 cmd = cmdbase + ['-t', target]
234
235 for pkg in GetTargetPackages(target):
236 if pkg == 'gdb':
237 # Gdb does not have selectable versions.
238 cmd.append('--ex-gdb')
Manoj Guptab8181562017-05-21 10:18:59 -0700239 elif pkg == 'ex_compiler-rt':
240 cmd.extend(CROSSDEV_COMPILER_RT_ARGS)
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700241 elif pkg == 'ex_go':
242 # Go does not have selectable versions.
243 cmd.extend(CROSSDEV_GO_ARGS)
Manoj Gupta946abb42017-04-12 14:27:19 -0700244 elif pkg in LLVM_PKGS_TABLE:
245 cmd.extend(LLVM_PKGS_TABLE[pkg])
Han Shene23782f2016-02-18 12:20:00 -0800246 elif pkg in cls.MANUAL_PKGS:
247 pass
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700248 else:
249 # The first of the desired versions is the "primary" one.
250 version = GetDesiredPackageVersions(target, pkg)[0]
251 cmd.extend(['--%s' % pkg, version])
David James66a09c42012-11-05 13:31:38 -0800252
253 cmd.extend(targets[target]['crossdev'].split())
254 if config_only:
255 # In this case we want to just quietly reinit
256 cmd.append('--init-target')
257 cros_build_lib.RunCommand(cmd, print_cmd=False, redirect_stdout=True)
258 else:
259 cros_build_lib.RunCommand(cmd)
260
261 configured_targets.append(target)
262
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100263
Zdenek Behan508dcce2011-12-05 15:39:32 +0100264def GetPackageMap(target):
265 """Compiles a package map for the given target from the constants.
266
267 Uses a cache in target_version_map, that is dynamically filled in as needed,
268 since here everything is static data and the structuring is for ease of
269 configurability only.
270
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500271 Args:
272 target: The target for which to return a version map
Zdenek Behan508dcce2011-12-05 15:39:32 +0100273
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500274 Returns:
275 A map between packages and desired versions in internal format
276 (using the PACKAGE_* constants)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100277 """
278 if target in target_version_map:
279 return target_version_map[target]
280
281 # Start from copy of the global defaults.
282 result = copy.copy(DEFAULT_TARGET_VERSION_MAP)
283
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100284 for pkg in GetTargetPackages(target):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100285 # prefer any specific overrides
286 if pkg in TARGET_VERSION_MAP.get(target, {}):
287 result[pkg] = TARGET_VERSION_MAP[target][pkg]
288 else:
289 # finally, if not already set, set a sane default
290 result.setdefault(pkg, DEFAULT_VERSION)
291 target_version_map[target] = result
292 return result
293
294
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100295def GetTargetPackages(target):
296 """Returns a list of packages for a given target."""
David James66a09c42012-11-05 13:31:38 -0800297 conf = Crossdev.GetConfig(target)
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100298 # Undesired packages are denoted by empty ${pkg}_pn variable.
Han Shene23782f2016-02-18 12:20:00 -0800299 return [x for x in conf['crosspkgs'] if conf.get(x+'_pn')]
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100300
301
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100302# Portage helper functions:
303def GetPortagePackage(target, package):
304 """Returns a package name for the given target."""
David James66a09c42012-11-05 13:31:38 -0800305 conf = Crossdev.GetConfig(target)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100306 # Portage category:
Han Shene23782f2016-02-18 12:20:00 -0800307 if target == 'host' or package in Crossdev.MANUAL_PKGS:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100308 category = conf[package + '_category']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100309 else:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100310 category = conf['category']
311 # Portage package:
312 pn = conf[package + '_pn']
313 # Final package name:
Mike Frysinger422faf42014-11-12 23:16:48 -0500314 assert category
315 assert pn
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100316 return '%s/%s' % (category, pn)
317
318
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100319def IsPackageDisabled(target, package):
320 """Returns if the given package is not used for the target."""
321 return GetDesiredPackageVersions(target, package) == [PACKAGE_NONE]
322
Liam McLoughlinf54a0782012-05-17 23:36:52 +0100323
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700324def PortageTrees(root):
325 """Return the portage trees for a given root."""
326 if root == '/':
327 return portage.db['/']
328 # The portage logic requires the path always end in a slash.
329 root = root.rstrip('/') + '/'
330 return portage.create_trees(target_root=root, config_root=root)[root]
331
332
333def GetInstalledPackageVersions(atom, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100334 """Extracts the list of current versions of a target, package pair.
335
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500336 Args:
337 atom: The atom to operate on (e.g. sys-devel/gcc)
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700338 root: The root to check for installed packages.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100339
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500340 Returns:
341 The list of versions of the package currently installed.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100342 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100343 versions = []
Mike Frysinger506e75f2012-12-17 14:21:13 -0500344 # pylint: disable=E1101
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700345 for pkg in PortageTrees(root)['vartree'].dbapi.match(atom, use_cache=0):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100346 version = portage.versions.cpv_getversion(pkg)
347 versions.append(version)
348 return versions
349
350
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700351def GetStablePackageVersion(atom, installed, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100352 """Extracts the current stable version for a given package.
353
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500354 Args:
355 atom: The target/package to operate on eg. i686-pc-linux-gnu,gcc
356 installed: Whether we want installed packages or ebuilds
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700357 root: The root to use when querying packages.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100358
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500359 Returns:
360 A string containing the latest version.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100361 """
David James90239b92012-11-05 15:31:34 -0800362 pkgtype = 'vartree' if installed else 'porttree'
Mike Frysinger506e75f2012-12-17 14:21:13 -0500363 # pylint: disable=E1101
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700364 cpv = portage.best(PortageTrees(root)[pkgtype].dbapi.match(atom, use_cache=0))
David James90239b92012-11-05 15:31:34 -0800365 return portage.versions.cpv_getversion(cpv) if cpv else None
Zdenek Behan508dcce2011-12-05 15:39:32 +0100366
367
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700368def VersionListToNumeric(target, package, versions, installed, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100369 """Resolves keywords in a given version list for a particular package.
370
371 Resolving means replacing PACKAGE_STABLE with the actual number.
372
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500373 Args:
374 target: The target to operate on (e.g. i686-pc-linux-gnu)
375 package: The target/package to operate on (e.g. gcc)
376 versions: List of versions to resolve
377 installed: Query installed packages
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700378 root: The install root to use; ignored if |installed| is False.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100379
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500380 Returns:
381 List of purely numeric versions equivalent to argument
Zdenek Behan508dcce2011-12-05 15:39:32 +0100382 """
383 resolved = []
David James90239b92012-11-05 15:31:34 -0800384 atom = GetPortagePackage(target, package)
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700385 if not installed:
386 root = '/'
Zdenek Behan508dcce2011-12-05 15:39:32 +0100387 for version in versions:
388 if version == PACKAGE_STABLE:
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700389 resolved.append(GetStablePackageVersion(atom, installed, root=root))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100390 elif version != PACKAGE_NONE:
391 resolved.append(version)
392 return resolved
393
394
395def GetDesiredPackageVersions(target, package):
396 """Produces the list of desired versions for each target, package pair.
397
398 The first version in the list is implicitly treated as primary, ie.
399 the version that will be initialized by crossdev and selected.
400
401 If the version is PACKAGE_STABLE, it really means the current version which
402 is emerged by using the package atom with no particular version key.
403 Since crossdev unmasks all packages by default, this will actually
404 mean 'unstable' in most cases.
405
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500406 Args:
407 target: The target to operate on (e.g. i686-pc-linux-gnu)
408 package: The target/package to operate on (e.g. gcc)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100409
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500410 Returns:
411 A list composed of either a version string, PACKAGE_STABLE
Zdenek Behan508dcce2011-12-05 15:39:32 +0100412 """
413 packagemap = GetPackageMap(target)
414
415 versions = []
416 if package in packagemap:
417 versions.append(packagemap[package])
418
419 return versions
420
421
422def TargetIsInitialized(target):
423 """Verifies if the given list of targets has been correctly initialized.
424
425 This determines whether we have to call crossdev while emerging
426 toolchain packages or can do it using emerge. Emerge is naturally
427 preferred, because all packages can be updated in a single pass.
428
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500429 Args:
430 target: The target to operate on (e.g. i686-pc-linux-gnu)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100431
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500432 Returns:
433 True if |target| is completely initialized, else False
Zdenek Behan508dcce2011-12-05 15:39:32 +0100434 """
435 # Check if packages for the given target all have a proper version.
436 try:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100437 for package in GetTargetPackages(target):
David James66a09c42012-11-05 13:31:38 -0800438 atom = GetPortagePackage(target, package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100439 # Do we even want this package && is it initialized?
David James90239b92012-11-05 15:31:34 -0800440 if not IsPackageDisabled(target, package) and not (
441 GetStablePackageVersion(atom, True) and
442 GetStablePackageVersion(atom, False)):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100443 return False
444 return True
445 except cros_build_lib.RunCommandError:
446 # Fails - The target has likely never been initialized before.
447 return False
448
449
450def RemovePackageMask(target):
451 """Removes a package.mask file for the given platform.
452
453 The pre-existing package.mask files can mess with the keywords.
454
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500455 Args:
456 target: The target to operate on (e.g. i686-pc-linux-gnu)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100457 """
458 maskfile = os.path.join('/etc/portage/package.mask', 'cross-' + target)
Brian Harringaf019fb2012-05-10 15:06:13 -0700459 osutils.SafeUnlink(maskfile)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100460
461
Zdenek Behan508dcce2011-12-05 15:39:32 +0100462# Main functions performing the actual update steps.
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700463def RebuildLibtool(root='/'):
Mike Frysingerc880a962013-11-08 13:59:06 -0500464 """Rebuild libtool as needed
465
466 Libtool hardcodes full paths to internal gcc files, so whenever we upgrade
467 gcc, libtool will break. We can't use binary packages either as those will
468 most likely be compiled against the previous version of gcc.
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700469
470 Args:
471 root: The install root where we want libtool rebuilt.
Mike Frysingerc880a962013-11-08 13:59:06 -0500472 """
473 needs_update = False
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700474 with open(os.path.join(root, 'usr/bin/libtool')) as f:
Mike Frysingerc880a962013-11-08 13:59:06 -0500475 for line in f:
476 # Look for a line like:
477 # sys_lib_search_path_spec="..."
478 # It'll be a list of paths and gcc will be one of them.
479 if line.startswith('sys_lib_search_path_spec='):
480 line = line.rstrip()
481 for path in line.split('=', 1)[1].strip('"').split():
Mike Frysinger3bba5032016-09-20 14:15:04 -0400482 root_path = os.path.join(root, path.lstrip(os.path.sep))
483 logging.debug('Libtool: checking %s', root_path)
484 if not os.path.exists(root_path):
485 logging.info('Rebuilding libtool after gcc upgrade')
486 logging.info(' %s', line)
487 logging.info(' missing path: %s', path)
Mike Frysingerc880a962013-11-08 13:59:06 -0500488 needs_update = True
489 break
490
491 if needs_update:
492 break
493
494 if needs_update:
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700495 cmd = [EMERGE_CMD, '--oneshot']
496 if root != '/':
497 cmd.extend(['--sysroot=%s' % root, '--root=%s' % root])
498 cmd.append('sys-devel/libtool')
Mike Frysingerc880a962013-11-08 13:59:06 -0500499 cros_build_lib.RunCommand(cmd)
Mike Frysinger3bba5032016-09-20 14:15:04 -0400500 else:
501 logging.debug('Libtool is up-to-date; no need to rebuild')
Mike Frysingerc880a962013-11-08 13:59:06 -0500502
503
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700504def UpdateTargets(targets, usepkg, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100505 """Determines which packages need update/unmerge and defers to portage.
506
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500507 Args:
508 targets: The list of targets to update
509 usepkg: Copies the commandline option
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700510 root: The install root in which we want packages updated.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100511 """
David James90239b92012-11-05 15:31:34 -0800512 # Remove keyword files created by old versions of cros_setup_toolchains.
513 osutils.SafeUnlink('/etc/portage/package.keywords/cross-host')
Zdenek Behan508dcce2011-12-05 15:39:32 +0100514
515 # For each target, we do two things. Figure out the list of updates,
516 # and figure out the appropriate keywords/masks. Crossdev will initialize
517 # these, but they need to be regenerated on every update.
Mike Frysinger3bba5032016-09-20 14:15:04 -0400518 logging.info('Determining required toolchain updates...')
David James90239b92012-11-05 15:31:34 -0800519 mergemap = {}
Zdenek Behan508dcce2011-12-05 15:39:32 +0100520 for target in targets:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400521 logging.debug('Updating target %s', target)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100522 # Record the highest needed version for each target, for masking purposes.
523 RemovePackageMask(target)
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100524 for package in GetTargetPackages(target):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100525 # Portage name for the package
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100526 if IsPackageDisabled(target, package):
Mike Frysinger3bba5032016-09-20 14:15:04 -0400527 logging.debug(' Skipping disabled package %s', package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100528 continue
Mike Frysinger3bba5032016-09-20 14:15:04 -0400529 logging.debug(' Updating package %s', package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100530 pkg = GetPortagePackage(target, package)
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700531 current = GetInstalledPackageVersions(pkg, root=root)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100532 desired = GetDesiredPackageVersions(target, package)
Zdenek Behan699ddd32012-04-13 07:14:08 +0200533 desired_num = VersionListToNumeric(target, package, desired, False)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100534 mergemap[pkg] = set(desired_num).difference(current)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100535
Zdenek Behan508dcce2011-12-05 15:39:32 +0100536 packages = []
537 for pkg in mergemap:
538 for ver in mergemap[pkg]:
Zdenek Behan677b6d82012-04-11 05:31:47 +0200539 if ver != PACKAGE_NONE:
David James90239b92012-11-05 15:31:34 -0800540 packages.append(pkg)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100541
542 if not packages:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400543 logging.info('Nothing to update!')
David Jamesf8c672f2012-11-06 13:38:11 -0800544 return False
Zdenek Behan508dcce2011-12-05 15:39:32 +0100545
Mike Frysinger3bba5032016-09-20 14:15:04 -0400546 logging.info('Updating packages:')
547 logging.info('%s', packages)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100548
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100549 cmd = [EMERGE_CMD, '--oneshot', '--update']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100550 if usepkg:
551 cmd.extend(['--getbinpkg', '--usepkgonly'])
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700552 if root != '/':
553 cmd.extend(['--sysroot=%s' % root, '--root=%s' % root])
Zdenek Behan508dcce2011-12-05 15:39:32 +0100554
555 cmd.extend(packages)
556 cros_build_lib.RunCommand(cmd)
David Jamesf8c672f2012-11-06 13:38:11 -0800557 return True
Zdenek Behan508dcce2011-12-05 15:39:32 +0100558
559
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700560def CleanTargets(targets, root='/'):
561 """Unmerges old packages that are assumed unnecessary.
562
563 Args:
564 targets: The list of targets to clean up.
565 root: The install root in which we want packages cleaned up.
566 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100567 unmergemap = {}
568 for target in targets:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400569 logging.debug('Cleaning target %s', target)
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100570 for package in GetTargetPackages(target):
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100571 if IsPackageDisabled(target, package):
Mike Frysinger3bba5032016-09-20 14:15:04 -0400572 logging.debug(' Skipping disabled package %s', package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100573 continue
Mike Frysinger3bba5032016-09-20 14:15:04 -0400574 logging.debug(' Cleaning package %s', package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100575 pkg = GetPortagePackage(target, package)
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700576 current = GetInstalledPackageVersions(pkg, root=root)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100577 desired = GetDesiredPackageVersions(target, package)
Gilad Arnold2fcb0aa2015-05-21 14:51:41 -0700578 # NOTE: This refers to installed packages (vartree) rather than the
579 # Portage version (porttree and/or bintree) when determining the current
580 # version. While this isn't the most accurate thing to do, it is probably
581 # a good simple compromise, which should have the desired result of
582 # uninstalling everything but the latest installed version. In
583 # particular, using the bintree (--usebinpkg) requires a non-trivial
584 # binhost sync and is probably more complex than useful.
Zdenek Behan699ddd32012-04-13 07:14:08 +0200585 desired_num = VersionListToNumeric(target, package, desired, True)
586 if not set(desired_num).issubset(current):
Mike Frysinger3bba5032016-09-20 14:15:04 -0400587 logging.warning('Error detecting stable version for %s, '
588 'skipping clean!', pkg)
Zdenek Behan699ddd32012-04-13 07:14:08 +0200589 return
Zdenek Behan508dcce2011-12-05 15:39:32 +0100590 unmergemap[pkg] = set(current).difference(desired_num)
591
592 # Cleaning doesn't care about consistency and rebuilding package.* files.
593 packages = []
594 for pkg, vers in unmergemap.iteritems():
595 packages.extend('=%s-%s' % (pkg, ver) for ver in vers if ver != '9999')
596
597 if packages:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400598 logging.info('Cleaning packages:')
599 logging.info('%s', packages)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100600 cmd = [EMERGE_CMD, '--unmerge']
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700601 if root != '/':
602 cmd.extend(['--sysroot=%s' % root, '--root=%s' % root])
Zdenek Behan508dcce2011-12-05 15:39:32 +0100603 cmd.extend(packages)
604 cros_build_lib.RunCommand(cmd)
605 else:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400606 logging.info('Nothing to clean!')
Zdenek Behan508dcce2011-12-05 15:39:32 +0100607
608
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700609def SelectActiveToolchains(targets, suffixes, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100610 """Runs gcc-config and binutils-config to select the desired.
611
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500612 Args:
613 targets: The targets to select
614 suffixes: Optional target-specific hacks
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700615 root: The root where we want to select toolchain versions.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100616 """
617 for package in ['gcc', 'binutils']:
618 for target in targets:
619 # Pick the first version in the numbered list as the selected one.
620 desired = GetDesiredPackageVersions(target, package)
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700621 desired_num = VersionListToNumeric(target, package, desired, True,
622 root=root)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100623 desired = desired_num[0]
624 # *-config does not play revisions, strip them, keep just PV.
625 desired = portage.versions.pkgsplit('%s-%s' % (package, desired))[1]
626
627 if target == 'host':
628 # *-config is the only tool treating host identically (by tuple).
David James27ac4ae2012-12-03 23:16:15 -0800629 target = toolchain.GetHostTuple()
Zdenek Behan508dcce2011-12-05 15:39:32 +0100630
631 # And finally, attach target to it.
632 desired = '%s-%s' % (target, desired)
633
634 # Target specific hacks
635 if package in suffixes:
636 if target in suffixes[package]:
637 desired += suffixes[package][target]
638
David James7ec5efc2012-11-06 09:39:49 -0800639 extra_env = {'CHOST': target}
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700640 if root != '/':
641 extra_env['ROOT'] = root
David James7ec5efc2012-11-06 09:39:49 -0800642 cmd = ['%s-config' % package, '-c', target]
Mike Frysingerd6e2df02014-11-26 02:55:04 -0500643 result = cros_build_lib.RunCommand(
644 cmd, print_cmd=False, redirect_stdout=True, extra_env=extra_env)
645 current = result.output.splitlines()[0]
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700646
647 # Do not reconfig when the current is live or nothing needs to be done.
648 extra_env = {'ROOT': root} if root != '/' else None
Zdenek Behan508dcce2011-12-05 15:39:32 +0100649 if current != desired and current != '9999':
Mike Frysingerd6e2df02014-11-26 02:55:04 -0500650 cmd = [package + '-config', desired]
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700651 cros_build_lib.RunCommand(cmd, print_cmd=False, extra_env=extra_env)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100652
653
Mike Frysinger35247af2012-11-16 18:58:06 -0500654def ExpandTargets(targets_wanted):
655 """Expand any possible toolchain aliases into full targets
656
657 This will expand 'all' and 'sdk' into the respective toolchain tuples.
658
659 Args:
660 targets_wanted: The targets specified by the user.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500661
Mike Frysinger35247af2012-11-16 18:58:06 -0500662 Returns:
Gilad Arnold8195b532015-04-07 10:56:30 +0300663 Dictionary of concrete targets and their toolchain tuples.
Mike Frysinger35247af2012-11-16 18:58:06 -0500664 """
Mike Frysinger35247af2012-11-16 18:58:06 -0500665 targets_wanted = set(targets_wanted)
Don Garrettc0c74002015-10-09 12:58:19 -0700666 if targets_wanted == set(['boards']):
667 # Only pull targets from the included boards.
Gilad Arnold8195b532015-04-07 10:56:30 +0300668 return {}
669
670 all_targets = toolchain.GetAllTargets()
Mike Frysinger35247af2012-11-16 18:58:06 -0500671 if targets_wanted == set(['all']):
Gilad Arnold8195b532015-04-07 10:56:30 +0300672 return all_targets
673 if targets_wanted == set(['sdk']):
Mike Frysinger35247af2012-11-16 18:58:06 -0500674 # Filter out all the non-sdk toolchains as we don't want to mess
675 # with those in all of our builds.
Gilad Arnold8195b532015-04-07 10:56:30 +0300676 return toolchain.FilterToolchains(all_targets, 'sdk', True)
677
678 # Verify user input.
679 nonexistent = targets_wanted.difference(all_targets)
680 if nonexistent:
681 raise ValueError('Invalid targets: %s', ','.join(nonexistent))
682 return {t: all_targets[t] for t in targets_wanted}
Mike Frysinger35247af2012-11-16 18:58:06 -0500683
684
David Jamesf8c672f2012-11-06 13:38:11 -0800685def UpdateToolchains(usepkg, deleteold, hostonly, reconfig,
Don Garrettc0c74002015-10-09 12:58:19 -0700686 targets_wanted, boards_wanted, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100687 """Performs all steps to create a synchronized toolchain enviroment.
688
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500689 Args:
690 usepkg: Use prebuilt packages
691 deleteold: Unmerge deprecated packages
692 hostonly: Only setup the host toolchain
693 reconfig: Reload crossdev config and reselect toolchains
694 targets_wanted: All the targets to update
695 boards_wanted: Load targets from these boards
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700696 root: The root in which to install the toolchains.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100697 """
David Jamesf8c672f2012-11-06 13:38:11 -0800698 targets, crossdev_targets, reconfig_targets = {}, {}, {}
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100699 if not hostonly:
700 # For hostonly, we can skip most of the below logic, much of which won't
701 # work on bare systems where this is useful.
Mike Frysinger35247af2012-11-16 18:58:06 -0500702 targets = ExpandTargets(targets_wanted)
Mike Frysinger7ccee992012-06-01 21:27:59 -0400703
Don Garrettc0c74002015-10-09 12:58:19 -0700704 # Now re-add any targets that might be from this board. This is to
Gilad Arnold8195b532015-04-07 10:56:30 +0300705 # allow unofficial boards to declare their own toolchains.
Mike Frysinger7ccee992012-06-01 21:27:59 -0400706 for board in boards_wanted:
David James27ac4ae2012-12-03 23:16:15 -0800707 targets.update(toolchain.GetToolchainsForBoard(board))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100708
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100709 # First check and initialize all cross targets that need to be.
Mike Frysinger7ccee992012-06-01 21:27:59 -0400710 for target in targets:
711 if TargetIsInitialized(target):
712 reconfig_targets[target] = targets[target]
713 else:
714 crossdev_targets[target] = targets[target]
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100715 if crossdev_targets:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400716 logging.info('The following targets need to be re-initialized:')
717 logging.info('%s', crossdev_targets)
David James66a09c42012-11-05 13:31:38 -0800718 Crossdev.UpdateTargets(crossdev_targets, usepkg)
Zdenek Behan8be29ba2012-05-29 23:10:34 +0200719 # Those that were not initialized may need a config update.
David James66a09c42012-11-05 13:31:38 -0800720 Crossdev.UpdateTargets(reconfig_targets, usepkg, config_only=True)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100721
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100722 # We want host updated.
Mike Frysinger7ccee992012-06-01 21:27:59 -0400723 targets['host'] = {}
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100724
725 # Now update all packages.
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700726 if UpdateTargets(targets, usepkg, root=root) or crossdev_targets or reconfig:
727 SelectActiveToolchains(targets, CONFIG_TARGET_SUFFIXES, root=root)
David James7ec5efc2012-11-06 09:39:49 -0800728
729 if deleteold:
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700730 CleanTargets(targets, root=root)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100731
Mike Frysingerc880a962013-11-08 13:59:06 -0500732 # Now that we've cleared out old versions, see if we need to rebuild
733 # anything. Can't do this earlier as it might not be broken.
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700734 RebuildLibtool(root=root)
Mike Frysingerc880a962013-11-08 13:59:06 -0500735
Zdenek Behan508dcce2011-12-05 15:39:32 +0100736
Bertrand SIMONNETcae9d5f2015-03-09 15:58:01 -0700737def ShowConfig(name):
738 """Show the toolchain tuples used by |name|
Mike Frysinger35247af2012-11-16 18:58:06 -0500739
740 Args:
Don Garrettc0c74002015-10-09 12:58:19 -0700741 name: The board name to query.
Mike Frysinger35247af2012-11-16 18:58:06 -0500742 """
Don Garrettc0c74002015-10-09 12:58:19 -0700743 toolchains = toolchain.GetToolchainsForBoard(name)
Mike Frysinger35247af2012-11-16 18:58:06 -0500744 # Make sure we display the default toolchain first.
Mike Frysinger3bba5032016-09-20 14:15:04 -0400745 # Note: Do not use logging here as this is meant to be used by other tools.
Mike Frysinger383367e2014-09-16 15:06:17 -0400746 print(','.join(
David James27ac4ae2012-12-03 23:16:15 -0800747 toolchain.FilterToolchains(toolchains, 'default', True).keys() +
Mike Frysinger383367e2014-09-16 15:06:17 -0400748 toolchain.FilterToolchains(toolchains, 'default', False).keys()))
Mike Frysinger35247af2012-11-16 18:58:06 -0500749
750
Mike Frysinger35247af2012-11-16 18:58:06 -0500751def GeneratePathWrapper(root, wrappath, path):
752 """Generate a shell script to execute another shell script
753
754 Since we can't symlink a wrapped ELF (see GenerateLdsoWrapper) because the
755 argv[0] won't be pointing to the correct path, generate a shell script that
756 just executes another program with its full path.
757
758 Args:
759 root: The root tree to generate scripts inside of
760 wrappath: The full path (inside |root|) to create the wrapper
761 path: The target program which this wrapper will execute
762 """
763 replacements = {
764 'path': path,
765 'relroot': os.path.relpath('/', os.path.dirname(wrappath)),
766 }
767 wrapper = """#!/bin/sh
768base=$(realpath "$0")
769basedir=${base%%/*}
770exec "${basedir}/%(relroot)s%(path)s" "$@"
771""" % replacements
772 root_wrapper = root + wrappath
773 if os.path.islink(root_wrapper):
774 os.unlink(root_wrapper)
775 else:
776 osutils.SafeMakedirs(os.path.dirname(root_wrapper))
777 osutils.WriteFile(root_wrapper, wrapper)
Mike Frysinger60ec1012013-10-21 00:11:10 -0400778 os.chmod(root_wrapper, 0o755)
Mike Frysinger35247af2012-11-16 18:58:06 -0500779
780
Rahul Chaudhrya8127bb2016-07-22 15:53:17 -0700781def FixClangXXWrapper(root, path):
782 """Fix wrapper shell scripts and symlinks for invoking clang++
783
784 In a typical installation, clang++ symlinks to clang, which symlinks to the
785 elf executable. The executable distinguishes between clang and clang++ based
786 on argv[0].
787
788 When invoked through the LdsoWrapper, argv[0] always contains the path to the
789 executable elf file, making clang/clang++ invocations indistinguishable.
790
791 This function detects if the elf executable being wrapped is clang-X.Y, and
792 fixes wrappers/symlinks as necessary so that clang++ will work correctly.
793
794 The calling sequence now becomes:
795 -) clang++ invocation turns into clang++-3.9 (which is a copy of clang-3.9,
796 the Ldsowrapper).
797 -) clang++-3.9 uses the Ldso to invoke clang++-3.9.elf, which is a symlink
798 to the original clang-3.9 elf.
799 -) The difference this time is that inside the elf file execution, $0 is
800 set as .../usr/bin/clang++-3.9.elf, which contains 'clang++' in the name.
801
802 Args:
803 root: The root tree to generate scripts / symlinks inside of
804 path: The target elf for which LdsoWrapper was created
805 """
806 if re.match(r'/usr/bin/clang-\d+\.\d+$', path):
807 logging.info('fixing clang++ invocation for %s', path)
808 clangdir = os.path.dirname(root + path)
809 clang = os.path.basename(path)
810 clangxx = clang.replace('clang', 'clang++')
811
812 # Create a symlink clang++-X.Y.elf to point to clang-X.Y.elf
813 os.symlink(clang + '.elf', os.path.join(clangdir, clangxx + '.elf'))
814
815 # Create a hardlink clang++-X.Y pointing to clang-X.Y
816 os.link(os.path.join(clangdir, clang), os.path.join(clangdir, clangxx))
817
818 # Adjust the clang++ symlink to point to clang++-X.Y
819 os.unlink(os.path.join(clangdir, 'clang++'))
820 os.symlink(clangxx, os.path.join(clangdir, 'clang++'))
821
822
Mike Frysinger35247af2012-11-16 18:58:06 -0500823def FileIsCrosSdkElf(elf):
824 """Determine if |elf| is an ELF that we execute in the cros_sdk
825
826 We don't need this to be perfect, just quick. It makes sure the ELF
827 is a 64bit LSB x86_64 ELF. That is the native type of cros_sdk.
828
829 Args:
830 elf: The file to check
Mike Frysinger1a736a82013-12-12 01:50:59 -0500831
Mike Frysinger35247af2012-11-16 18:58:06 -0500832 Returns:
833 True if we think |elf| is a native ELF
834 """
835 with open(elf) as f:
836 data = f.read(20)
837 # Check the magic number, EI_CLASS, EI_DATA, and e_machine.
838 return (data[0:4] == '\x7fELF' and
839 data[4] == '\x02' and
840 data[5] == '\x01' and
841 data[18] == '\x3e')
842
843
844def IsPathPackagable(ptype, path):
845 """Should the specified file be included in a toolchain package?
846
847 We only need to handle files as we'll create dirs as we need them.
848
849 Further, trim files that won't be useful:
850 - non-english translations (.mo) since it'd require env vars
851 - debug files since these are for the host compiler itself
852 - info/man pages as they're big, and docs are online, and the
853 native docs should work fine for the most part (`man gcc`)
854
855 Args:
856 ptype: A string describing the path type (i.e. 'file' or 'dir' or 'sym')
857 path: The full path to inspect
Mike Frysinger1a736a82013-12-12 01:50:59 -0500858
Mike Frysinger35247af2012-11-16 18:58:06 -0500859 Returns:
860 True if we want to include this path in the package
861 """
862 return not (ptype in ('dir',) or
863 path.startswith('/usr/lib/debug/') or
864 os.path.splitext(path)[1] == '.mo' or
865 ('/man/' in path or '/info/' in path))
866
867
868def ReadlinkRoot(path, root):
869 """Like os.readlink(), but relative to a |root|
870
871 Args:
872 path: The symlink to read
873 root: The path to use for resolving absolute symlinks
Mike Frysinger1a736a82013-12-12 01:50:59 -0500874
Mike Frysinger35247af2012-11-16 18:58:06 -0500875 Returns:
876 A fully resolved symlink path
877 """
878 while os.path.islink(root + path):
879 path = os.path.join(os.path.dirname(path), os.readlink(root + path))
880 return path
881
882
883def _GetFilesForTarget(target, root='/'):
884 """Locate all the files to package for |target|
885
886 This does not cover ELF dependencies.
887
888 Args:
889 target: The toolchain target name
890 root: The root path to pull all packages from
Mike Frysinger1a736a82013-12-12 01:50:59 -0500891
Mike Frysinger35247af2012-11-16 18:58:06 -0500892 Returns:
893 A tuple of a set of all packable paths, and a set of all paths which
894 are also native ELFs
895 """
896 paths = set()
897 elfs = set()
898
899 # Find all the files owned by the packages for this target.
900 for pkg in GetTargetPackages(target):
Mike Frysinger35247af2012-11-16 18:58:06 -0500901
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700902 # Skip Go compiler from redistributable packages.
903 # The "go" executable has GOROOT=/usr/lib/go/${CTARGET} hardcoded
904 # into it. Due to this, the toolchain cannot be unpacked anywhere
905 # else and be readily useful. To enable packaging Go, we need to:
906 # -) Tweak the wrappers/environment to override GOROOT
907 # automatically based on the unpack location.
908 # -) Make sure the ELF dependency checking and wrapping logic
909 # below skips the Go toolchain executables and libraries.
910 # -) Make sure the packaging process maintains the relative
911 # timestamps of precompiled standard library packages.
912 # (see dev-lang/go ebuild for details).
913 if pkg == 'ex_go':
914 continue
915
Mike Frysinger35247af2012-11-16 18:58:06 -0500916 atom = GetPortagePackage(target, pkg)
917 cat, pn = atom.split('/')
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700918 ver = GetInstalledPackageVersions(atom, root=root)[0]
Ralph Nathan03047282015-03-23 11:09:32 -0700919 logging.info('packaging %s-%s', atom, ver)
Mike Frysinger35247af2012-11-16 18:58:06 -0500920
921 # pylint: disable=E1101
922 dblink = portage.dblink(cat, pn + '-' + ver, myroot=root,
923 settings=portage.settings)
924 contents = dblink.getcontents()
925 for obj in contents:
926 ptype = contents[obj][0]
927 if not IsPathPackagable(ptype, obj):
928 continue
929
930 if ptype == 'obj':
931 # For native ELFs, we need to pull in their dependencies too.
932 if FileIsCrosSdkElf(obj):
933 elfs.add(obj)
934 paths.add(obj)
935
936 return paths, elfs
937
938
939def _BuildInitialPackageRoot(output_dir, paths, elfs, ldpaths,
Mike Frysingerd6e2df02014-11-26 02:55:04 -0500940 path_rewrite_func=lambda x: x, root='/'):
Mike Frysinger35247af2012-11-16 18:58:06 -0500941 """Link in all packable files and their runtime dependencies
942
943 This also wraps up executable ELFs with helper scripts.
944
945 Args:
946 output_dir: The output directory to store files
947 paths: All the files to include
948 elfs: All the files which are ELFs (a subset of |paths|)
949 ldpaths: A dict of static ldpath information
950 path_rewrite_func: User callback to rewrite paths in output_dir
951 root: The root path to pull all packages/files from
952 """
953 # Link in all the files.
954 sym_paths = []
955 for path in paths:
956 new_path = path_rewrite_func(path)
957 dst = output_dir + new_path
958 osutils.SafeMakedirs(os.path.dirname(dst))
959
960 # Is this a symlink which we have to rewrite or wrap?
961 # Delay wrap check until after we have created all paths.
962 src = root + path
963 if os.path.islink(src):
964 tgt = os.readlink(src)
965 if os.path.sep in tgt:
966 sym_paths.append((new_path, lddtree.normpath(ReadlinkRoot(src, root))))
967
968 # Rewrite absolute links to relative and then generate the symlink
969 # ourselves. All other symlinks can be hardlinked below.
970 if tgt[0] == '/':
971 tgt = os.path.relpath(tgt, os.path.dirname(new_path))
972 os.symlink(tgt, dst)
973 continue
974
975 os.link(src, dst)
976
977 # Now see if any of the symlinks need to be wrapped.
978 for sym, tgt in sym_paths:
979 if tgt in elfs:
980 GeneratePathWrapper(output_dir, sym, tgt)
981
982 # Locate all the dependencies for all the ELFs. Stick them all in the
983 # top level "lib" dir to make the wrapper simpler. This exact path does
984 # not matter since we execute ldso directly, and we tell the ldso the
985 # exact path to search for its libraries.
986 libdir = os.path.join(output_dir, 'lib')
987 osutils.SafeMakedirs(libdir)
988 donelibs = set()
989 for elf in elfs:
Mike Frysingerea7688e2014-07-31 22:40:33 -0400990 e = lddtree.ParseELF(elf, root=root, ldpaths=ldpaths)
Mike Frysinger35247af2012-11-16 18:58:06 -0500991 interp = e['interp']
992 if interp:
993 # Generate a wrapper if it is executable.
Mike Frysingerc2ec0902013-03-26 01:28:45 -0400994 interp = os.path.join('/lib', os.path.basename(interp))
995 lddtree.GenerateLdsoWrapper(output_dir, path_rewrite_func(elf), interp,
996 libpaths=e['rpath'] + e['runpath'])
Rahul Chaudhrya8127bb2016-07-22 15:53:17 -0700997 FixClangXXWrapper(output_dir, path_rewrite_func(elf))
Mike Frysinger35247af2012-11-16 18:58:06 -0500998
999 for lib, lib_data in e['libs'].iteritems():
1000 if lib in donelibs:
1001 continue
1002
1003 src = path = lib_data['path']
1004 if path is None:
Ralph Nathan446aee92015-03-23 14:44:56 -07001005 logging.warning('%s: could not locate %s', elf, lib)
Mike Frysinger35247af2012-11-16 18:58:06 -05001006 continue
1007 donelibs.add(lib)
1008
1009 # Needed libs are the SONAME, but that is usually a symlink, not a
1010 # real file. So link in the target rather than the symlink itself.
1011 # We have to walk all the possible symlinks (SONAME could point to a
1012 # symlink which points to a symlink), and we have to handle absolute
1013 # ourselves (since we have a "root" argument).
1014 dst = os.path.join(libdir, os.path.basename(path))
1015 src = ReadlinkRoot(src, root)
1016
1017 os.link(root + src, dst)
1018
1019
1020def _EnvdGetVar(envd, var):
1021 """Given a Gentoo env.d file, extract a var from it
1022
1023 Args:
1024 envd: The env.d file to load (may be a glob path)
1025 var: The var to extract
Mike Frysinger1a736a82013-12-12 01:50:59 -05001026
Mike Frysinger35247af2012-11-16 18:58:06 -05001027 Returns:
1028 The value of |var|
1029 """
1030 envds = glob.glob(envd)
1031 assert len(envds) == 1, '%s: should have exactly 1 env.d file' % envd
1032 envd = envds[0]
1033 return cros_build_lib.LoadKeyValueFile(envd)[var]
1034
1035
1036def _ProcessBinutilsConfig(target, output_dir):
1037 """Do what binutils-config would have done"""
1038 binpath = os.path.join('/bin', target + '-')
Mike Frysingerd4d40fd2014-11-06 17:30:57 -05001039
1040 # Locate the bin dir holding the gold linker.
1041 binutils_bin_path = os.path.join(output_dir, 'usr', toolchain.GetHostTuple(),
1042 target, 'binutils-bin')
1043 globpath = os.path.join(binutils_bin_path, '*-gold')
Mike Frysinger35247af2012-11-16 18:58:06 -05001044 srcpath = glob.glob(globpath)
Mike Frysingerd4d40fd2014-11-06 17:30:57 -05001045 if not srcpath:
1046 # Maybe this target doesn't support gold.
1047 globpath = os.path.join(binutils_bin_path, '*')
1048 srcpath = glob.glob(globpath)
1049 assert len(srcpath) == 1, ('%s: matched more than one path (but not *-gold)'
1050 % globpath)
1051 srcpath = srcpath[0]
1052 ld_path = os.path.join(srcpath, 'ld')
1053 assert os.path.exists(ld_path), '%s: linker is missing!' % ld_path
1054 ld_path = os.path.join(srcpath, 'ld.bfd')
1055 assert os.path.exists(ld_path), '%s: linker is missing!' % ld_path
1056 ld_path = os.path.join(srcpath, 'ld.gold')
1057 assert not os.path.exists(ld_path), ('%s: exists, but gold dir does not!'
1058 % ld_path)
1059
1060 # Nope, no gold support to be found.
1061 gold_supported = False
Ralph Nathan446aee92015-03-23 14:44:56 -07001062 logging.warning('%s: binutils lacks support for the gold linker', target)
Mike Frysingerd4d40fd2014-11-06 17:30:57 -05001063 else:
1064 assert len(srcpath) == 1, '%s: did not match exactly 1 path' % globpath
Mike Frysinger78b7a812014-11-26 19:45:23 -05001065 srcpath = srcpath[0]
Mike Frysingerd4d40fd2014-11-06 17:30:57 -05001066
Rahul Chaudhry4891b4d2017-03-08 10:31:27 -08001067 # Package the binutils-bin directory without the '-gold' suffix
1068 # if gold is not enabled as the default linker for this target.
1069 gold_supported = CONFIG_TARGET_SUFFIXES['binutils'].get(target) == '-gold'
1070 if not gold_supported:
1071 srcpath = srcpath[:-len('-gold')]
1072 ld_path = os.path.join(srcpath, 'ld')
1073 assert os.path.exists(ld_path), '%s: linker is missing!' % ld_path
1074
Mike Frysinger78b7a812014-11-26 19:45:23 -05001075 srcpath = srcpath[len(output_dir):]
Mike Frysinger35247af2012-11-16 18:58:06 -05001076 gccpath = os.path.join('/usr', 'libexec', 'gcc')
1077 for prog in os.listdir(output_dir + srcpath):
1078 # Skip binaries already wrapped.
1079 if not prog.endswith('.real'):
1080 GeneratePathWrapper(output_dir, binpath + prog,
1081 os.path.join(srcpath, prog))
1082 GeneratePathWrapper(output_dir, os.path.join(gccpath, prog),
1083 os.path.join(srcpath, prog))
1084
David James27ac4ae2012-12-03 23:16:15 -08001085 libpath = os.path.join('/usr', toolchain.GetHostTuple(), target, 'lib')
Mike Frysingerd4d40fd2014-11-06 17:30:57 -05001086 envd = os.path.join(output_dir, 'etc', 'env.d', 'binutils', '*')
1087 if gold_supported:
1088 envd += '-gold'
Rahul Chaudhry4891b4d2017-03-08 10:31:27 -08001089 else:
1090 # If gold is not enabled as the default linker and 2 env.d
1091 # files exist, pick the one without the '-gold' suffix.
1092 envds = sorted(glob.glob(envd))
1093 if len(envds) == 2 and envds[1] == envds[0] + '-gold':
1094 envd = envds[0]
Mike Frysinger35247af2012-11-16 18:58:06 -05001095 srcpath = _EnvdGetVar(envd, 'LIBPATH')
1096 os.symlink(os.path.relpath(srcpath, os.path.dirname(libpath)),
1097 output_dir + libpath)
1098
1099
1100def _ProcessGccConfig(target, output_dir):
1101 """Do what gcc-config would have done"""
1102 binpath = '/bin'
1103 envd = os.path.join(output_dir, 'etc', 'env.d', 'gcc', '*')
1104 srcpath = _EnvdGetVar(envd, 'GCC_PATH')
1105 for prog in os.listdir(output_dir + srcpath):
1106 # Skip binaries already wrapped.
1107 if (not prog.endswith('.real') and
1108 not prog.endswith('.elf') and
1109 prog.startswith(target)):
1110 GeneratePathWrapper(output_dir, os.path.join(binpath, prog),
1111 os.path.join(srcpath, prog))
1112 return srcpath
1113
1114
Frank Henigman179ec7c2015-02-06 03:01:09 -05001115def _ProcessSysrootWrappers(_target, output_dir, srcpath):
1116 """Remove chroot-specific things from our sysroot wrappers"""
Mike Frysinger35247af2012-11-16 18:58:06 -05001117 # Disable ccache since we know it won't work outside of chroot.
Frank Henigman179ec7c2015-02-06 03:01:09 -05001118 for sysroot_wrapper in glob.glob(os.path.join(
1119 output_dir + srcpath, 'sysroot_wrapper*')):
1120 contents = osutils.ReadFile(sysroot_wrapper).splitlines()
1121 for num in xrange(len(contents)):
1122 if '@CCACHE_DEFAULT@' in contents[num]:
Caroline Ticece9e9232017-06-02 09:38:42 -07001123 assert 'True' in contents[num]
1124 contents[num] = contents[num].replace('True', 'False')
Frank Henigman179ec7c2015-02-06 03:01:09 -05001125 break
1126 # Can't update the wrapper in place since it's a hardlink to a file in /.
1127 os.unlink(sysroot_wrapper)
1128 osutils.WriteFile(sysroot_wrapper, '\n'.join(contents))
1129 os.chmod(sysroot_wrapper, 0o755)
Mike Frysinger35247af2012-11-16 18:58:06 -05001130
1131
1132def _ProcessDistroCleanups(target, output_dir):
1133 """Clean up the tree and remove all distro-specific requirements
1134
1135 Args:
1136 target: The toolchain target name
1137 output_dir: The output directory to clean up
1138 """
1139 _ProcessBinutilsConfig(target, output_dir)
1140 gcc_path = _ProcessGccConfig(target, output_dir)
Frank Henigman179ec7c2015-02-06 03:01:09 -05001141 _ProcessSysrootWrappers(target, output_dir, gcc_path)
Mike Frysinger35247af2012-11-16 18:58:06 -05001142
1143 osutils.RmDir(os.path.join(output_dir, 'etc'))
1144
1145
1146def CreatePackagableRoot(target, output_dir, ldpaths, root='/'):
1147 """Setup a tree from the packages for the specified target
1148
1149 This populates a path with all the files from toolchain packages so that
1150 a tarball can easily be generated from the result.
1151
1152 Args:
1153 target: The target to create a packagable root from
1154 output_dir: The output directory to place all the files
1155 ldpaths: A dict of static ldpath information
1156 root: The root path to pull all packages/files from
1157 """
1158 # Find all the files owned by the packages for this target.
1159 paths, elfs = _GetFilesForTarget(target, root=root)
1160
1161 # Link in all the package's files, any ELF dependencies, and wrap any
1162 # executable ELFs with helper scripts.
1163 def MoveUsrBinToBin(path):
Han Shen699ea192016-03-02 10:42:47 -08001164 """Move /usr/bin to /bin so people can just use that toplevel dir
1165
1166 Note we do not apply this to clang - there is correlation between clang's
1167 search path for libraries / inclusion and its installation path.
1168 """
1169 if path.startswith('/usr/bin/') and path.find('clang') == -1:
1170 return path[4:]
1171 return path
Mike Frysinger35247af2012-11-16 18:58:06 -05001172 _BuildInitialPackageRoot(output_dir, paths, elfs, ldpaths,
1173 path_rewrite_func=MoveUsrBinToBin, root=root)
1174
1175 # The packages, when part of the normal distro, have helper scripts
1176 # that setup paths and such. Since we are making this standalone, we
1177 # need to preprocess all that ourselves.
1178 _ProcessDistroCleanups(target, output_dir)
1179
1180
1181def CreatePackages(targets_wanted, output_dir, root='/'):
1182 """Create redistributable cross-compiler packages for the specified targets
1183
1184 This creates toolchain packages that should be usable in conjunction with
1185 a downloaded sysroot (created elsewhere).
1186
1187 Tarballs (one per target) will be created in $PWD.
1188
1189 Args:
Don Garrett25f309a2014-03-19 14:02:12 -07001190 targets_wanted: The targets to package up.
1191 output_dir: The directory to put the packages in.
1192 root: The root path to pull all packages/files from.
Mike Frysinger35247af2012-11-16 18:58:06 -05001193 """
Ralph Nathan03047282015-03-23 11:09:32 -07001194 logging.info('Writing tarballs to %s', output_dir)
Mike Frysinger35247af2012-11-16 18:58:06 -05001195 osutils.SafeMakedirs(output_dir)
1196 ldpaths = lddtree.LoadLdpaths(root)
1197 targets = ExpandTargets(targets_wanted)
1198
David James4bc13702013-03-26 08:08:04 -07001199 with osutils.TempDir() as tempdir:
Mike Frysinger35247af2012-11-16 18:58:06 -05001200 # We have to split the root generation from the compression stages. This is
1201 # because we hardlink in all the files (to avoid overhead of reading/writing
1202 # the copies multiple times). But tar gets angry if a file's hardlink count
1203 # changes from when it starts reading a file to when it finishes.
1204 with parallel.BackgroundTaskRunner(CreatePackagableRoot) as queue:
1205 for target in targets:
1206 output_target_dir = os.path.join(tempdir, target)
1207 queue.put([target, output_target_dir, ldpaths, root])
1208
1209 # Build the tarball.
1210 with parallel.BackgroundTaskRunner(cros_build_lib.CreateTarball) as queue:
1211 for target in targets:
1212 tar_file = os.path.join(output_dir, target + '.tar.xz')
1213 queue.put([tar_file, os.path.join(tempdir, target)])
1214
1215
Brian Harring30675052012-02-29 12:18:22 -08001216def main(argv):
Mike Frysinger0c808452014-11-06 17:30:23 -05001217 parser = commandline.ArgumentParser(description=__doc__)
1218 parser.add_argument('-u', '--nousepkg',
1219 action='store_false', dest='usepkg', default=True,
1220 help='Use prebuilt packages if possible')
1221 parser.add_argument('-d', '--deleteold',
1222 action='store_true', dest='deleteold', default=False,
1223 help='Unmerge deprecated packages')
1224 parser.add_argument('-t', '--targets',
1225 dest='targets', default='sdk',
Gilad Arnold8195b532015-04-07 10:56:30 +03001226 help="Comma separated list of tuples. Special keywords "
Don Garrettc0c74002015-10-09 12:58:19 -07001227 "'host', 'sdk', 'boards', and 'all' are "
Gilad Arnold8195b532015-04-07 10:56:30 +03001228 "allowed. Defaults to 'sdk'.")
1229 parser.add_argument('--include-boards', default='', metavar='BOARDS',
1230 help='Comma separated list of boards whose toolchains we '
1231 'will always include. Default: none')
Mike Frysinger0c808452014-11-06 17:30:23 -05001232 parser.add_argument('--hostonly',
1233 dest='hostonly', default=False, action='store_true',
1234 help='Only setup the host toolchain. '
1235 'Useful for bootstrapping chroot')
Bertrand SIMONNETcae9d5f2015-03-09 15:58:01 -07001236 parser.add_argument('--show-board-cfg', '--show-cfg',
1237 dest='cfg_name', default=None,
Don Garrettc0c74002015-10-09 12:58:19 -07001238 help='Board to list toolchains tuples for')
Mike Frysinger0c808452014-11-06 17:30:23 -05001239 parser.add_argument('--create-packages',
1240 action='store_true', default=False,
1241 help='Build redistributable packages')
1242 parser.add_argument('--output-dir', default=os.getcwd(), type='path',
1243 help='Output directory')
1244 parser.add_argument('--reconfig', default=False, action='store_true',
1245 help='Reload crossdev config and reselect toolchains')
Gilad Arnold2dab78c2015-05-21 14:43:33 -07001246 parser.add_argument('--sysroot', type='path',
1247 help='The sysroot in which to install the toolchains')
Zdenek Behan508dcce2011-12-05 15:39:32 +01001248
Mike Frysinger0c808452014-11-06 17:30:23 -05001249 options = parser.parse_args(argv)
1250 options.Freeze()
Zdenek Behan508dcce2011-12-05 15:39:32 +01001251
Mike Frysinger35247af2012-11-16 18:58:06 -05001252 # Figure out what we're supposed to do and reject conflicting options.
Bertrand SIMONNETcae9d5f2015-03-09 15:58:01 -07001253 if options.cfg_name and options.create_packages:
Mike Frysinger35247af2012-11-16 18:58:06 -05001254 parser.error('conflicting options: create-packages & show-board-cfg')
Mike Frysinger984d0622012-06-01 16:08:44 -04001255
Gilad Arnold8195b532015-04-07 10:56:30 +03001256 targets_wanted = set(options.targets.split(','))
1257 boards_wanted = (set(options.include_boards.split(','))
1258 if options.include_boards else set())
Mike Frysinger35247af2012-11-16 18:58:06 -05001259
Bertrand SIMONNETcae9d5f2015-03-09 15:58:01 -07001260 if options.cfg_name:
1261 ShowConfig(options.cfg_name)
Mike Frysinger35247af2012-11-16 18:58:06 -05001262 elif options.create_packages:
1263 cros_build_lib.AssertInsideChroot()
1264 Crossdev.Load(False)
Gilad Arnold8195b532015-04-07 10:56:30 +03001265 CreatePackages(targets_wanted, options.output_dir)
Mike Frysinger35247af2012-11-16 18:58:06 -05001266 else:
1267 cros_build_lib.AssertInsideChroot()
1268 # This has to be always run as root.
1269 if os.geteuid() != 0:
1270 cros_build_lib.Die('this script must be run as root')
1271
1272 Crossdev.Load(options.reconfig)
Gilad Arnold2dab78c2015-05-21 14:43:33 -07001273 root = options.sysroot or '/'
Mike Frysinger35247af2012-11-16 18:58:06 -05001274 UpdateToolchains(options.usepkg, options.deleteold, options.hostonly,
Gilad Arnold8195b532015-04-07 10:56:30 +03001275 options.reconfig, targets_wanted, boards_wanted,
Don Garrettc0c74002015-10-09 12:58:19 -07001276 root=root)
Mike Frysinger35247af2012-11-16 18:58:06 -05001277 Crossdev.Save()
1278
1279 return 0