blob: 7b5bd761cbaecfa4e9615f4ee4b5f18653e97c6a [file] [log] [blame]
Zdenek Behan508dcce2011-12-05 15:39:32 +01001#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""This script manages the installed toolchains in the chroot.
7"""
8
9import copy
Zdenek Behan7e33b4e2012-03-12 17:00:56 +010010import errno
Zdenek Behan508dcce2011-12-05 15:39:32 +010011import optparse
12import os
13import sys
14
Brian Harring503f3ab2012-03-09 21:39:41 -080015from chromite.buildbot import constants
16from chromite.lib import cros_build_lib
Zdenek Behan508dcce2011-12-05 15:39:32 +010017
18# Some sanity checks first.
19if not cros_build_lib.IsInsideChroot():
20 print '%s: This needs to be run inside the chroot' % sys.argv[0]
21 sys.exit(1)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +010022# This has to be always ran as root.
23if not os.getuid() == 0:
24 print "This script must be run as root!"
25 sys.exit(1)
Zdenek Behan508dcce2011-12-05 15:39:32 +010026# Only import portage after we've checked that we're inside the chroot.
27# Outside may not have portage, in which case the above may not happen.
28import portage
29
30
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010031EMERGE_CMD = os.path.join(os.path.dirname(__file__),
32 '../bin', 'parallel_emerge')
Zdenek Behan508dcce2011-12-05 15:39:32 +010033PACKAGE_STABLE = '[stable]'
34PACKAGE_NONE = '[none]'
35SRC_ROOT = os.path.realpath(constants.SOURCE_ROOT)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010036# NOTE: gdb is only built using --ex-gdb through crossdev.
37CROSSDEV_PACKAGES = ['gcc', 'libc', 'binutils', 'kernel']
38TOOLCHAIN_PACKAGES = CROSSDEV_PACKAGES + ['gdb']
39
40
41CHROMIUMOS_OVERLAY = '/usr/local/portage/chromiumos'
42STABLE_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 'binutils' : '2.21-r4',
52}
53TARGET_VERSION_MAP = {
54 'arm-none-eabi' : {
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010055 'kernel' : PACKAGE_NONE,
Zdenek Behan508dcce2011-12-05 15:39:32 +010056 'gdb' : PACKAGE_NONE,
57 },
58 'host' : {
59 'binutils' : '2.21.1',
60 'gdb' : PACKAGE_NONE,
61 },
62}
63# Overrides for {gcc,binutils}-config, pick a package with particular suffix.
64CONFIG_TARGET_SUFFIXES = {
65 'binutils' : {
66 'i686-pc-linux-gnu' : '-gold',
67 'x86_64-cros-linux-gnu' : '-gold',
68 },
69}
Zdenek Behan508dcce2011-12-05 15:39:32 +010070# Global per-run cache that will be filled ondemand in by GetPackageMap()
71# function as needed.
72target_version_map = {
73}
74
75
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010076# Global variable cache. It has to be a descendant of 'object', rather than
77# instance thereof, because attributes cannot be set on 'object' instances.
78class VariableCache(object):
79 pass
80VAR_CACHE = VariableCache()
81
82
Zdenek Behan508dcce2011-12-05 15:39:32 +010083def GetPackageMap(target):
84 """Compiles a package map for the given target from the constants.
85
86 Uses a cache in target_version_map, that is dynamically filled in as needed,
87 since here everything is static data and the structuring is for ease of
88 configurability only.
89
90 args:
91 target - the target for which to return a version map
92
93 returns a map between packages and desired versions in internal format
94 (using the PACKAGE_* constants)
95 """
96 if target in target_version_map:
97 return target_version_map[target]
98
99 # Start from copy of the global defaults.
100 result = copy.copy(DEFAULT_TARGET_VERSION_MAP)
101
102 for pkg in TOOLCHAIN_PACKAGES:
103 # prefer any specific overrides
104 if pkg in TARGET_VERSION_MAP.get(target, {}):
105 result[pkg] = TARGET_VERSION_MAP[target][pkg]
106 else:
107 # finally, if not already set, set a sane default
108 result.setdefault(pkg, DEFAULT_VERSION)
109 target_version_map[target] = result
110 return result
111
112
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100113def GetHostTuple():
114 """Returns compiler tuple for the host system.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100115
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100116 Caches the result, because the command can be fairly expensive, and never
117 changes throughout a single run.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100118 """
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100119 CACHE_ATTR = '_host_tuple'
Zdenek Behan508dcce2011-12-05 15:39:32 +0100120
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100121 val = getattr(VAR_CACHE, CACHE_ATTR, None)
122 if val is None:
123 val = cros_build_lib.RunCommand(['portageq', 'envvar', 'CHOST'],
124 print_cmd=False, redirect_stdout=True).output
125 setattr(VAR_CACHE, CACHE_ATTR, val)
126 return val
127
128
129def GetCrossdevConf(target):
130 """Returns a map of crossdev provided variables about a tuple."""
131 CACHE_ATTR = '_target_tuple_map'
132
133 val = getattr(VAR_CACHE, CACHE_ATTR, {})
134 if not target in val:
135 # Find out the crossdev tuple.
136 target_tuple = target
137 if target == 'host':
138 target_tuple = GetHostTuple()
139 # Catch output of crossdev.
140 out = cros_build_lib.RunCommand(['crossdev', '--show-target-cfg',
141 '--ex-gdb', target_tuple],
142 print_cmd=False, redirect_stdout=True).output.splitlines()
143 # List of tuples split at the first '=', converted into dict.
144 val[target] = dict([x.split('=', 1) for x in out])
145 setattr(VAR_CACHE, CACHE_ATTR, {})
146 return val[target]
147
148
149# Portage helper functions:
150def GetPortagePackage(target, package):
151 """Returns a package name for the given target."""
152 conf = GetCrossdevConf(target)
153 # Portage category:
Zdenek Behan508dcce2011-12-05 15:39:32 +0100154 if target == 'host':
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100155 category = conf[package + '_category']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100156 else:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100157 category = conf['category']
158 # Portage package:
159 pn = conf[package + '_pn']
160 # Final package name:
161 assert(category)
162 assert(pn)
163 return '%s/%s' % (category, pn)
164
165
166def GetPortageKeyword(target):
167 """Returns a portage friendly keyword for a given target."""
168 return GetCrossdevConf(target)['arch']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100169
170
171def GetHostTarget():
172 """Returns a string for the host target tuple."""
173 return portage.settings['CHOST']
174
175
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100176def IsPackageDisabled(target, package):
177 """Returns if the given package is not used for the target."""
178 return GetDesiredPackageVersions(target, package) == [PACKAGE_NONE]
179
Zdenek Behan508dcce2011-12-05 15:39:32 +0100180# Tree interface functions. They help with retrieving data about the current
181# state of the tree:
182def GetAllTargets():
183 """Get the complete list of targets.
184
185 returns the list of cross targets for the current tree
186 """
187 cmd = ['cros_overlay_list', '--all_boards']
188 overlays = cros_build_lib.RunCommand(cmd, print_cmd=False,
189 redirect_stdout=True).output.splitlines()
190 targets = set()
191 for overlay in overlays:
192 config = os.path.join(overlay, 'toolchain.conf')
193 if os.path.exists(config):
194 with open(config) as config_file:
195 lines = config_file.read().splitlines()
196 for line in lines:
197 # Remove empty lines and commented lines.
198 if line and not line.startswith('#'):
199 targets.add(line)
200
201 # Remove the host target as that is not a cross-target. Replace with 'host'.
202 targets.remove(GetHostTarget())
203 targets.add('host')
204 return targets
205
206
207def GetInstalledPackageVersions(target, package):
208 """Extracts the list of current versions of a target, package pair.
209
210 args:
211 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
212
213 returns the list of versions of the package currently installed.
214 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100215 versions = []
216 # This is the package name in terms of portage.
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100217 atom = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100218 for pkg in portage.db['/']['vartree'].dbapi.match(atom):
219 version = portage.versions.cpv_getversion(pkg)
220 versions.append(version)
221 return versions
222
223
Zdenek Behan508dcce2011-12-05 15:39:32 +0100224def GetStablePackageVersion(target, package):
225 """Extracts the current stable version for a given package.
226
227 args:
228 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
229
230 returns a string containing the latest version.
231 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100232 keyword = GetPortageKeyword(target)
233 extra_env = {'ACCEPT_KEYWORDS' : '-* ' + keyword}
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100234 atom = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100235 cpv = cros_build_lib.RunCommand(['portageq', 'best_visible', '/', atom],
236 print_cmd=False, redirect_stdout=True,
237 extra_env=extra_env).output.splitlines()[0]
238 return portage.versions.cpv_getversion(cpv)
239
240
241def VersionListToNumeric(target, package, versions):
242 """Resolves keywords in a given version list for a particular package.
243
244 Resolving means replacing PACKAGE_STABLE with the actual number.
245
246 args:
247 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
248 versions - list of versions to resolve
249
250 returns list of purely numeric versions equivalent to argument
251 """
252 resolved = []
253 for version in versions:
254 if version == PACKAGE_STABLE:
255 resolved.append(GetStablePackageVersion(target, package))
256 elif version != PACKAGE_NONE:
257 resolved.append(version)
258 return resolved
259
260
261def GetDesiredPackageVersions(target, package):
262 """Produces the list of desired versions for each target, package pair.
263
264 The first version in the list is implicitly treated as primary, ie.
265 the version that will be initialized by crossdev and selected.
266
267 If the version is PACKAGE_STABLE, it really means the current version which
268 is emerged by using the package atom with no particular version key.
269 Since crossdev unmasks all packages by default, this will actually
270 mean 'unstable' in most cases.
271
272 args:
273 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
274
275 returns a list composed of either a version string, PACKAGE_STABLE
276 """
277 packagemap = GetPackageMap(target)
278
279 versions = []
280 if package in packagemap:
281 versions.append(packagemap[package])
282
283 return versions
284
285
286def TargetIsInitialized(target):
287 """Verifies if the given list of targets has been correctly initialized.
288
289 This determines whether we have to call crossdev while emerging
290 toolchain packages or can do it using emerge. Emerge is naturally
291 preferred, because all packages can be updated in a single pass.
292
293 args:
294 targets - list of individual cross targets which are checked
295
296 returns True if target is completely initialized
297 returns False otherwise
298 """
299 # Check if packages for the given target all have a proper version.
300 try:
301 for package in TOOLCHAIN_PACKAGES:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100302 # Do we even want this package && is it initialized?
303 if not IsPackageDisabled(target, package) and \
304 not GetInstalledPackageVersions(target, package):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100305 return False
306 return True
307 except cros_build_lib.RunCommandError:
308 # Fails - The target has likely never been initialized before.
309 return False
310
311
312def RemovePackageMask(target):
313 """Removes a package.mask file for the given platform.
314
315 The pre-existing package.mask files can mess with the keywords.
316
317 args:
318 target - the target for which to remove the file
319 """
320 maskfile = os.path.join('/etc/portage/package.mask', 'cross-' + target)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100321 try:
322 os.unlink(maskfile)
323 except EnvironmentError as e:
324 if e.errno != errno.ENOENT:
325 raise
Zdenek Behan508dcce2011-12-05 15:39:32 +0100326
327
328def CreatePackageMask(target, masks):
329 """[Re]creates a package.mask file for the given platform.
330
331 args:
332 target - the given target on which to operate
333 masks - a map of package : version,
334 where version is the highest permissible version (mask >)
335 """
336 maskfile = os.path.join('/etc/portage/package.mask', 'cross-' + target)
337 assert not os.path.exists(maskfile)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100338 cros_build_lib.SafeMakedirs(os.path.dirname(maskfile))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100339
340 with open(maskfile, 'w') as f:
341 for pkg, m in masks.items():
342 f.write('>%s-%s\n' % (pkg, m))
343
344
345def CreatePackageKeywords(target):
346 """[Re]create a package.keywords file for the platform.
347
348 This sets all package.keywords files to unmask all stable/testing packages.
349 TODO: Note that this approach should be deprecated and is only done for
350 compatibility reasons. In the future, we'd like to stop using keywords
351 altogether, and keep just stable unmasked.
352
353 args:
354 target - target for which to recreate package.keywords
355 """
356 maskfile = os.path.join('/etc/portage/package.keywords', 'cross-' + target)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100357 try:
358 os.unlink(maskfile)
359 except EnvironmentError as e:
360 if e.errno != errno.ENOENT:
361 raise
362 cros_build_lib.SafeMakedirs(os.path.dirname(maskfile))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100363
364 keyword = GetPortageKeyword(target)
365
366 with open(maskfile, 'w') as f:
367 for pkg in TOOLCHAIN_PACKAGES:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100368 if IsPackageDisabled(target, pkg):
369 continue
370 f.write('%s %s ~%s\n' %
371 (GetPortagePackage(target, pkg), keyword, keyword))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100372
373
374# Main functions performing the actual update steps.
375def InitializeCrossdevTargets(targets, usepkg):
376 """Calls crossdev to initialize a cross target.
377 args:
378 targets - the list of targets to initialize using crossdev
379 usepkg - copies the commandline opts
380 """
381 print 'The following targets need to be re-initialized:'
382 print targets
Zdenek Behan508dcce2011-12-05 15:39:32 +0100383
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100384 extra_env = { 'FEATURES' : 'splitdebug' }
Zdenek Behan508dcce2011-12-05 15:39:32 +0100385 for target in targets:
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100386 cmd = ['crossdev', '--show-fail-log',
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100387 '-t', target]
Zdenek Behan508dcce2011-12-05 15:39:32 +0100388 # Pick stable by default, and override as necessary.
389 cmd.extend(['-P', '--oneshot'])
390 if usepkg:
391 cmd.extend(['-P', '--getbinpkg',
392 '-P', '--usepkgonly',
393 '--without-headers'])
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100394
395 cmd.extend(['--overlays', '%s %s' % (CHROMIUMOS_OVERLAY, STABLE_OVERLAY)])
396 cmd.extend(['--ov-output', CROSSDEV_OVERLAY])
Zdenek Behan508dcce2011-12-05 15:39:32 +0100397
398 # HACK(zbehan): arm-none-eabi uses newlib which doesn't like headers-only.
399 if target == 'arm-none-eabi':
400 cmd.append('--without-headers')
401
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100402 if not IsPackageDisabled(target, 'gdb'):
403 cmd.append('--ex-gdb')
404
405 for pkg in CROSSDEV_PACKAGES:
406 if IsPackageDisabled(target, pkg):
407 continue
Zdenek Behan508dcce2011-12-05 15:39:32 +0100408 # The first of the desired versions is the "primary" one.
409 version = GetDesiredPackageVersions(target, pkg)[0]
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100410 cmd.extend(['--%s' % pkg, version])
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100411 cros_build_lib.RunCommand(cmd, extra_env=extra_env)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100412
413
414def UpdateTargets(targets, usepkg):
415 """Determines which packages need update/unmerge and defers to portage.
416
417 args:
418 targets - the list of targets to update
419 usepkg - copies the commandline option
420 """
421 # TODO(zbehan): This process is rather complex due to package.* handling.
422 # With some semantic changes over the original setup_board functionality,
423 # it can be considerably cleaned up.
424 mergemap = {}
425
426 # For each target, we do two things. Figure out the list of updates,
427 # and figure out the appropriate keywords/masks. Crossdev will initialize
428 # these, but they need to be regenerated on every update.
429 print 'Determining required toolchain updates...'
430 for target in targets:
431 # Record the highest needed version for each target, for masking purposes.
432 RemovePackageMask(target)
433 CreatePackageKeywords(target)
434 packagemasks = {}
435 for package in TOOLCHAIN_PACKAGES:
436 # Portage name for the package
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100437 if IsPackageDisabled(target, package):
438 continue
439 pkg = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100440 current = GetInstalledPackageVersions(target, package)
441 desired = GetDesiredPackageVersions(target, package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100442 desired_num = VersionListToNumeric(target, package, desired)
443 mergemap[pkg] = set(desired_num).difference(current)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100444
445 # Pick the highest version for mask.
446 packagemasks[pkg] = portage.versions.best(desired_num)
447
448 CreatePackageMask(target, packagemasks)
449
450 packages = []
451 for pkg in mergemap:
452 for ver in mergemap[pkg]:
453 if ver == PACKAGE_STABLE:
454 packages.append(pkg)
455 elif ver != PACKAGE_NONE:
456 packages.append('=%s-%s' % (pkg, ver))
457
458 if not packages:
459 print 'Nothing to update!'
460 return
461
462 print 'Updating packages:'
463 print packages
464
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100465 cmd = [EMERGE_CMD, '--oneshot', '--update']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100466 if usepkg:
467 cmd.extend(['--getbinpkg', '--usepkgonly'])
468
469 cmd.extend(packages)
470 cros_build_lib.RunCommand(cmd)
471
472
473def CleanTargets(targets):
474 """Unmerges old packages that are assumed unnecessary."""
475 unmergemap = {}
476 for target in targets:
477 for package in TOOLCHAIN_PACKAGES:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100478 if IsPackageDisabled(target, package):
479 continue
480 pkg = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100481 current = GetInstalledPackageVersions(target, package)
482 desired = GetDesiredPackageVersions(target, package)
483 desired_num = VersionListToNumeric(target, package, desired)
484 assert set(desired).issubset(set(desired))
485 unmergemap[pkg] = set(current).difference(desired_num)
486
487 # Cleaning doesn't care about consistency and rebuilding package.* files.
488 packages = []
489 for pkg, vers in unmergemap.iteritems():
490 packages.extend('=%s-%s' % (pkg, ver) for ver in vers if ver != '9999')
491
492 if packages:
493 print 'Cleaning packages:'
494 print packages
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100495 cmd = [EMERGE_CMD, '--unmerge']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100496 cmd.extend(packages)
497 cros_build_lib.RunCommand(cmd)
498 else:
499 print 'Nothing to clean!'
500
501
502def SelectActiveToolchains(targets, suffixes):
503 """Runs gcc-config and binutils-config to select the desired.
504
505 args:
506 targets - the targets to select
507 """
508 for package in ['gcc', 'binutils']:
509 for target in targets:
510 # Pick the first version in the numbered list as the selected one.
511 desired = GetDesiredPackageVersions(target, package)
512 desired_num = VersionListToNumeric(target, package, desired)
513 desired = desired_num[0]
514 # *-config does not play revisions, strip them, keep just PV.
515 desired = portage.versions.pkgsplit('%s-%s' % (package, desired))[1]
516
517 if target == 'host':
518 # *-config is the only tool treating host identically (by tuple).
519 target = GetHostTarget()
520
521 # And finally, attach target to it.
522 desired = '%s-%s' % (target, desired)
523
524 # Target specific hacks
525 if package in suffixes:
526 if target in suffixes[package]:
527 desired += suffixes[package][target]
528
529 cmd = [ package + '-config', '-c', target ]
530 current = cros_build_lib.RunCommand(cmd, print_cmd=False,
531 redirect_stdout=True).output.splitlines()[0]
532 # Do not gcc-config when the current is live or nothing needs to be done.
533 if current != desired and current != '9999':
534 cmd = [ package + '-config', desired ]
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100535 cros_build_lib.RunCommand(cmd, print_cmd=False)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100536
537
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100538def UpdateToolchains(usepkg, deleteold, hostonly, targets_wanted):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100539 """Performs all steps to create a synchronized toolchain enviroment.
540
541 args:
542 arguments correspond to the given commandline flags
543 """
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100544 targets = set()
545 if not hostonly:
546 # For hostonly, we can skip most of the below logic, much of which won't
547 # work on bare systems where this is useful.
548 alltargets = GetAllTargets()
549 nonexistant = []
550 if targets_wanted == set(['all']):
551 targets = set(alltargets)
552 else:
553 targets = set(targets_wanted)
554 # Verify user input.
555 for target in targets_wanted:
556 if target not in alltargets:
557 nonexistant.append(target)
558 if nonexistant:
559 raise Exception("Invalid targets: " + ','.join(nonexistant))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100560
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100561 # First check and initialize all cross targets that need to be.
562 crossdev_targets = \
563 [t for t in targets if not TargetIsInitialized(t)]
564 if crossdev_targets:
565 InitializeCrossdevTargets(crossdev_targets, usepkg)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100566
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100567 # We want host updated.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100568 targets.add('host')
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100569
570 # Now update all packages.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100571 UpdateTargets(targets, usepkg)
572 SelectActiveToolchains(targets, CONFIG_TARGET_SUFFIXES)
573
574 if deleteold:
575 CleanTargets(targets)
576
577
Brian Harring30675052012-02-29 12:18:22 -0800578def main(argv):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100579 usage = """usage: %prog [options]
580
581 The script installs and updates the toolchains in your chroot.
582 """
583 parser = optparse.OptionParser(usage)
584 parser.add_option('-u', '--nousepkg',
585 action='store_false', dest='usepkg', default=True,
586 help=('Use prebuilt packages if possible.'))
587 parser.add_option('-d', '--deleteold',
588 action='store_true', dest='deleteold', default=False,
589 help=('Unmerge deprecated packages.'))
590 parser.add_option('-t', '--targets',
591 dest='targets', default='all',
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100592 help=('Comma separated list of tuples. '
593 'Special keyword \'host\' is allowed. Default: all.'))
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100594 parser.add_option('', '--hostonly',
595 dest='hostonly', default=False, action='store_true',
596 help=('Only setup the host toolchain. '
597 'Useful for bootstrapping chroot.'))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100598
Brian Harring30675052012-02-29 12:18:22 -0800599 (options, _remaining_arguments) = parser.parse_args(argv)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100600
601 targets = set(options.targets.split(','))
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100602 UpdateToolchains(options.usepkg, options.deleteold, options.hostonly, targets)