blob: 7fbdc403ec79a6da13e3f09ed25b071db68287fb [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]'
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010039
40CHROMIUMOS_OVERLAY = '/usr/local/portage/chromiumos'
Christopher Wileyb22c0712015-06-02 10:37:03 -070041ECLASS_OVERLAY = '/usr/local/portage/eclass-overlay'
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010042STABLE_OVERLAY = '/usr/local/portage/stable'
43CROSSDEV_OVERLAY = '/usr/local/portage/crossdev'
Zdenek Behan508dcce2011-12-05 15:39:32 +010044
45
46# TODO: The versions are stored here very much like in setup_board.
47# The goal for future is to differentiate these using a config file.
48# This is done essentially by messing with GetDesiredPackageVersions()
49DEFAULT_VERSION = PACKAGE_STABLE
50DEFAULT_TARGET_VERSION_MAP = {
Zdenek Behan508dcce2011-12-05 15:39:32 +010051}
52TARGET_VERSION_MAP = {
Mike Frysingerd6e2df02014-11-26 02:55:04 -050053 'host' : {
54 'gdb' : PACKAGE_NONE,
55 },
Zdenek Behan508dcce2011-12-05 15:39:32 +010056}
Rahul Chaudhry4b803052015-05-13 15:25:56 -070057
58# Enable the Go compiler for these targets.
59TARGET_GO_ENABLED = (
60 'x86_64-cros-linux-gnu',
Rahul Chaudhry4b803052015-05-13 15:25:56 -070061 'armv7a-cros-linux-gnueabi',
62)
63CROSSDEV_GO_ARGS = ['--ex-pkg', 'dev-lang/go']
64
Manoj Gupta1b5642e2017-03-08 16:44:12 -080065# Enable llvm's compiler-rt for these targets.
66TARGET_COMPILER_RT_ENABLED = (
67 'armv7a-cros-linux-gnueabi',
Manoj Gupta946abb42017-04-12 14:27:19 -070068 'aarch64-cros-linux-gnu',
Manoj Gupta1b5642e2017-03-08 16:44:12 -080069)
70CROSSDEV_COMPILER_RT_ARGS = ['--ex-pkg', 'sys-libs/compiler-rt']
71
Manoj Gupta946abb42017-04-12 14:27:19 -070072TARGET_LLVM_PKGS_ENABLED = (
73 'armv7a-cros-linux-gnueabi',
74 'aarch64-cros-linux-gnu',
75 'x86_64-cros-linux-gnu',
76)
77
78LLVM_PKGS_TABLE = {
Yunlian Jiangbb2a3d32017-04-26 14:44:09 -070079 'ex_libcxxabi' : ['--ex-pkg', 'sys-libs/libcxxabi'],
80 'ex_libcxx' : ['--ex-pkg', 'sys-libs/libcxx'],
Manoj Gupta946abb42017-04-12 14:27:19 -070081}
82
Zdenek Behan508dcce2011-12-05 15:39:32 +010083# Overrides for {gcc,binutils}-config, pick a package with particular suffix.
84CONFIG_TARGET_SUFFIXES = {
Mike Frysingerd6e2df02014-11-26 02:55:04 -050085 'binutils' : {
Mike Frysinger8a83c622015-05-28 00:35:05 -040086 'armv6j-cros-linux-gnueabi': '-gold',
Han Shen43b84422015-02-19 11:38:13 -080087 'armv7a-cros-linux-gnueabi': '-gold',
Mike Frysingerd6e2df02014-11-26 02:55:04 -050088 'i686-pc-linux-gnu' : '-gold',
89 'x86_64-cros-linux-gnu' : '-gold',
90 },
Zdenek Behan508dcce2011-12-05 15:39:32 +010091}
Zdenek Behan508dcce2011-12-05 15:39:32 +010092# Global per-run cache that will be filled ondemand in by GetPackageMap()
93# function as needed.
94target_version_map = {
95}
96
97
David James66a09c42012-11-05 13:31:38 -080098class Crossdev(object):
99 """Class for interacting with crossdev and caching its output."""
100
101 _CACHE_FILE = os.path.join(CROSSDEV_OVERLAY, '.configured.json')
102 _CACHE = {}
Han Shene23782f2016-02-18 12:20:00 -0800103 # Packages that needs separate handling, in addition to what we have from
104 # crossdev.
105 MANUAL_PKGS = {
Manoj Guptaf0a602e2017-08-02 10:25:45 -0700106 'clang': 'sys-devel',
Han Shene23782f2016-02-18 12:20:00 -0800107 'llvm': 'sys-devel',
Manoj Gupta20cfc6c2017-07-19 15:49:55 -0700108 'libcxxabi': 'sys-libs',
109 'libcxx': 'sys-libs',
Han Shene23782f2016-02-18 12:20:00 -0800110 }
David James66a09c42012-11-05 13:31:38 -0800111
112 @classmethod
113 def Load(cls, reconfig):
Mike Frysinger3ed47722017-08-08 14:59:08 -0400114 """Load crossdev cache from disk.
115
116 We invalidate the cache when crossdev updates or this script changes.
117 """
David James90239b92012-11-05 15:31:34 -0800118 crossdev_version = GetStablePackageVersion('sys-devel/crossdev', True)
Mike Frysinger3ed47722017-08-08 14:59:08 -0400119 # If we run the compiled/cached .pyc file, we'll read/hash that when we
120 # really always want to track the source .py file.
121 script = os.path.abspath(__file__)
122 if script.endswith('.pyc'):
123 script = script[:-1]
124 setup_toolchains_hash = hashlib.md5(osutils.ReadFile(script)).hexdigest()
125
126 cls._CACHE = {
127 'crossdev_version': crossdev_version,
128 'setup_toolchains_hash': setup_toolchains_hash,
129 }
130
131 logging.debug('cache: checking file: %s', cls._CACHE_FILE)
132 if reconfig:
133 logging.debug('cache: forcing regen due to reconfig')
134 return
135
136 try:
137 file_data = osutils.ReadFile(cls._CACHE_FILE)
138 except IOError as e:
139 if e.errno != errno.ENOENT:
140 logging.warning('cache: reading failed: %s', e)
141 osutils.SafeUnlink(cls._CACHE_FILE)
142 return
143
144 try:
145 data = json.loads(file_data)
146 except ValueError as e:
147 logging.warning('cache: ignoring invalid content: %s', e)
148 return
149
150 if crossdev_version != data.get('crossdev_version'):
151 logging.debug('cache: rebuilding after crossdev upgrade')
152 elif setup_toolchains_hash != data.get('setup_toolchains_hash'):
153 logging.debug('cache: rebuilding after cros_setup_toolchains change')
154 else:
155 logging.debug('cache: content is up-to-date!')
156 cls._CACHE = data
David James66a09c42012-11-05 13:31:38 -0800157
158 @classmethod
159 def Save(cls):
160 """Store crossdev cache on disk."""
161 # Save the cache from the successful run.
162 with open(cls._CACHE_FILE, 'w') as f:
163 json.dump(cls._CACHE, f)
164
165 @classmethod
166 def GetConfig(cls, target):
167 """Returns a map of crossdev provided variables about a tuple."""
168 CACHE_ATTR = '_target_tuple_map'
169
170 val = cls._CACHE.setdefault(CACHE_ATTR, {})
171 if not target in val:
172 # Find out the crossdev tuple.
173 target_tuple = target
174 if target == 'host':
David James27ac4ae2012-12-03 23:16:15 -0800175 target_tuple = toolchain.GetHostTuple()
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700176 # Build the crossdev command.
177 cmd = ['crossdev', '--show-target-cfg', '--ex-gdb']
Manoj Gupta1b5642e2017-03-08 16:44:12 -0800178 if target in TARGET_COMPILER_RT_ENABLED:
179 cmd.extend(CROSSDEV_COMPILER_RT_ARGS)
Manoj Guptab8181562017-05-21 10:18:59 -0700180 if target in TARGET_GO_ENABLED:
181 cmd.extend(CROSSDEV_GO_ARGS)
Manoj Gupta946abb42017-04-12 14:27:19 -0700182 if target in TARGET_LLVM_PKGS_ENABLED:
183 for pkg in LLVM_PKGS_TABLE:
184 cmd.extend(LLVM_PKGS_TABLE[pkg])
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700185 cmd.extend(['-t', target_tuple])
David James66a09c42012-11-05 13:31:38 -0800186 # Catch output of crossdev.
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700187 out = cros_build_lib.RunCommand(cmd, print_cmd=False,
188 redirect_stdout=True).output.splitlines()
David James66a09c42012-11-05 13:31:38 -0800189 # List of tuples split at the first '=', converted into dict.
Han Shene23782f2016-02-18 12:20:00 -0800190 conf = dict((k, cros_build_lib.ShellUnquote(v))
191 for k, v in (x.split('=', 1) for x in out))
192 conf['crosspkgs'] = conf['crosspkgs'].split()
193
194 for pkg, cat in cls.MANUAL_PKGS.iteritems():
Mike Frysinger3bba5032016-09-20 14:15:04 -0400195 conf[pkg + '_pn'] = pkg
196 conf[pkg + '_category'] = cat
197 if pkg not in conf['crosspkgs']:
198 conf['crosspkgs'].append(pkg)
Han Shene23782f2016-02-18 12:20:00 -0800199
200 val[target] = conf
201
David James66a09c42012-11-05 13:31:38 -0800202 return val[target]
203
204 @classmethod
205 def UpdateTargets(cls, targets, usepkg, config_only=False):
206 """Calls crossdev to initialize a cross target.
207
208 Args:
Don Garrett25f309a2014-03-19 14:02:12 -0700209 targets: The list of targets to initialize using crossdev.
210 usepkg: Copies the commandline opts.
211 config_only: Just update.
David James66a09c42012-11-05 13:31:38 -0800212 """
213 configured_targets = cls._CACHE.setdefault('configured_targets', [])
214
215 cmdbase = ['crossdev', '--show-fail-log']
216 cmdbase.extend(['--env', 'FEATURES=splitdebug'])
217 # Pick stable by default, and override as necessary.
218 cmdbase.extend(['-P', '--oneshot'])
219 if usepkg:
220 cmdbase.extend(['-P', '--getbinpkg',
221 '-P', '--usepkgonly',
222 '--without-headers'])
223
Christopher Wileyb22c0712015-06-02 10:37:03 -0700224 overlays = ' '.join((CHROMIUMOS_OVERLAY, ECLASS_OVERLAY, STABLE_OVERLAY))
David James66a09c42012-11-05 13:31:38 -0800225 cmdbase.extend(['--overlays', overlays])
226 cmdbase.extend(['--ov-output', CROSSDEV_OVERLAY])
227
228 for target in targets:
229 if config_only and target in configured_targets:
230 continue
231
232 cmd = cmdbase + ['-t', target]
233
234 for pkg in GetTargetPackages(target):
235 if pkg == 'gdb':
236 # Gdb does not have selectable versions.
237 cmd.append('--ex-gdb')
Manoj Guptab8181562017-05-21 10:18:59 -0700238 elif pkg == 'ex_compiler-rt':
239 cmd.extend(CROSSDEV_COMPILER_RT_ARGS)
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700240 elif pkg == 'ex_go':
241 # Go does not have selectable versions.
242 cmd.extend(CROSSDEV_GO_ARGS)
Manoj Gupta946abb42017-04-12 14:27:19 -0700243 elif pkg in LLVM_PKGS_TABLE:
244 cmd.extend(LLVM_PKGS_TABLE[pkg])
Han Shene23782f2016-02-18 12:20:00 -0800245 elif pkg in cls.MANUAL_PKGS:
246 pass
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700247 else:
248 # The first of the desired versions is the "primary" one.
249 version = GetDesiredPackageVersions(target, pkg)[0]
250 cmd.extend(['--%s' % pkg, version])
David James66a09c42012-11-05 13:31:38 -0800251
252 cmd.extend(targets[target]['crossdev'].split())
253 if config_only:
254 # In this case we want to just quietly reinit
255 cmd.append('--init-target')
256 cros_build_lib.RunCommand(cmd, print_cmd=False, redirect_stdout=True)
257 else:
258 cros_build_lib.RunCommand(cmd)
259
260 configured_targets.append(target)
261
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100262
Zdenek Behan508dcce2011-12-05 15:39:32 +0100263def GetPackageMap(target):
264 """Compiles a package map for the given target from the constants.
265
266 Uses a cache in target_version_map, that is dynamically filled in as needed,
267 since here everything is static data and the structuring is for ease of
268 configurability only.
269
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500270 Args:
271 target: The target for which to return a version map
Zdenek Behan508dcce2011-12-05 15:39:32 +0100272
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500273 Returns:
274 A map between packages and desired versions in internal format
275 (using the PACKAGE_* constants)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100276 """
277 if target in target_version_map:
278 return target_version_map[target]
279
280 # Start from copy of the global defaults.
281 result = copy.copy(DEFAULT_TARGET_VERSION_MAP)
282
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100283 for pkg in GetTargetPackages(target):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100284 # prefer any specific overrides
285 if pkg in TARGET_VERSION_MAP.get(target, {}):
286 result[pkg] = TARGET_VERSION_MAP[target][pkg]
287 else:
288 # finally, if not already set, set a sane default
289 result.setdefault(pkg, DEFAULT_VERSION)
290 target_version_map[target] = result
291 return result
292
293
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100294def GetTargetPackages(target):
295 """Returns a list of packages for a given target."""
David James66a09c42012-11-05 13:31:38 -0800296 conf = Crossdev.GetConfig(target)
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100297 # Undesired packages are denoted by empty ${pkg}_pn variable.
Han Shene23782f2016-02-18 12:20:00 -0800298 return [x for x in conf['crosspkgs'] if conf.get(x+'_pn')]
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100299
300
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100301# Portage helper functions:
302def GetPortagePackage(target, package):
303 """Returns a package name for the given target."""
David James66a09c42012-11-05 13:31:38 -0800304 conf = Crossdev.GetConfig(target)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100305 # Portage category:
Han Shene23782f2016-02-18 12:20:00 -0800306 if target == 'host' or package in Crossdev.MANUAL_PKGS:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100307 category = conf[package + '_category']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100308 else:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100309 category = conf['category']
310 # Portage package:
311 pn = conf[package + '_pn']
312 # Final package name:
Mike Frysinger422faf42014-11-12 23:16:48 -0500313 assert category
314 assert pn
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100315 return '%s/%s' % (category, pn)
316
317
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100318def IsPackageDisabled(target, package):
319 """Returns if the given package is not used for the target."""
320 return GetDesiredPackageVersions(target, package) == [PACKAGE_NONE]
321
Liam McLoughlinf54a0782012-05-17 23:36:52 +0100322
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700323def PortageTrees(root):
324 """Return the portage trees for a given root."""
325 if root == '/':
326 return portage.db['/']
327 # The portage logic requires the path always end in a slash.
328 root = root.rstrip('/') + '/'
329 return portage.create_trees(target_root=root, config_root=root)[root]
330
331
332def GetInstalledPackageVersions(atom, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100333 """Extracts the list of current versions of a target, package pair.
334
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500335 Args:
336 atom: The atom to operate on (e.g. sys-devel/gcc)
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700337 root: The root to check for installed packages.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100338
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500339 Returns:
340 The list of versions of the package currently installed.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100341 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100342 versions = []
Mike Frysinger506e75f2012-12-17 14:21:13 -0500343 # pylint: disable=E1101
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700344 for pkg in PortageTrees(root)['vartree'].dbapi.match(atom, use_cache=0):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100345 version = portage.versions.cpv_getversion(pkg)
346 versions.append(version)
347 return versions
348
349
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700350def GetStablePackageVersion(atom, installed, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100351 """Extracts the current stable version for a given package.
352
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500353 Args:
354 atom: The target/package to operate on eg. i686-pc-linux-gnu,gcc
355 installed: Whether we want installed packages or ebuilds
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700356 root: The root to use when querying packages.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100357
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500358 Returns:
359 A string containing the latest version.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100360 """
David James90239b92012-11-05 15:31:34 -0800361 pkgtype = 'vartree' if installed else 'porttree'
Mike Frysinger506e75f2012-12-17 14:21:13 -0500362 # pylint: disable=E1101
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700363 cpv = portage.best(PortageTrees(root)[pkgtype].dbapi.match(atom, use_cache=0))
David James90239b92012-11-05 15:31:34 -0800364 return portage.versions.cpv_getversion(cpv) if cpv else None
Zdenek Behan508dcce2011-12-05 15:39:32 +0100365
366
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700367def VersionListToNumeric(target, package, versions, installed, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100368 """Resolves keywords in a given version list for a particular package.
369
370 Resolving means replacing PACKAGE_STABLE with the actual number.
371
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500372 Args:
373 target: The target to operate on (e.g. i686-pc-linux-gnu)
374 package: The target/package to operate on (e.g. gcc)
375 versions: List of versions to resolve
376 installed: Query installed packages
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700377 root: The install root to use; ignored if |installed| is False.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100378
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500379 Returns:
380 List of purely numeric versions equivalent to argument
Zdenek Behan508dcce2011-12-05 15:39:32 +0100381 """
382 resolved = []
David James90239b92012-11-05 15:31:34 -0800383 atom = GetPortagePackage(target, package)
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700384 if not installed:
385 root = '/'
Zdenek Behan508dcce2011-12-05 15:39:32 +0100386 for version in versions:
387 if version == PACKAGE_STABLE:
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700388 resolved.append(GetStablePackageVersion(atom, installed, root=root))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100389 elif version != PACKAGE_NONE:
390 resolved.append(version)
391 return resolved
392
393
394def GetDesiredPackageVersions(target, package):
395 """Produces the list of desired versions for each target, package pair.
396
397 The first version in the list is implicitly treated as primary, ie.
398 the version that will be initialized by crossdev and selected.
399
400 If the version is PACKAGE_STABLE, it really means the current version which
401 is emerged by using the package atom with no particular version key.
402 Since crossdev unmasks all packages by default, this will actually
403 mean 'unstable' in most cases.
404
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500405 Args:
406 target: The target to operate on (e.g. i686-pc-linux-gnu)
407 package: The target/package to operate on (e.g. gcc)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100408
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500409 Returns:
410 A list composed of either a version string, PACKAGE_STABLE
Zdenek Behan508dcce2011-12-05 15:39:32 +0100411 """
412 packagemap = GetPackageMap(target)
413
414 versions = []
415 if package in packagemap:
416 versions.append(packagemap[package])
417
418 return versions
419
420
421def TargetIsInitialized(target):
422 """Verifies if the given list of targets has been correctly initialized.
423
424 This determines whether we have to call crossdev while emerging
425 toolchain packages or can do it using emerge. Emerge is naturally
426 preferred, because all packages can be updated in a single pass.
427
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500428 Args:
429 target: The target to operate on (e.g. i686-pc-linux-gnu)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100430
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500431 Returns:
432 True if |target| is completely initialized, else False
Zdenek Behan508dcce2011-12-05 15:39:32 +0100433 """
434 # Check if packages for the given target all have a proper version.
435 try:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100436 for package in GetTargetPackages(target):
David James66a09c42012-11-05 13:31:38 -0800437 atom = GetPortagePackage(target, package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100438 # Do we even want this package && is it initialized?
David James90239b92012-11-05 15:31:34 -0800439 if not IsPackageDisabled(target, package) and not (
440 GetStablePackageVersion(atom, True) and
441 GetStablePackageVersion(atom, False)):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100442 return False
443 return True
444 except cros_build_lib.RunCommandError:
445 # Fails - The target has likely never been initialized before.
446 return False
447
448
449def RemovePackageMask(target):
450 """Removes a package.mask file for the given platform.
451
452 The pre-existing package.mask files can mess with the keywords.
453
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500454 Args:
455 target: The target to operate on (e.g. i686-pc-linux-gnu)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100456 """
457 maskfile = os.path.join('/etc/portage/package.mask', 'cross-' + target)
Brian Harringaf019fb2012-05-10 15:06:13 -0700458 osutils.SafeUnlink(maskfile)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100459
460
Zdenek Behan508dcce2011-12-05 15:39:32 +0100461# Main functions performing the actual update steps.
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700462def RebuildLibtool(root='/'):
Mike Frysingerc880a962013-11-08 13:59:06 -0500463 """Rebuild libtool as needed
464
465 Libtool hardcodes full paths to internal gcc files, so whenever we upgrade
466 gcc, libtool will break. We can't use binary packages either as those will
467 most likely be compiled against the previous version of gcc.
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700468
469 Args:
470 root: The install root where we want libtool rebuilt.
Mike Frysingerc880a962013-11-08 13:59:06 -0500471 """
472 needs_update = False
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700473 with open(os.path.join(root, 'usr/bin/libtool')) as f:
Mike Frysingerc880a962013-11-08 13:59:06 -0500474 for line in f:
475 # Look for a line like:
476 # sys_lib_search_path_spec="..."
477 # It'll be a list of paths and gcc will be one of them.
478 if line.startswith('sys_lib_search_path_spec='):
479 line = line.rstrip()
480 for path in line.split('=', 1)[1].strip('"').split():
Mike Frysinger3bba5032016-09-20 14:15:04 -0400481 root_path = os.path.join(root, path.lstrip(os.path.sep))
482 logging.debug('Libtool: checking %s', root_path)
483 if not os.path.exists(root_path):
484 logging.info('Rebuilding libtool after gcc upgrade')
485 logging.info(' %s', line)
486 logging.info(' missing path: %s', path)
Mike Frysingerc880a962013-11-08 13:59:06 -0500487 needs_update = True
488 break
489
490 if needs_update:
491 break
492
493 if needs_update:
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700494 cmd = [EMERGE_CMD, '--oneshot']
495 if root != '/':
496 cmd.extend(['--sysroot=%s' % root, '--root=%s' % root])
497 cmd.append('sys-devel/libtool')
Mike Frysingerc880a962013-11-08 13:59:06 -0500498 cros_build_lib.RunCommand(cmd)
Mike Frysinger3bba5032016-09-20 14:15:04 -0400499 else:
500 logging.debug('Libtool is up-to-date; no need to rebuild')
Mike Frysingerc880a962013-11-08 13:59:06 -0500501
502
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700503def UpdateTargets(targets, usepkg, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100504 """Determines which packages need update/unmerge and defers to portage.
505
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500506 Args:
507 targets: The list of targets to update
508 usepkg: Copies the commandline option
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700509 root: The install root in which we want packages updated.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100510 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100511 # For each target, we do two things. Figure out the list of updates,
512 # and figure out the appropriate keywords/masks. Crossdev will initialize
513 # these, but they need to be regenerated on every update.
Mike Frysinger3bba5032016-09-20 14:15:04 -0400514 logging.info('Determining required toolchain updates...')
David James90239b92012-11-05 15:31:34 -0800515 mergemap = {}
Zdenek Behan508dcce2011-12-05 15:39:32 +0100516 for target in targets:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400517 logging.debug('Updating target %s', target)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100518 # Record the highest needed version for each target, for masking purposes.
519 RemovePackageMask(target)
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100520 for package in GetTargetPackages(target):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100521 # Portage name for the package
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100522 if IsPackageDisabled(target, package):
Mike Frysinger3bba5032016-09-20 14:15:04 -0400523 logging.debug(' Skipping disabled package %s', package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100524 continue
Mike Frysinger3bba5032016-09-20 14:15:04 -0400525 logging.debug(' Updating package %s', package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100526 pkg = GetPortagePackage(target, package)
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700527 current = GetInstalledPackageVersions(pkg, root=root)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100528 desired = GetDesiredPackageVersions(target, package)
Zdenek Behan699ddd32012-04-13 07:14:08 +0200529 desired_num = VersionListToNumeric(target, package, desired, False)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100530 mergemap[pkg] = set(desired_num).difference(current)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100531
Zdenek Behan508dcce2011-12-05 15:39:32 +0100532 packages = []
533 for pkg in mergemap:
534 for ver in mergemap[pkg]:
Zdenek Behan677b6d82012-04-11 05:31:47 +0200535 if ver != PACKAGE_NONE:
David James90239b92012-11-05 15:31:34 -0800536 packages.append(pkg)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100537
538 if not packages:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400539 logging.info('Nothing to update!')
David Jamesf8c672f2012-11-06 13:38:11 -0800540 return False
Zdenek Behan508dcce2011-12-05 15:39:32 +0100541
Mike Frysinger3bba5032016-09-20 14:15:04 -0400542 logging.info('Updating packages:')
543 logging.info('%s', packages)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100544
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100545 cmd = [EMERGE_CMD, '--oneshot', '--update']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100546 if usepkg:
547 cmd.extend(['--getbinpkg', '--usepkgonly'])
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700548 if root != '/':
549 cmd.extend(['--sysroot=%s' % root, '--root=%s' % root])
Zdenek Behan508dcce2011-12-05 15:39:32 +0100550
551 cmd.extend(packages)
552 cros_build_lib.RunCommand(cmd)
David Jamesf8c672f2012-11-06 13:38:11 -0800553 return True
Zdenek Behan508dcce2011-12-05 15:39:32 +0100554
555
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700556def CleanTargets(targets, root='/'):
557 """Unmerges old packages that are assumed unnecessary.
558
559 Args:
560 targets: The list of targets to clean up.
561 root: The install root in which we want packages cleaned up.
562 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100563 unmergemap = {}
564 for target in targets:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400565 logging.debug('Cleaning target %s', target)
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100566 for package in GetTargetPackages(target):
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100567 if IsPackageDisabled(target, package):
Mike Frysinger3bba5032016-09-20 14:15:04 -0400568 logging.debug(' Skipping disabled package %s', package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100569 continue
Mike Frysinger3bba5032016-09-20 14:15:04 -0400570 logging.debug(' Cleaning package %s', package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100571 pkg = GetPortagePackage(target, package)
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700572 current = GetInstalledPackageVersions(pkg, root=root)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100573 desired = GetDesiredPackageVersions(target, package)
Gilad Arnold2fcb0aa2015-05-21 14:51:41 -0700574 # NOTE: This refers to installed packages (vartree) rather than the
575 # Portage version (porttree and/or bintree) when determining the current
576 # version. While this isn't the most accurate thing to do, it is probably
577 # a good simple compromise, which should have the desired result of
578 # uninstalling everything but the latest installed version. In
579 # particular, using the bintree (--usebinpkg) requires a non-trivial
580 # binhost sync and is probably more complex than useful.
Zdenek Behan699ddd32012-04-13 07:14:08 +0200581 desired_num = VersionListToNumeric(target, package, desired, True)
582 if not set(desired_num).issubset(current):
Mike Frysinger3bba5032016-09-20 14:15:04 -0400583 logging.warning('Error detecting stable version for %s, '
584 'skipping clean!', pkg)
Zdenek Behan699ddd32012-04-13 07:14:08 +0200585 return
Zdenek Behan508dcce2011-12-05 15:39:32 +0100586 unmergemap[pkg] = set(current).difference(desired_num)
587
588 # Cleaning doesn't care about consistency and rebuilding package.* files.
589 packages = []
590 for pkg, vers in unmergemap.iteritems():
591 packages.extend('=%s-%s' % (pkg, ver) for ver in vers if ver != '9999')
592
593 if packages:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400594 logging.info('Cleaning packages:')
595 logging.info('%s', packages)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100596 cmd = [EMERGE_CMD, '--unmerge']
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700597 if root != '/':
598 cmd.extend(['--sysroot=%s' % root, '--root=%s' % root])
Zdenek Behan508dcce2011-12-05 15:39:32 +0100599 cmd.extend(packages)
600 cros_build_lib.RunCommand(cmd)
601 else:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400602 logging.info('Nothing to clean!')
Zdenek Behan508dcce2011-12-05 15:39:32 +0100603
604
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700605def SelectActiveToolchains(targets, suffixes, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100606 """Runs gcc-config and binutils-config to select the desired.
607
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500608 Args:
609 targets: The targets to select
610 suffixes: Optional target-specific hacks
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700611 root: The root where we want to select toolchain versions.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100612 """
613 for package in ['gcc', 'binutils']:
614 for target in targets:
615 # Pick the first version in the numbered list as the selected one.
616 desired = GetDesiredPackageVersions(target, package)
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700617 desired_num = VersionListToNumeric(target, package, desired, True,
618 root=root)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100619 desired = desired_num[0]
620 # *-config does not play revisions, strip them, keep just PV.
621 desired = portage.versions.pkgsplit('%s-%s' % (package, desired))[1]
622
623 if target == 'host':
624 # *-config is the only tool treating host identically (by tuple).
David James27ac4ae2012-12-03 23:16:15 -0800625 target = toolchain.GetHostTuple()
Zdenek Behan508dcce2011-12-05 15:39:32 +0100626
627 # And finally, attach target to it.
628 desired = '%s-%s' % (target, desired)
629
630 # Target specific hacks
631 if package in suffixes:
632 if target in suffixes[package]:
633 desired += suffixes[package][target]
634
David James7ec5efc2012-11-06 09:39:49 -0800635 extra_env = {'CHOST': target}
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700636 if root != '/':
637 extra_env['ROOT'] = root
David James7ec5efc2012-11-06 09:39:49 -0800638 cmd = ['%s-config' % package, '-c', target]
Mike Frysingerd6e2df02014-11-26 02:55:04 -0500639 result = cros_build_lib.RunCommand(
640 cmd, print_cmd=False, redirect_stdout=True, extra_env=extra_env)
641 current = result.output.splitlines()[0]
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700642
643 # Do not reconfig when the current is live or nothing needs to be done.
644 extra_env = {'ROOT': root} if root != '/' else None
Zdenek Behan508dcce2011-12-05 15:39:32 +0100645 if current != desired and current != '9999':
Mike Frysingerd6e2df02014-11-26 02:55:04 -0500646 cmd = [package + '-config', desired]
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700647 cros_build_lib.RunCommand(cmd, print_cmd=False, extra_env=extra_env)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100648
649
Mike Frysinger35247af2012-11-16 18:58:06 -0500650def ExpandTargets(targets_wanted):
651 """Expand any possible toolchain aliases into full targets
652
653 This will expand 'all' and 'sdk' into the respective toolchain tuples.
654
655 Args:
656 targets_wanted: The targets specified by the user.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500657
Mike Frysinger35247af2012-11-16 18:58:06 -0500658 Returns:
Gilad Arnold8195b532015-04-07 10:56:30 +0300659 Dictionary of concrete targets and their toolchain tuples.
Mike Frysinger35247af2012-11-16 18:58:06 -0500660 """
Mike Frysinger35247af2012-11-16 18:58:06 -0500661 targets_wanted = set(targets_wanted)
Don Garrettc0c74002015-10-09 12:58:19 -0700662 if targets_wanted == set(['boards']):
663 # Only pull targets from the included boards.
Gilad Arnold8195b532015-04-07 10:56:30 +0300664 return {}
665
666 all_targets = toolchain.GetAllTargets()
Mike Frysinger35247af2012-11-16 18:58:06 -0500667 if targets_wanted == set(['all']):
Gilad Arnold8195b532015-04-07 10:56:30 +0300668 return all_targets
669 if targets_wanted == set(['sdk']):
Mike Frysinger35247af2012-11-16 18:58:06 -0500670 # Filter out all the non-sdk toolchains as we don't want to mess
671 # with those in all of our builds.
Gilad Arnold8195b532015-04-07 10:56:30 +0300672 return toolchain.FilterToolchains(all_targets, 'sdk', True)
673
674 # Verify user input.
675 nonexistent = targets_wanted.difference(all_targets)
676 if nonexistent:
677 raise ValueError('Invalid targets: %s', ','.join(nonexistent))
678 return {t: all_targets[t] for t in targets_wanted}
Mike Frysinger35247af2012-11-16 18:58:06 -0500679
680
David Jamesf8c672f2012-11-06 13:38:11 -0800681def UpdateToolchains(usepkg, deleteold, hostonly, reconfig,
Don Garrettc0c74002015-10-09 12:58:19 -0700682 targets_wanted, boards_wanted, root='/'):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100683 """Performs all steps to create a synchronized toolchain enviroment.
684
Mike Frysingerdc649ae2014-11-26 19:29:24 -0500685 Args:
686 usepkg: Use prebuilt packages
687 deleteold: Unmerge deprecated packages
688 hostonly: Only setup the host toolchain
689 reconfig: Reload crossdev config and reselect toolchains
690 targets_wanted: All the targets to update
691 boards_wanted: Load targets from these boards
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700692 root: The root in which to install the toolchains.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100693 """
David Jamesf8c672f2012-11-06 13:38:11 -0800694 targets, crossdev_targets, reconfig_targets = {}, {}, {}
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100695 if not hostonly:
696 # For hostonly, we can skip most of the below logic, much of which won't
697 # work on bare systems where this is useful.
Mike Frysinger35247af2012-11-16 18:58:06 -0500698 targets = ExpandTargets(targets_wanted)
Mike Frysinger7ccee992012-06-01 21:27:59 -0400699
Don Garrettc0c74002015-10-09 12:58:19 -0700700 # Now re-add any targets that might be from this board. This is to
Gilad Arnold8195b532015-04-07 10:56:30 +0300701 # allow unofficial boards to declare their own toolchains.
Mike Frysinger7ccee992012-06-01 21:27:59 -0400702 for board in boards_wanted:
David James27ac4ae2012-12-03 23:16:15 -0800703 targets.update(toolchain.GetToolchainsForBoard(board))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100704
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100705 # First check and initialize all cross targets that need to be.
Mike Frysinger7ccee992012-06-01 21:27:59 -0400706 for target in targets:
707 if TargetIsInitialized(target):
708 reconfig_targets[target] = targets[target]
709 else:
710 crossdev_targets[target] = targets[target]
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100711 if crossdev_targets:
Mike Frysinger3bba5032016-09-20 14:15:04 -0400712 logging.info('The following targets need to be re-initialized:')
713 logging.info('%s', crossdev_targets)
David James66a09c42012-11-05 13:31:38 -0800714 Crossdev.UpdateTargets(crossdev_targets, usepkg)
Zdenek Behan8be29ba2012-05-29 23:10:34 +0200715 # Those that were not initialized may need a config update.
David James66a09c42012-11-05 13:31:38 -0800716 Crossdev.UpdateTargets(reconfig_targets, usepkg, config_only=True)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100717
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100718 # We want host updated.
Mike Frysinger7ccee992012-06-01 21:27:59 -0400719 targets['host'] = {}
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100720
721 # Now update all packages.
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700722 if UpdateTargets(targets, usepkg, root=root) or crossdev_targets or reconfig:
723 SelectActiveToolchains(targets, CONFIG_TARGET_SUFFIXES, root=root)
David James7ec5efc2012-11-06 09:39:49 -0800724
725 if deleteold:
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700726 CleanTargets(targets, root=root)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100727
Mike Frysingerc880a962013-11-08 13:59:06 -0500728 # Now that we've cleared out old versions, see if we need to rebuild
729 # anything. Can't do this earlier as it might not be broken.
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700730 RebuildLibtool(root=root)
Mike Frysingerc880a962013-11-08 13:59:06 -0500731
Zdenek Behan508dcce2011-12-05 15:39:32 +0100732
Bertrand SIMONNETcae9d5f2015-03-09 15:58:01 -0700733def ShowConfig(name):
734 """Show the toolchain tuples used by |name|
Mike Frysinger35247af2012-11-16 18:58:06 -0500735
736 Args:
Don Garrettc0c74002015-10-09 12:58:19 -0700737 name: The board name to query.
Mike Frysinger35247af2012-11-16 18:58:06 -0500738 """
Don Garrettc0c74002015-10-09 12:58:19 -0700739 toolchains = toolchain.GetToolchainsForBoard(name)
Mike Frysinger35247af2012-11-16 18:58:06 -0500740 # Make sure we display the default toolchain first.
Mike Frysinger3bba5032016-09-20 14:15:04 -0400741 # Note: Do not use logging here as this is meant to be used by other tools.
Mike Frysinger383367e2014-09-16 15:06:17 -0400742 print(','.join(
David James27ac4ae2012-12-03 23:16:15 -0800743 toolchain.FilterToolchains(toolchains, 'default', True).keys() +
Mike Frysinger383367e2014-09-16 15:06:17 -0400744 toolchain.FilterToolchains(toolchains, 'default', False).keys()))
Mike Frysinger35247af2012-11-16 18:58:06 -0500745
746
Mike Frysinger35247af2012-11-16 18:58:06 -0500747def GeneratePathWrapper(root, wrappath, path):
748 """Generate a shell script to execute another shell script
749
750 Since we can't symlink a wrapped ELF (see GenerateLdsoWrapper) because the
751 argv[0] won't be pointing to the correct path, generate a shell script that
752 just executes another program with its full path.
753
754 Args:
755 root: The root tree to generate scripts inside of
756 wrappath: The full path (inside |root|) to create the wrapper
757 path: The target program which this wrapper will execute
758 """
759 replacements = {
760 'path': path,
761 'relroot': os.path.relpath('/', os.path.dirname(wrappath)),
762 }
763 wrapper = """#!/bin/sh
764base=$(realpath "$0")
765basedir=${base%%/*}
766exec "${basedir}/%(relroot)s%(path)s" "$@"
767""" % replacements
768 root_wrapper = root + wrappath
769 if os.path.islink(root_wrapper):
770 os.unlink(root_wrapper)
771 else:
772 osutils.SafeMakedirs(os.path.dirname(root_wrapper))
773 osutils.WriteFile(root_wrapper, wrapper)
Mike Frysinger60ec1012013-10-21 00:11:10 -0400774 os.chmod(root_wrapper, 0o755)
Mike Frysinger35247af2012-11-16 18:58:06 -0500775
776
Rahul Chaudhrya8127bb2016-07-22 15:53:17 -0700777def FixClangXXWrapper(root, path):
778 """Fix wrapper shell scripts and symlinks for invoking clang++
779
780 In a typical installation, clang++ symlinks to clang, which symlinks to the
781 elf executable. The executable distinguishes between clang and clang++ based
782 on argv[0].
783
784 When invoked through the LdsoWrapper, argv[0] always contains the path to the
785 executable elf file, making clang/clang++ invocations indistinguishable.
786
787 This function detects if the elf executable being wrapped is clang-X.Y, and
788 fixes wrappers/symlinks as necessary so that clang++ will work correctly.
789
790 The calling sequence now becomes:
791 -) clang++ invocation turns into clang++-3.9 (which is a copy of clang-3.9,
792 the Ldsowrapper).
793 -) clang++-3.9 uses the Ldso to invoke clang++-3.9.elf, which is a symlink
794 to the original clang-3.9 elf.
795 -) The difference this time is that inside the elf file execution, $0 is
796 set as .../usr/bin/clang++-3.9.elf, which contains 'clang++' in the name.
797
798 Args:
799 root: The root tree to generate scripts / symlinks inside of
800 path: The target elf for which LdsoWrapper was created
801 """
802 if re.match(r'/usr/bin/clang-\d+\.\d+$', path):
803 logging.info('fixing clang++ invocation for %s', path)
804 clangdir = os.path.dirname(root + path)
805 clang = os.path.basename(path)
806 clangxx = clang.replace('clang', 'clang++')
807
808 # Create a symlink clang++-X.Y.elf to point to clang-X.Y.elf
809 os.symlink(clang + '.elf', os.path.join(clangdir, clangxx + '.elf'))
810
811 # Create a hardlink clang++-X.Y pointing to clang-X.Y
812 os.link(os.path.join(clangdir, clang), os.path.join(clangdir, clangxx))
813
814 # Adjust the clang++ symlink to point to clang++-X.Y
815 os.unlink(os.path.join(clangdir, 'clang++'))
816 os.symlink(clangxx, os.path.join(clangdir, 'clang++'))
817
818
Mike Frysinger35247af2012-11-16 18:58:06 -0500819def FileIsCrosSdkElf(elf):
820 """Determine if |elf| is an ELF that we execute in the cros_sdk
821
822 We don't need this to be perfect, just quick. It makes sure the ELF
823 is a 64bit LSB x86_64 ELF. That is the native type of cros_sdk.
824
825 Args:
826 elf: The file to check
Mike Frysinger1a736a82013-12-12 01:50:59 -0500827
Mike Frysinger35247af2012-11-16 18:58:06 -0500828 Returns:
829 True if we think |elf| is a native ELF
830 """
831 with open(elf) as f:
832 data = f.read(20)
833 # Check the magic number, EI_CLASS, EI_DATA, and e_machine.
834 return (data[0:4] == '\x7fELF' and
835 data[4] == '\x02' and
836 data[5] == '\x01' and
837 data[18] == '\x3e')
838
839
840def IsPathPackagable(ptype, path):
841 """Should the specified file be included in a toolchain package?
842
843 We only need to handle files as we'll create dirs as we need them.
844
845 Further, trim files that won't be useful:
846 - non-english translations (.mo) since it'd require env vars
847 - debug files since these are for the host compiler itself
848 - info/man pages as they're big, and docs are online, and the
849 native docs should work fine for the most part (`man gcc`)
850
851 Args:
852 ptype: A string describing the path type (i.e. 'file' or 'dir' or 'sym')
853 path: The full path to inspect
Mike Frysinger1a736a82013-12-12 01:50:59 -0500854
Mike Frysinger35247af2012-11-16 18:58:06 -0500855 Returns:
856 True if we want to include this path in the package
857 """
858 return not (ptype in ('dir',) or
859 path.startswith('/usr/lib/debug/') or
860 os.path.splitext(path)[1] == '.mo' or
861 ('/man/' in path or '/info/' in path))
862
863
864def ReadlinkRoot(path, root):
865 """Like os.readlink(), but relative to a |root|
866
867 Args:
868 path: The symlink to read
869 root: The path to use for resolving absolute symlinks
Mike Frysinger1a736a82013-12-12 01:50:59 -0500870
Mike Frysinger35247af2012-11-16 18:58:06 -0500871 Returns:
872 A fully resolved symlink path
873 """
874 while os.path.islink(root + path):
875 path = os.path.join(os.path.dirname(path), os.readlink(root + path))
876 return path
877
878
879def _GetFilesForTarget(target, root='/'):
880 """Locate all the files to package for |target|
881
882 This does not cover ELF dependencies.
883
884 Args:
885 target: The toolchain target name
886 root: The root path to pull all packages from
Mike Frysinger1a736a82013-12-12 01:50:59 -0500887
Mike Frysinger35247af2012-11-16 18:58:06 -0500888 Returns:
889 A tuple of a set of all packable paths, and a set of all paths which
890 are also native ELFs
891 """
892 paths = set()
893 elfs = set()
894
895 # Find all the files owned by the packages for this target.
896 for pkg in GetTargetPackages(target):
Mike Frysinger35247af2012-11-16 18:58:06 -0500897
Rahul Chaudhry4b803052015-05-13 15:25:56 -0700898 # Skip Go compiler from redistributable packages.
899 # The "go" executable has GOROOT=/usr/lib/go/${CTARGET} hardcoded
900 # into it. Due to this, the toolchain cannot be unpacked anywhere
901 # else and be readily useful. To enable packaging Go, we need to:
902 # -) Tweak the wrappers/environment to override GOROOT
903 # automatically based on the unpack location.
904 # -) Make sure the ELF dependency checking and wrapping logic
905 # below skips the Go toolchain executables and libraries.
906 # -) Make sure the packaging process maintains the relative
907 # timestamps of precompiled standard library packages.
908 # (see dev-lang/go ebuild for details).
909 if pkg == 'ex_go':
910 continue
911
Mike Frysinger35247af2012-11-16 18:58:06 -0500912 atom = GetPortagePackage(target, pkg)
913 cat, pn = atom.split('/')
Gilad Arnold2dab78c2015-05-21 14:43:33 -0700914 ver = GetInstalledPackageVersions(atom, root=root)[0]
Ralph Nathan03047282015-03-23 11:09:32 -0700915 logging.info('packaging %s-%s', atom, ver)
Mike Frysinger35247af2012-11-16 18:58:06 -0500916
917 # pylint: disable=E1101
918 dblink = portage.dblink(cat, pn + '-' + ver, myroot=root,
919 settings=portage.settings)
920 contents = dblink.getcontents()
921 for obj in contents:
922 ptype = contents[obj][0]
923 if not IsPathPackagable(ptype, obj):
924 continue
925
926 if ptype == 'obj':
927 # For native ELFs, we need to pull in their dependencies too.
928 if FileIsCrosSdkElf(obj):
929 elfs.add(obj)
930 paths.add(obj)
931
932 return paths, elfs
933
934
935def _BuildInitialPackageRoot(output_dir, paths, elfs, ldpaths,
Mike Frysingerd6e2df02014-11-26 02:55:04 -0500936 path_rewrite_func=lambda x: x, root='/'):
Mike Frysinger35247af2012-11-16 18:58:06 -0500937 """Link in all packable files and their runtime dependencies
938
939 This also wraps up executable ELFs with helper scripts.
940
941 Args:
942 output_dir: The output directory to store files
943 paths: All the files to include
944 elfs: All the files which are ELFs (a subset of |paths|)
945 ldpaths: A dict of static ldpath information
946 path_rewrite_func: User callback to rewrite paths in output_dir
947 root: The root path to pull all packages/files from
948 """
949 # Link in all the files.
950 sym_paths = []
951 for path in paths:
952 new_path = path_rewrite_func(path)
953 dst = output_dir + new_path
954 osutils.SafeMakedirs(os.path.dirname(dst))
955
956 # Is this a symlink which we have to rewrite or wrap?
957 # Delay wrap check until after we have created all paths.
958 src = root + path
959 if os.path.islink(src):
960 tgt = os.readlink(src)
961 if os.path.sep in tgt:
962 sym_paths.append((new_path, lddtree.normpath(ReadlinkRoot(src, root))))
963
964 # Rewrite absolute links to relative and then generate the symlink
965 # ourselves. All other symlinks can be hardlinked below.
966 if tgt[0] == '/':
967 tgt = os.path.relpath(tgt, os.path.dirname(new_path))
968 os.symlink(tgt, dst)
969 continue
970
971 os.link(src, dst)
972
973 # Now see if any of the symlinks need to be wrapped.
974 for sym, tgt in sym_paths:
975 if tgt in elfs:
976 GeneratePathWrapper(output_dir, sym, tgt)
977
978 # Locate all the dependencies for all the ELFs. Stick them all in the
979 # top level "lib" dir to make the wrapper simpler. This exact path does
980 # not matter since we execute ldso directly, and we tell the ldso the
981 # exact path to search for its libraries.
982 libdir = os.path.join(output_dir, 'lib')
983 osutils.SafeMakedirs(libdir)
984 donelibs = set()
985 for elf in elfs:
Mike Frysingerea7688e2014-07-31 22:40:33 -0400986 e = lddtree.ParseELF(elf, root=root, ldpaths=ldpaths)
Mike Frysinger35247af2012-11-16 18:58:06 -0500987 interp = e['interp']
988 if interp:
989 # Generate a wrapper if it is executable.
Mike Frysingerc2ec0902013-03-26 01:28:45 -0400990 interp = os.path.join('/lib', os.path.basename(interp))
991 lddtree.GenerateLdsoWrapper(output_dir, path_rewrite_func(elf), interp,
992 libpaths=e['rpath'] + e['runpath'])
Rahul Chaudhrya8127bb2016-07-22 15:53:17 -0700993 FixClangXXWrapper(output_dir, path_rewrite_func(elf))
Mike Frysinger35247af2012-11-16 18:58:06 -0500994
995 for lib, lib_data in e['libs'].iteritems():
996 if lib in donelibs:
997 continue
998
999 src = path = lib_data['path']
1000 if path is None:
Ralph Nathan446aee92015-03-23 14:44:56 -07001001 logging.warning('%s: could not locate %s', elf, lib)
Mike Frysinger35247af2012-11-16 18:58:06 -05001002 continue
1003 donelibs.add(lib)
1004
1005 # Needed libs are the SONAME, but that is usually a symlink, not a
1006 # real file. So link in the target rather than the symlink itself.
1007 # We have to walk all the possible symlinks (SONAME could point to a
1008 # symlink which points to a symlink), and we have to handle absolute
1009 # ourselves (since we have a "root" argument).
1010 dst = os.path.join(libdir, os.path.basename(path))
1011 src = ReadlinkRoot(src, root)
1012
1013 os.link(root + src, dst)
1014
1015
1016def _EnvdGetVar(envd, var):
1017 """Given a Gentoo env.d file, extract a var from it
1018
1019 Args:
1020 envd: The env.d file to load (may be a glob path)
1021 var: The var to extract
Mike Frysinger1a736a82013-12-12 01:50:59 -05001022
Mike Frysinger35247af2012-11-16 18:58:06 -05001023 Returns:
1024 The value of |var|
1025 """
1026 envds = glob.glob(envd)
1027 assert len(envds) == 1, '%s: should have exactly 1 env.d file' % envd
1028 envd = envds[0]
1029 return cros_build_lib.LoadKeyValueFile(envd)[var]
1030
1031
1032def _ProcessBinutilsConfig(target, output_dir):
1033 """Do what binutils-config would have done"""
1034 binpath = os.path.join('/bin', target + '-')
Mike Frysingerd4d40fd2014-11-06 17:30:57 -05001035
1036 # Locate the bin dir holding the gold linker.
1037 binutils_bin_path = os.path.join(output_dir, 'usr', toolchain.GetHostTuple(),
1038 target, 'binutils-bin')
1039 globpath = os.path.join(binutils_bin_path, '*-gold')
Mike Frysinger35247af2012-11-16 18:58:06 -05001040 srcpath = glob.glob(globpath)
Mike Frysingerd4d40fd2014-11-06 17:30:57 -05001041 if not srcpath:
1042 # Maybe this target doesn't support gold.
1043 globpath = os.path.join(binutils_bin_path, '*')
1044 srcpath = glob.glob(globpath)
1045 assert len(srcpath) == 1, ('%s: matched more than one path (but not *-gold)'
1046 % globpath)
1047 srcpath = srcpath[0]
1048 ld_path = os.path.join(srcpath, 'ld')
1049 assert os.path.exists(ld_path), '%s: linker is missing!' % ld_path
1050 ld_path = os.path.join(srcpath, 'ld.bfd')
1051 assert os.path.exists(ld_path), '%s: linker is missing!' % ld_path
1052 ld_path = os.path.join(srcpath, 'ld.gold')
1053 assert not os.path.exists(ld_path), ('%s: exists, but gold dir does not!'
1054 % ld_path)
1055
1056 # Nope, no gold support to be found.
1057 gold_supported = False
Ralph Nathan446aee92015-03-23 14:44:56 -07001058 logging.warning('%s: binutils lacks support for the gold linker', target)
Mike Frysingerd4d40fd2014-11-06 17:30:57 -05001059 else:
1060 assert len(srcpath) == 1, '%s: did not match exactly 1 path' % globpath
Mike Frysinger78b7a812014-11-26 19:45:23 -05001061 srcpath = srcpath[0]
Mike Frysingerd4d40fd2014-11-06 17:30:57 -05001062
Rahul Chaudhry4891b4d2017-03-08 10:31:27 -08001063 # Package the binutils-bin directory without the '-gold' suffix
1064 # if gold is not enabled as the default linker for this target.
1065 gold_supported = CONFIG_TARGET_SUFFIXES['binutils'].get(target) == '-gold'
1066 if not gold_supported:
1067 srcpath = srcpath[:-len('-gold')]
1068 ld_path = os.path.join(srcpath, 'ld')
1069 assert os.path.exists(ld_path), '%s: linker is missing!' % ld_path
1070
Mike Frysinger78b7a812014-11-26 19:45:23 -05001071 srcpath = srcpath[len(output_dir):]
Mike Frysinger35247af2012-11-16 18:58:06 -05001072 gccpath = os.path.join('/usr', 'libexec', 'gcc')
1073 for prog in os.listdir(output_dir + srcpath):
1074 # Skip binaries already wrapped.
1075 if not prog.endswith('.real'):
1076 GeneratePathWrapper(output_dir, binpath + prog,
1077 os.path.join(srcpath, prog))
1078 GeneratePathWrapper(output_dir, os.path.join(gccpath, prog),
1079 os.path.join(srcpath, prog))
1080
David James27ac4ae2012-12-03 23:16:15 -08001081 libpath = os.path.join('/usr', toolchain.GetHostTuple(), target, 'lib')
Mike Frysingerd4d40fd2014-11-06 17:30:57 -05001082 envd = os.path.join(output_dir, 'etc', 'env.d', 'binutils', '*')
1083 if gold_supported:
1084 envd += '-gold'
Rahul Chaudhry4891b4d2017-03-08 10:31:27 -08001085 else:
1086 # If gold is not enabled as the default linker and 2 env.d
1087 # files exist, pick the one without the '-gold' suffix.
1088 envds = sorted(glob.glob(envd))
1089 if len(envds) == 2 and envds[1] == envds[0] + '-gold':
1090 envd = envds[0]
Mike Frysinger35247af2012-11-16 18:58:06 -05001091 srcpath = _EnvdGetVar(envd, 'LIBPATH')
1092 os.symlink(os.path.relpath(srcpath, os.path.dirname(libpath)),
1093 output_dir + libpath)
1094
1095
1096def _ProcessGccConfig(target, output_dir):
1097 """Do what gcc-config would have done"""
1098 binpath = '/bin'
1099 envd = os.path.join(output_dir, 'etc', 'env.d', 'gcc', '*')
1100 srcpath = _EnvdGetVar(envd, 'GCC_PATH')
1101 for prog in os.listdir(output_dir + srcpath):
1102 # Skip binaries already wrapped.
1103 if (not prog.endswith('.real') and
1104 not prog.endswith('.elf') and
1105 prog.startswith(target)):
1106 GeneratePathWrapper(output_dir, os.path.join(binpath, prog),
1107 os.path.join(srcpath, prog))
1108 return srcpath
1109
1110
Frank Henigman179ec7c2015-02-06 03:01:09 -05001111def _ProcessSysrootWrappers(_target, output_dir, srcpath):
1112 """Remove chroot-specific things from our sysroot wrappers"""
Mike Frysinger35247af2012-11-16 18:58:06 -05001113 # Disable ccache since we know it won't work outside of chroot.
Frank Henigman179ec7c2015-02-06 03:01:09 -05001114 for sysroot_wrapper in glob.glob(os.path.join(
1115 output_dir + srcpath, 'sysroot_wrapper*')):
1116 contents = osutils.ReadFile(sysroot_wrapper).splitlines()
1117 for num in xrange(len(contents)):
1118 if '@CCACHE_DEFAULT@' in contents[num]:
Caroline Ticece9e9232017-06-02 09:38:42 -07001119 assert 'True' in contents[num]
1120 contents[num] = contents[num].replace('True', 'False')
Frank Henigman179ec7c2015-02-06 03:01:09 -05001121 break
1122 # Can't update the wrapper in place since it's a hardlink to a file in /.
1123 os.unlink(sysroot_wrapper)
1124 osutils.WriteFile(sysroot_wrapper, '\n'.join(contents))
1125 os.chmod(sysroot_wrapper, 0o755)
Mike Frysinger35247af2012-11-16 18:58:06 -05001126
1127
1128def _ProcessDistroCleanups(target, output_dir):
1129 """Clean up the tree and remove all distro-specific requirements
1130
1131 Args:
1132 target: The toolchain target name
1133 output_dir: The output directory to clean up
1134 """
1135 _ProcessBinutilsConfig(target, output_dir)
1136 gcc_path = _ProcessGccConfig(target, output_dir)
Frank Henigman179ec7c2015-02-06 03:01:09 -05001137 _ProcessSysrootWrappers(target, output_dir, gcc_path)
Mike Frysinger35247af2012-11-16 18:58:06 -05001138
1139 osutils.RmDir(os.path.join(output_dir, 'etc'))
1140
1141
1142def CreatePackagableRoot(target, output_dir, ldpaths, root='/'):
1143 """Setup a tree from the packages for the specified target
1144
1145 This populates a path with all the files from toolchain packages so that
1146 a tarball can easily be generated from the result.
1147
1148 Args:
1149 target: The target to create a packagable root from
1150 output_dir: The output directory to place all the files
1151 ldpaths: A dict of static ldpath information
1152 root: The root path to pull all packages/files from
1153 """
1154 # Find all the files owned by the packages for this target.
1155 paths, elfs = _GetFilesForTarget(target, root=root)
1156
1157 # Link in all the package's files, any ELF dependencies, and wrap any
1158 # executable ELFs with helper scripts.
1159 def MoveUsrBinToBin(path):
Han Shen699ea192016-03-02 10:42:47 -08001160 """Move /usr/bin to /bin so people can just use that toplevel dir
1161
1162 Note we do not apply this to clang - there is correlation between clang's
1163 search path for libraries / inclusion and its installation path.
1164 """
1165 if path.startswith('/usr/bin/') and path.find('clang') == -1:
1166 return path[4:]
1167 return path
Mike Frysinger35247af2012-11-16 18:58:06 -05001168 _BuildInitialPackageRoot(output_dir, paths, elfs, ldpaths,
1169 path_rewrite_func=MoveUsrBinToBin, root=root)
1170
1171 # The packages, when part of the normal distro, have helper scripts
1172 # that setup paths and such. Since we are making this standalone, we
1173 # need to preprocess all that ourselves.
1174 _ProcessDistroCleanups(target, output_dir)
1175
1176
1177def CreatePackages(targets_wanted, output_dir, root='/'):
1178 """Create redistributable cross-compiler packages for the specified targets
1179
1180 This creates toolchain packages that should be usable in conjunction with
1181 a downloaded sysroot (created elsewhere).
1182
1183 Tarballs (one per target) will be created in $PWD.
1184
1185 Args:
Don Garrett25f309a2014-03-19 14:02:12 -07001186 targets_wanted: The targets to package up.
1187 output_dir: The directory to put the packages in.
1188 root: The root path to pull all packages/files from.
Mike Frysinger35247af2012-11-16 18:58:06 -05001189 """
Ralph Nathan03047282015-03-23 11:09:32 -07001190 logging.info('Writing tarballs to %s', output_dir)
Mike Frysinger35247af2012-11-16 18:58:06 -05001191 osutils.SafeMakedirs(output_dir)
1192 ldpaths = lddtree.LoadLdpaths(root)
1193 targets = ExpandTargets(targets_wanted)
1194
David James4bc13702013-03-26 08:08:04 -07001195 with osutils.TempDir() as tempdir:
Mike Frysinger35247af2012-11-16 18:58:06 -05001196 # We have to split the root generation from the compression stages. This is
1197 # because we hardlink in all the files (to avoid overhead of reading/writing
1198 # the copies multiple times). But tar gets angry if a file's hardlink count
1199 # changes from when it starts reading a file to when it finishes.
1200 with parallel.BackgroundTaskRunner(CreatePackagableRoot) as queue:
1201 for target in targets:
1202 output_target_dir = os.path.join(tempdir, target)
1203 queue.put([target, output_target_dir, ldpaths, root])
1204
1205 # Build the tarball.
1206 with parallel.BackgroundTaskRunner(cros_build_lib.CreateTarball) as queue:
1207 for target in targets:
1208 tar_file = os.path.join(output_dir, target + '.tar.xz')
1209 queue.put([tar_file, os.path.join(tempdir, target)])
1210
1211
Mike Frysinger07534cf2017-09-12 17:40:21 -04001212def GetParser():
1213 """Return a command line parser."""
Mike Frysinger0c808452014-11-06 17:30:23 -05001214 parser = commandline.ArgumentParser(description=__doc__)
1215 parser.add_argument('-u', '--nousepkg',
1216 action='store_false', dest='usepkg', default=True,
1217 help='Use prebuilt packages if possible')
1218 parser.add_argument('-d', '--deleteold',
1219 action='store_true', dest='deleteold', default=False,
1220 help='Unmerge deprecated packages')
1221 parser.add_argument('-t', '--targets',
1222 dest='targets', default='sdk',
Gilad Arnold8195b532015-04-07 10:56:30 +03001223 help="Comma separated list of tuples. Special keywords "
Don Garrettc0c74002015-10-09 12:58:19 -07001224 "'host', 'sdk', 'boards', and 'all' are "
Gilad Arnold8195b532015-04-07 10:56:30 +03001225 "allowed. Defaults to 'sdk'.")
1226 parser.add_argument('--include-boards', default='', metavar='BOARDS',
1227 help='Comma separated list of boards whose toolchains we '
1228 'will always include. Default: none')
Mike Frysinger0c808452014-11-06 17:30:23 -05001229 parser.add_argument('--hostonly',
1230 dest='hostonly', default=False, action='store_true',
1231 help='Only setup the host toolchain. '
1232 'Useful for bootstrapping chroot')
Bertrand SIMONNETcae9d5f2015-03-09 15:58:01 -07001233 parser.add_argument('--show-board-cfg', '--show-cfg',
1234 dest='cfg_name', default=None,
Don Garrettc0c74002015-10-09 12:58:19 -07001235 help='Board to list toolchains tuples for')
Mike Frysinger0c808452014-11-06 17:30:23 -05001236 parser.add_argument('--create-packages',
1237 action='store_true', default=False,
1238 help='Build redistributable packages')
1239 parser.add_argument('--output-dir', default=os.getcwd(), type='path',
1240 help='Output directory')
1241 parser.add_argument('--reconfig', default=False, action='store_true',
1242 help='Reload crossdev config and reselect toolchains')
Gilad Arnold2dab78c2015-05-21 14:43:33 -07001243 parser.add_argument('--sysroot', type='path',
1244 help='The sysroot in which to install the toolchains')
Mike Frysinger07534cf2017-09-12 17:40:21 -04001245 return parser
Zdenek Behan508dcce2011-12-05 15:39:32 +01001246
Mike Frysinger07534cf2017-09-12 17:40:21 -04001247
1248def main(argv):
1249 parser = GetParser()
Mike Frysinger0c808452014-11-06 17:30:23 -05001250 options = parser.parse_args(argv)
1251 options.Freeze()
Zdenek Behan508dcce2011-12-05 15:39:32 +01001252
Mike Frysinger35247af2012-11-16 18:58:06 -05001253 # Figure out what we're supposed to do and reject conflicting options.
Bertrand SIMONNETcae9d5f2015-03-09 15:58:01 -07001254 if options.cfg_name and options.create_packages:
Mike Frysinger35247af2012-11-16 18:58:06 -05001255 parser.error('conflicting options: create-packages & show-board-cfg')
Mike Frysinger984d0622012-06-01 16:08:44 -04001256
Gilad Arnold8195b532015-04-07 10:56:30 +03001257 targets_wanted = set(options.targets.split(','))
1258 boards_wanted = (set(options.include_boards.split(','))
1259 if options.include_boards else set())
Mike Frysinger35247af2012-11-16 18:58:06 -05001260
Bertrand SIMONNETcae9d5f2015-03-09 15:58:01 -07001261 if options.cfg_name:
1262 ShowConfig(options.cfg_name)
Mike Frysinger35247af2012-11-16 18:58:06 -05001263 elif options.create_packages:
1264 cros_build_lib.AssertInsideChroot()
1265 Crossdev.Load(False)
Gilad Arnold8195b532015-04-07 10:56:30 +03001266 CreatePackages(targets_wanted, options.output_dir)
Mike Frysinger35247af2012-11-16 18:58:06 -05001267 else:
1268 cros_build_lib.AssertInsideChroot()
1269 # This has to be always run as root.
1270 if os.geteuid() != 0:
1271 cros_build_lib.Die('this script must be run as root')
1272
1273 Crossdev.Load(options.reconfig)
Gilad Arnold2dab78c2015-05-21 14:43:33 -07001274 root = options.sysroot or '/'
Mike Frysinger35247af2012-11-16 18:58:06 -05001275 UpdateToolchains(options.usepkg, options.deleteold, options.hostonly,
Gilad Arnold8195b532015-04-07 10:56:30 +03001276 options.reconfig, targets_wanted, boards_wanted,
Don Garrettc0c74002015-10-09 12:58:19 -07001277 root=root)
Mike Frysinger35247af2012-11-16 18:58:06 -05001278 Crossdev.Save()
1279
1280 return 0