blob: fcbec8102b7ea6f3fdd3fbe9381417e1c0e4c931 [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)
22# Only import portage after we've checked that we're inside the chroot.
23# Outside may not have portage, in which case the above may not happen.
24import portage
25
26
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010027EMERGE_CMD = os.path.join(os.path.dirname(__file__),
28 '../bin', 'parallel_emerge')
Zdenek Behan508dcce2011-12-05 15:39:32 +010029PACKAGE_STABLE = '[stable]'
30PACKAGE_NONE = '[none]'
31SRC_ROOT = os.path.realpath(constants.SOURCE_ROOT)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010032# NOTE: gdb is only built using --ex-gdb through crossdev.
33CROSSDEV_PACKAGES = ['gcc', 'libc', 'binutils', 'kernel']
34TOOLCHAIN_PACKAGES = CROSSDEV_PACKAGES + ['gdb']
35
36
37CHROMIUMOS_OVERLAY = '/usr/local/portage/chromiumos'
38STABLE_OVERLAY = '/usr/local/portage/stable'
39CROSSDEV_OVERLAY = '/usr/local/portage/crossdev'
Zdenek Behan508dcce2011-12-05 15:39:32 +010040
41
42# TODO: The versions are stored here very much like in setup_board.
43# The goal for future is to differentiate these using a config file.
44# This is done essentially by messing with GetDesiredPackageVersions()
45DEFAULT_VERSION = PACKAGE_STABLE
46DEFAULT_TARGET_VERSION_MAP = {
Zdenek Behan508dcce2011-12-05 15:39:32 +010047 'binutils' : '2.21-r4',
48}
49TARGET_VERSION_MAP = {
50 'arm-none-eabi' : {
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010051 'kernel' : PACKAGE_NONE,
Zdenek Behan508dcce2011-12-05 15:39:32 +010052 'gdb' : PACKAGE_NONE,
53 },
54 'host' : {
55 'binutils' : '2.21.1',
56 'gdb' : PACKAGE_NONE,
57 },
58}
59# Overrides for {gcc,binutils}-config, pick a package with particular suffix.
60CONFIG_TARGET_SUFFIXES = {
61 'binutils' : {
62 'i686-pc-linux-gnu' : '-gold',
63 'x86_64-cros-linux-gnu' : '-gold',
64 },
65}
Zdenek Behan508dcce2011-12-05 15:39:32 +010066# Global per-run cache that will be filled ondemand in by GetPackageMap()
67# function as needed.
68target_version_map = {
69}
70
71
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010072# Global variable cache. It has to be a descendant of 'object', rather than
73# instance thereof, because attributes cannot be set on 'object' instances.
74class VariableCache(object):
75 pass
76VAR_CACHE = VariableCache()
77
78
Zdenek Behan508dcce2011-12-05 15:39:32 +010079def GetPackageMap(target):
80 """Compiles a package map for the given target from the constants.
81
82 Uses a cache in target_version_map, that is dynamically filled in as needed,
83 since here everything is static data and the structuring is for ease of
84 configurability only.
85
86 args:
87 target - the target for which to return a version map
88
89 returns a map between packages and desired versions in internal format
90 (using the PACKAGE_* constants)
91 """
92 if target in target_version_map:
93 return target_version_map[target]
94
95 # Start from copy of the global defaults.
96 result = copy.copy(DEFAULT_TARGET_VERSION_MAP)
97
98 for pkg in TOOLCHAIN_PACKAGES:
99 # prefer any specific overrides
100 if pkg in TARGET_VERSION_MAP.get(target, {}):
101 result[pkg] = TARGET_VERSION_MAP[target][pkg]
102 else:
103 # finally, if not already set, set a sane default
104 result.setdefault(pkg, DEFAULT_VERSION)
105 target_version_map[target] = result
106 return result
107
108
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100109def GetHostTuple():
110 """Returns compiler tuple for the host system.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100111
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100112 Caches the result, because the command can be fairly expensive, and never
113 changes throughout a single run.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100114 """
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100115 CACHE_ATTR = '_host_tuple'
Zdenek Behan508dcce2011-12-05 15:39:32 +0100116
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100117 val = getattr(VAR_CACHE, CACHE_ATTR, None)
118 if val is None:
119 val = cros_build_lib.RunCommand(['portageq', 'envvar', 'CHOST'],
120 print_cmd=False, redirect_stdout=True).output
121 setattr(VAR_CACHE, CACHE_ATTR, val)
122 return val
123
124
125def GetCrossdevConf(target):
126 """Returns a map of crossdev provided variables about a tuple."""
127 CACHE_ATTR = '_target_tuple_map'
128
129 val = getattr(VAR_CACHE, CACHE_ATTR, {})
130 if not target in val:
131 # Find out the crossdev tuple.
132 target_tuple = target
133 if target == 'host':
134 target_tuple = GetHostTuple()
135 # Catch output of crossdev.
136 out = cros_build_lib.RunCommand(['crossdev', '--show-target-cfg',
137 '--ex-gdb', target_tuple],
138 print_cmd=False, redirect_stdout=True).output.splitlines()
139 # List of tuples split at the first '=', converted into dict.
140 val[target] = dict([x.split('=', 1) for x in out])
141 setattr(VAR_CACHE, CACHE_ATTR, {})
142 return val[target]
143
144
145# Portage helper functions:
146def GetPortagePackage(target, package):
147 """Returns a package name for the given target."""
148 conf = GetCrossdevConf(target)
149 # Portage category:
Zdenek Behan508dcce2011-12-05 15:39:32 +0100150 if target == 'host':
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100151 category = conf[package + '_category']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100152 else:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100153 category = conf['category']
154 # Portage package:
155 pn = conf[package + '_pn']
156 # Final package name:
157 assert(category)
158 assert(pn)
159 return '%s/%s' % (category, pn)
160
161
162def GetPortageKeyword(target):
163 """Returns a portage friendly keyword for a given target."""
164 return GetCrossdevConf(target)['arch']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100165
166
167def GetHostTarget():
168 """Returns a string for the host target tuple."""
169 return portage.settings['CHOST']
170
171
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100172def IsPackageDisabled(target, package):
173 """Returns if the given package is not used for the target."""
174 return GetDesiredPackageVersions(target, package) == [PACKAGE_NONE]
175
Zdenek Behan508dcce2011-12-05 15:39:32 +0100176# Tree interface functions. They help with retrieving data about the current
177# state of the tree:
178def GetAllTargets():
179 """Get the complete list of targets.
180
181 returns the list of cross targets for the current tree
182 """
183 cmd = ['cros_overlay_list', '--all_boards']
184 overlays = cros_build_lib.RunCommand(cmd, print_cmd=False,
185 redirect_stdout=True).output.splitlines()
186 targets = set()
187 for overlay in overlays:
188 config = os.path.join(overlay, 'toolchain.conf')
189 if os.path.exists(config):
190 with open(config) as config_file:
191 lines = config_file.read().splitlines()
192 for line in lines:
193 # Remove empty lines and commented lines.
194 if line and not line.startswith('#'):
195 targets.add(line)
196
197 # Remove the host target as that is not a cross-target. Replace with 'host'.
198 targets.remove(GetHostTarget())
199 targets.add('host')
200 return targets
201
202
203def GetInstalledPackageVersions(target, package):
204 """Extracts the list of current versions of a target, package pair.
205
206 args:
207 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
208
209 returns the list of versions of the package currently installed.
210 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100211 versions = []
212 # This is the package name in terms of portage.
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100213 atom = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100214 for pkg in portage.db['/']['vartree'].dbapi.match(atom):
215 version = portage.versions.cpv_getversion(pkg)
216 versions.append(version)
217 return versions
218
219
Zdenek Behan508dcce2011-12-05 15:39:32 +0100220def GetStablePackageVersion(target, package):
221 """Extracts the current stable version for a given package.
222
223 args:
224 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
225
226 returns a string containing the latest version.
227 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100228 keyword = GetPortageKeyword(target)
229 extra_env = {'ACCEPT_KEYWORDS' : '-* ' + keyword}
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100230 atom = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100231 cpv = cros_build_lib.RunCommand(['portageq', 'best_visible', '/', atom],
232 print_cmd=False, redirect_stdout=True,
233 extra_env=extra_env).output.splitlines()[0]
234 return portage.versions.cpv_getversion(cpv)
235
236
237def VersionListToNumeric(target, package, versions):
238 """Resolves keywords in a given version list for a particular package.
239
240 Resolving means replacing PACKAGE_STABLE with the actual number.
241
242 args:
243 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
244 versions - list of versions to resolve
245
246 returns list of purely numeric versions equivalent to argument
247 """
248 resolved = []
249 for version in versions:
250 if version == PACKAGE_STABLE:
251 resolved.append(GetStablePackageVersion(target, package))
252 elif version != PACKAGE_NONE:
253 resolved.append(version)
254 return resolved
255
256
257def GetDesiredPackageVersions(target, package):
258 """Produces the list of desired versions for each target, package pair.
259
260 The first version in the list is implicitly treated as primary, ie.
261 the version that will be initialized by crossdev and selected.
262
263 If the version is PACKAGE_STABLE, it really means the current version which
264 is emerged by using the package atom with no particular version key.
265 Since crossdev unmasks all packages by default, this will actually
266 mean 'unstable' in most cases.
267
268 args:
269 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
270
271 returns a list composed of either a version string, PACKAGE_STABLE
272 """
273 packagemap = GetPackageMap(target)
274
275 versions = []
276 if package in packagemap:
277 versions.append(packagemap[package])
278
279 return versions
280
281
282def TargetIsInitialized(target):
283 """Verifies if the given list of targets has been correctly initialized.
284
285 This determines whether we have to call crossdev while emerging
286 toolchain packages or can do it using emerge. Emerge is naturally
287 preferred, because all packages can be updated in a single pass.
288
289 args:
290 targets - list of individual cross targets which are checked
291
292 returns True if target is completely initialized
293 returns False otherwise
294 """
295 # Check if packages for the given target all have a proper version.
296 try:
297 for package in TOOLCHAIN_PACKAGES:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100298 # Do we even want this package && is it initialized?
299 if not IsPackageDisabled(target, package) and \
300 not GetInstalledPackageVersions(target, package):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100301 return False
302 return True
303 except cros_build_lib.RunCommandError:
304 # Fails - The target has likely never been initialized before.
305 return False
306
307
308def RemovePackageMask(target):
309 """Removes a package.mask file for the given platform.
310
311 The pre-existing package.mask files can mess with the keywords.
312
313 args:
314 target - the target for which to remove the file
315 """
316 maskfile = os.path.join('/etc/portage/package.mask', 'cross-' + target)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100317 try:
318 os.unlink(maskfile)
319 except EnvironmentError as e:
320 if e.errno != errno.ENOENT:
321 raise
Zdenek Behan508dcce2011-12-05 15:39:32 +0100322
323
324def CreatePackageMask(target, masks):
325 """[Re]creates a package.mask file for the given platform.
326
327 args:
328 target - the given target on which to operate
329 masks - a map of package : version,
330 where version is the highest permissible version (mask >)
331 """
332 maskfile = os.path.join('/etc/portage/package.mask', 'cross-' + target)
333 assert not os.path.exists(maskfile)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100334 cros_build_lib.SafeMakedirs(os.path.dirname(maskfile))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100335
336 with open(maskfile, 'w') as f:
337 for pkg, m in masks.items():
338 f.write('>%s-%s\n' % (pkg, m))
339
340
341def CreatePackageKeywords(target):
342 """[Re]create a package.keywords file for the platform.
343
344 This sets all package.keywords files to unmask all stable/testing packages.
345 TODO: Note that this approach should be deprecated and is only done for
346 compatibility reasons. In the future, we'd like to stop using keywords
347 altogether, and keep just stable unmasked.
348
349 args:
350 target - target for which to recreate package.keywords
351 """
352 maskfile = os.path.join('/etc/portage/package.keywords', 'cross-' + target)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100353 try:
354 os.unlink(maskfile)
355 except EnvironmentError as e:
356 if e.errno != errno.ENOENT:
357 raise
358 cros_build_lib.SafeMakedirs(os.path.dirname(maskfile))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100359
360 keyword = GetPortageKeyword(target)
361
362 with open(maskfile, 'w') as f:
363 for pkg in TOOLCHAIN_PACKAGES:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100364 if IsPackageDisabled(target, pkg):
365 continue
366 f.write('%s %s ~%s\n' %
367 (GetPortagePackage(target, pkg), keyword, keyword))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100368
369
370# Main functions performing the actual update steps.
371def InitializeCrossdevTargets(targets, usepkg):
372 """Calls crossdev to initialize a cross target.
373 args:
374 targets - the list of targets to initialize using crossdev
375 usepkg - copies the commandline opts
376 """
377 print 'The following targets need to be re-initialized:'
378 print targets
Zdenek Behan508dcce2011-12-05 15:39:32 +0100379
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100380 extra_env = { 'FEATURES' : 'splitdebug' }
Zdenek Behan508dcce2011-12-05 15:39:32 +0100381 for target in targets:
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100382 cmd = ['crossdev', '--show-fail-log',
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100383 '-t', target]
Zdenek Behan508dcce2011-12-05 15:39:32 +0100384 # Pick stable by default, and override as necessary.
385 cmd.extend(['-P', '--oneshot'])
386 if usepkg:
387 cmd.extend(['-P', '--getbinpkg',
388 '-P', '--usepkgonly',
389 '--without-headers'])
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100390
391 cmd.extend(['--overlays', '%s %s' % (CHROMIUMOS_OVERLAY, STABLE_OVERLAY)])
392 cmd.extend(['--ov-output', CROSSDEV_OVERLAY])
Zdenek Behan508dcce2011-12-05 15:39:32 +0100393
394 # HACK(zbehan): arm-none-eabi uses newlib which doesn't like headers-only.
395 if target == 'arm-none-eabi':
396 cmd.append('--without-headers')
397
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100398 if not IsPackageDisabled(target, 'gdb'):
399 cmd.append('--ex-gdb')
400
401 for pkg in CROSSDEV_PACKAGES:
402 if IsPackageDisabled(target, pkg):
403 continue
Zdenek Behan508dcce2011-12-05 15:39:32 +0100404 # The first of the desired versions is the "primary" one.
405 version = GetDesiredPackageVersions(target, pkg)[0]
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100406 cmd.extend(['--%s' % pkg, version])
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100407 cros_build_lib.RunCommand(cmd, extra_env=extra_env)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100408
409
410def UpdateTargets(targets, usepkg):
411 """Determines which packages need update/unmerge and defers to portage.
412
413 args:
414 targets - the list of targets to update
415 usepkg - copies the commandline option
416 """
417 # TODO(zbehan): This process is rather complex due to package.* handling.
418 # With some semantic changes over the original setup_board functionality,
419 # it can be considerably cleaned up.
420 mergemap = {}
421
422 # For each target, we do two things. Figure out the list of updates,
423 # and figure out the appropriate keywords/masks. Crossdev will initialize
424 # these, but they need to be regenerated on every update.
425 print 'Determining required toolchain updates...'
426 for target in targets:
427 # Record the highest needed version for each target, for masking purposes.
428 RemovePackageMask(target)
429 CreatePackageKeywords(target)
430 packagemasks = {}
431 for package in TOOLCHAIN_PACKAGES:
432 # Portage name for the package
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100433 if IsPackageDisabled(target, package):
434 continue
435 pkg = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100436 current = GetInstalledPackageVersions(target, package)
437 desired = GetDesiredPackageVersions(target, package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100438 desired_num = VersionListToNumeric(target, package, desired)
439 mergemap[pkg] = set(desired_num).difference(current)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100440
441 # Pick the highest version for mask.
442 packagemasks[pkg] = portage.versions.best(desired_num)
443
444 CreatePackageMask(target, packagemasks)
445
446 packages = []
447 for pkg in mergemap:
448 for ver in mergemap[pkg]:
449 if ver == PACKAGE_STABLE:
450 packages.append(pkg)
451 elif ver != PACKAGE_NONE:
452 packages.append('=%s-%s' % (pkg, ver))
453
454 if not packages:
455 print 'Nothing to update!'
456 return
457
458 print 'Updating packages:'
459 print packages
460
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100461 cmd = [EMERGE_CMD, '--oneshot', '--update']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100462 if usepkg:
463 cmd.extend(['--getbinpkg', '--usepkgonly'])
464
465 cmd.extend(packages)
466 cros_build_lib.RunCommand(cmd)
467
468
469def CleanTargets(targets):
470 """Unmerges old packages that are assumed unnecessary."""
471 unmergemap = {}
472 for target in targets:
473 for package in TOOLCHAIN_PACKAGES:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100474 if IsPackageDisabled(target, package):
475 continue
476 pkg = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100477 current = GetInstalledPackageVersions(target, package)
478 desired = GetDesiredPackageVersions(target, package)
479 desired_num = VersionListToNumeric(target, package, desired)
480 assert set(desired).issubset(set(desired))
481 unmergemap[pkg] = set(current).difference(desired_num)
482
483 # Cleaning doesn't care about consistency and rebuilding package.* files.
484 packages = []
485 for pkg, vers in unmergemap.iteritems():
486 packages.extend('=%s-%s' % (pkg, ver) for ver in vers if ver != '9999')
487
488 if packages:
489 print 'Cleaning packages:'
490 print packages
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100491 cmd = [EMERGE_CMD, '--unmerge']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100492 cmd.extend(packages)
493 cros_build_lib.RunCommand(cmd)
494 else:
495 print 'Nothing to clean!'
496
497
498def SelectActiveToolchains(targets, suffixes):
499 """Runs gcc-config and binutils-config to select the desired.
500
501 args:
502 targets - the targets to select
503 """
504 for package in ['gcc', 'binutils']:
505 for target in targets:
506 # Pick the first version in the numbered list as the selected one.
507 desired = GetDesiredPackageVersions(target, package)
508 desired_num = VersionListToNumeric(target, package, desired)
509 desired = desired_num[0]
510 # *-config does not play revisions, strip them, keep just PV.
511 desired = portage.versions.pkgsplit('%s-%s' % (package, desired))[1]
512
513 if target == 'host':
514 # *-config is the only tool treating host identically (by tuple).
515 target = GetHostTarget()
516
517 # And finally, attach target to it.
518 desired = '%s-%s' % (target, desired)
519
520 # Target specific hacks
521 if package in suffixes:
522 if target in suffixes[package]:
523 desired += suffixes[package][target]
524
525 cmd = [ package + '-config', '-c', target ]
526 current = cros_build_lib.RunCommand(cmd, print_cmd=False,
527 redirect_stdout=True).output.splitlines()[0]
528 # Do not gcc-config when the current is live or nothing needs to be done.
529 if current != desired and current != '9999':
530 cmd = [ package + '-config', desired ]
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100531 cros_build_lib.RunCommand(cmd, print_cmd=False)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100532
533
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100534def UpdateToolchains(usepkg, deleteold, hostonly, targets_wanted):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100535 """Performs all steps to create a synchronized toolchain enviroment.
536
537 args:
538 arguments correspond to the given commandline flags
539 """
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100540 targets = set()
541 if not hostonly:
542 # For hostonly, we can skip most of the below logic, much of which won't
543 # work on bare systems where this is useful.
544 alltargets = GetAllTargets()
545 nonexistant = []
546 if targets_wanted == set(['all']):
547 targets = set(alltargets)
548 else:
549 targets = set(targets_wanted)
550 # Verify user input.
551 for target in targets_wanted:
552 if target not in alltargets:
553 nonexistant.append(target)
554 if nonexistant:
555 raise Exception("Invalid targets: " + ','.join(nonexistant))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100556
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100557 # First check and initialize all cross targets that need to be.
558 crossdev_targets = \
559 [t for t in targets if not TargetIsInitialized(t)]
560 if crossdev_targets:
561 InitializeCrossdevTargets(crossdev_targets, usepkg)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100562
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100563 # We want host updated.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100564 targets.add('host')
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100565
566 # Now update all packages.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100567 UpdateTargets(targets, usepkg)
568 SelectActiveToolchains(targets, CONFIG_TARGET_SUFFIXES)
569
570 if deleteold:
571 CleanTargets(targets)
572
573
Brian Harring30675052012-02-29 12:18:22 -0800574def main(argv):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100575 usage = """usage: %prog [options]
576
577 The script installs and updates the toolchains in your chroot.
578 """
579 parser = optparse.OptionParser(usage)
580 parser.add_option('-u', '--nousepkg',
581 action='store_false', dest='usepkg', default=True,
582 help=('Use prebuilt packages if possible.'))
583 parser.add_option('-d', '--deleteold',
584 action='store_true', dest='deleteold', default=False,
585 help=('Unmerge deprecated packages.'))
586 parser.add_option('-t', '--targets',
587 dest='targets', default='all',
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100588 help=('Comma separated list of tuples. '
589 'Special keyword \'host\' is allowed. Default: all.'))
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100590 parser.add_option('', '--hostonly',
591 dest='hostonly', default=False, action='store_true',
592 help=('Only setup the host toolchain. '
593 'Useful for bootstrapping chroot.'))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100594
Brian Harring30675052012-02-29 12:18:22 -0800595 (options, _remaining_arguments) = parser.parse_args(argv)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100596
Mike Frysingerb9a28fe2012-03-21 11:35:42 -0400597 # This has to be always ran as root.
598 if not os.getuid() == 0:
599 print "%s: This script must be run as root!" % sys.argv[0]
600 sys.exit(1)
601
Zdenek Behan508dcce2011-12-05 15:39:32 +0100602 targets = set(options.targets.split(','))
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100603 UpdateToolchains(options.usepkg, options.deleteold, options.hostonly, targets)