blob: 48023291973a8003b1daada117c88edff85482dc [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
33CHROMIUMOS_OVERLAY = '/usr/local/portage/chromiumos'
34STABLE_OVERLAY = '/usr/local/portage/stable'
35CROSSDEV_OVERLAY = '/usr/local/portage/crossdev'
Zdenek Behan508dcce2011-12-05 15:39:32 +010036
37
38# TODO: The versions are stored here very much like in setup_board.
39# The goal for future is to differentiate these using a config file.
40# This is done essentially by messing with GetDesiredPackageVersions()
41DEFAULT_VERSION = PACKAGE_STABLE
42DEFAULT_TARGET_VERSION_MAP = {
Zdenek Behan508dcce2011-12-05 15:39:32 +010043}
44TARGET_VERSION_MAP = {
Zdenek Behan508dcce2011-12-05 15:39:32 +010045 'host' : {
46 'binutils' : '2.21.1',
47 'gdb' : PACKAGE_NONE,
48 },
49}
50# Overrides for {gcc,binutils}-config, pick a package with particular suffix.
51CONFIG_TARGET_SUFFIXES = {
52 'binutils' : {
53 'i686-pc-linux-gnu' : '-gold',
54 'x86_64-cros-linux-gnu' : '-gold',
55 },
56}
Zdenek Behan508dcce2011-12-05 15:39:32 +010057# Global per-run cache that will be filled ondemand in by GetPackageMap()
58# function as needed.
59target_version_map = {
60}
61
62
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010063# Global variable cache. It has to be a descendant of 'object', rather than
64# instance thereof, because attributes cannot be set on 'object' instances.
65class VariableCache(object):
66 pass
67VAR_CACHE = VariableCache()
68
69
Zdenek Behan508dcce2011-12-05 15:39:32 +010070def GetPackageMap(target):
71 """Compiles a package map for the given target from the constants.
72
73 Uses a cache in target_version_map, that is dynamically filled in as needed,
74 since here everything is static data and the structuring is for ease of
75 configurability only.
76
77 args:
78 target - the target for which to return a version map
79
80 returns a map between packages and desired versions in internal format
81 (using the PACKAGE_* constants)
82 """
83 if target in target_version_map:
84 return target_version_map[target]
85
86 # Start from copy of the global defaults.
87 result = copy.copy(DEFAULT_TARGET_VERSION_MAP)
88
Zdenek Behanf4d18a02012-03-22 15:45:05 +010089 for pkg in GetTargetPackages(target):
Zdenek Behan508dcce2011-12-05 15:39:32 +010090 # prefer any specific overrides
91 if pkg in TARGET_VERSION_MAP.get(target, {}):
92 result[pkg] = TARGET_VERSION_MAP[target][pkg]
93 else:
94 # finally, if not already set, set a sane default
95 result.setdefault(pkg, DEFAULT_VERSION)
96 target_version_map[target] = result
97 return result
98
99
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100100def GetHostTuple():
101 """Returns compiler tuple for the host system.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100102
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100103 Caches the result, because the command can be fairly expensive, and never
104 changes throughout a single run.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100105 """
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100106 CACHE_ATTR = '_host_tuple'
Zdenek Behan508dcce2011-12-05 15:39:32 +0100107
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100108 val = getattr(VAR_CACHE, CACHE_ATTR, None)
109 if val is None:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100110 val = portage.settings['CHOST']
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100111 setattr(VAR_CACHE, CACHE_ATTR, val)
112 return val
113
114
115def GetCrossdevConf(target):
116 """Returns a map of crossdev provided variables about a tuple."""
117 CACHE_ATTR = '_target_tuple_map'
118
119 val = getattr(VAR_CACHE, CACHE_ATTR, {})
120 if not target in val:
121 # Find out the crossdev tuple.
122 target_tuple = target
123 if target == 'host':
124 target_tuple = GetHostTuple()
125 # Catch output of crossdev.
126 out = cros_build_lib.RunCommand(['crossdev', '--show-target-cfg',
127 '--ex-gdb', target_tuple],
128 print_cmd=False, redirect_stdout=True).output.splitlines()
129 # List of tuples split at the first '=', converted into dict.
130 val[target] = dict([x.split('=', 1) for x in out])
131 setattr(VAR_CACHE, CACHE_ATTR, {})
132 return val[target]
133
134
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100135def GetTargetPackages(target):
136 """Returns a list of packages for a given target."""
137 conf = GetCrossdevConf(target)
138 # Undesired packages are denoted by empty ${pkg}_pn variable.
139 return [x for x in conf['crosspkgs'].strip("'").split() if conf[x+'_pn']]
140
141
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100142# Portage helper functions:
143def GetPortagePackage(target, package):
144 """Returns a package name for the given target."""
145 conf = GetCrossdevConf(target)
146 # Portage category:
Zdenek Behan508dcce2011-12-05 15:39:32 +0100147 if target == 'host':
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100148 category = conf[package + '_category']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100149 else:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100150 category = conf['category']
151 # Portage package:
152 pn = conf[package + '_pn']
153 # Final package name:
154 assert(category)
155 assert(pn)
156 return '%s/%s' % (category, pn)
157
158
159def GetPortageKeyword(target):
160 """Returns a portage friendly keyword for a given target."""
161 return GetCrossdevConf(target)['arch']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100162
163
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100164def IsPackageDisabled(target, package):
165 """Returns if the given package is not used for the target."""
166 return GetDesiredPackageVersions(target, package) == [PACKAGE_NONE]
167
Zdenek Behan508dcce2011-12-05 15:39:32 +0100168# Tree interface functions. They help with retrieving data about the current
169# state of the tree:
170def GetAllTargets():
171 """Get the complete list of targets.
172
173 returns the list of cross targets for the current tree
174 """
175 cmd = ['cros_overlay_list', '--all_boards']
176 overlays = cros_build_lib.RunCommand(cmd, print_cmd=False,
177 redirect_stdout=True).output.splitlines()
178 targets = set()
179 for overlay in overlays:
180 config = os.path.join(overlay, 'toolchain.conf')
181 if os.path.exists(config):
182 with open(config) as config_file:
183 lines = config_file.read().splitlines()
184 for line in lines:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100185 line = line.split('#', 1)[0]
186 targets.update(line.split())
Zdenek Behan508dcce2011-12-05 15:39:32 +0100187
188 # Remove the host target as that is not a cross-target. Replace with 'host'.
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100189 targets.discard(GetHostTuple())
Zdenek Behan508dcce2011-12-05 15:39:32 +0100190 return targets
191
192
193def GetInstalledPackageVersions(target, package):
194 """Extracts the list of current versions of a target, package pair.
195
196 args:
197 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
198
199 returns the list of versions of the package currently installed.
200 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100201 versions = []
202 # This is the package name in terms of portage.
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100203 atom = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100204 for pkg in portage.db['/']['vartree'].dbapi.match(atom):
205 version = portage.versions.cpv_getversion(pkg)
206 versions.append(version)
207 return versions
208
209
Zdenek Behan508dcce2011-12-05 15:39:32 +0100210def GetStablePackageVersion(target, package):
211 """Extracts the current stable version for a given package.
212
213 args:
214 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
215
216 returns a string containing the latest version.
217 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100218 keyword = GetPortageKeyword(target)
219 extra_env = {'ACCEPT_KEYWORDS' : '-* ' + keyword}
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100220 atom = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100221 cpv = cros_build_lib.RunCommand(['portageq', 'best_visible', '/', atom],
222 print_cmd=False, redirect_stdout=True,
223 extra_env=extra_env).output.splitlines()[0]
224 return portage.versions.cpv_getversion(cpv)
225
226
227def VersionListToNumeric(target, package, versions):
228 """Resolves keywords in a given version list for a particular package.
229
230 Resolving means replacing PACKAGE_STABLE with the actual number.
231
232 args:
233 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
234 versions - list of versions to resolve
235
236 returns list of purely numeric versions equivalent to argument
237 """
238 resolved = []
239 for version in versions:
240 if version == PACKAGE_STABLE:
241 resolved.append(GetStablePackageVersion(target, package))
242 elif version != PACKAGE_NONE:
243 resolved.append(version)
244 return resolved
245
246
247def GetDesiredPackageVersions(target, package):
248 """Produces the list of desired versions for each target, package pair.
249
250 The first version in the list is implicitly treated as primary, ie.
251 the version that will be initialized by crossdev and selected.
252
253 If the version is PACKAGE_STABLE, it really means the current version which
254 is emerged by using the package atom with no particular version key.
255 Since crossdev unmasks all packages by default, this will actually
256 mean 'unstable' in most cases.
257
258 args:
259 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
260
261 returns a list composed of either a version string, PACKAGE_STABLE
262 """
263 packagemap = GetPackageMap(target)
264
265 versions = []
266 if package in packagemap:
267 versions.append(packagemap[package])
268
269 return versions
270
271
272def TargetIsInitialized(target):
273 """Verifies if the given list of targets has been correctly initialized.
274
275 This determines whether we have to call crossdev while emerging
276 toolchain packages or can do it using emerge. Emerge is naturally
277 preferred, because all packages can be updated in a single pass.
278
279 args:
280 targets - list of individual cross targets which are checked
281
282 returns True if target is completely initialized
283 returns False otherwise
284 """
285 # Check if packages for the given target all have a proper version.
286 try:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100287 for package in GetTargetPackages(target):
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100288 # Do we even want this package && is it initialized?
289 if not IsPackageDisabled(target, package) and \
290 not GetInstalledPackageVersions(target, package):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100291 return False
292 return True
293 except cros_build_lib.RunCommandError:
294 # Fails - The target has likely never been initialized before.
295 return False
296
297
298def RemovePackageMask(target):
299 """Removes a package.mask file for the given platform.
300
301 The pre-existing package.mask files can mess with the keywords.
302
303 args:
304 target - the target for which to remove the file
305 """
306 maskfile = os.path.join('/etc/portage/package.mask', 'cross-' + target)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100307 try:
308 os.unlink(maskfile)
309 except EnvironmentError as e:
310 if e.errno != errno.ENOENT:
311 raise
Zdenek Behan508dcce2011-12-05 15:39:32 +0100312
313
314def CreatePackageMask(target, masks):
315 """[Re]creates a package.mask file for the given platform.
316
317 args:
318 target - the given target on which to operate
319 masks - a map of package : version,
320 where version is the highest permissible version (mask >)
321 """
322 maskfile = os.path.join('/etc/portage/package.mask', 'cross-' + target)
323 assert not os.path.exists(maskfile)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100324 cros_build_lib.SafeMakedirs(os.path.dirname(maskfile))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100325
326 with open(maskfile, 'w') as f:
327 for pkg, m in masks.items():
328 f.write('>%s-%s\n' % (pkg, m))
329
330
331def CreatePackageKeywords(target):
332 """[Re]create a package.keywords file for the platform.
333
334 This sets all package.keywords files to unmask all stable/testing packages.
335 TODO: Note that this approach should be deprecated and is only done for
336 compatibility reasons. In the future, we'd like to stop using keywords
337 altogether, and keep just stable unmasked.
338
339 args:
340 target - target for which to recreate package.keywords
341 """
342 maskfile = os.path.join('/etc/portage/package.keywords', 'cross-' + target)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100343 try:
344 os.unlink(maskfile)
345 except EnvironmentError as e:
346 if e.errno != errno.ENOENT:
347 raise
348 cros_build_lib.SafeMakedirs(os.path.dirname(maskfile))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100349
350 keyword = GetPortageKeyword(target)
351
352 with open(maskfile, 'w') as f:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100353 for pkg in GetTargetPackages(target):
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100354 if IsPackageDisabled(target, pkg):
355 continue
356 f.write('%s %s ~%s\n' %
357 (GetPortagePackage(target, pkg), keyword, keyword))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100358
359
360# Main functions performing the actual update steps.
361def InitializeCrossdevTargets(targets, usepkg):
362 """Calls crossdev to initialize a cross target.
363 args:
364 targets - the list of targets to initialize using crossdev
365 usepkg - copies the commandline opts
366 """
367 print 'The following targets need to be re-initialized:'
368 print targets
Zdenek Behan508dcce2011-12-05 15:39:32 +0100369
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100370 extra_env = { 'FEATURES' : 'splitdebug' }
Zdenek Behan508dcce2011-12-05 15:39:32 +0100371 for target in targets:
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100372 cmd = ['crossdev', '--show-fail-log',
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100373 '-t', target]
Zdenek Behan508dcce2011-12-05 15:39:32 +0100374 # Pick stable by default, and override as necessary.
375 cmd.extend(['-P', '--oneshot'])
376 if usepkg:
377 cmd.extend(['-P', '--getbinpkg',
378 '-P', '--usepkgonly',
379 '--without-headers'])
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100380
381 cmd.extend(['--overlays', '%s %s' % (CHROMIUMOS_OVERLAY, STABLE_OVERLAY)])
382 cmd.extend(['--ov-output', CROSSDEV_OVERLAY])
Zdenek Behan508dcce2011-12-05 15:39:32 +0100383
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100384 for pkg in GetTargetPackages(target):
385 if pkg == 'gdb':
386 # Gdb does not have selectable versions.
387 cmd.append('--ex-gdb')
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100388 continue
Zdenek Behan508dcce2011-12-05 15:39:32 +0100389 # The first of the desired versions is the "primary" one.
390 version = GetDesiredPackageVersions(target, pkg)[0]
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100391 cmd.extend(['--%s' % pkg, version])
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100392 cros_build_lib.RunCommand(cmd, extra_env=extra_env)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100393
394
395def UpdateTargets(targets, usepkg):
396 """Determines which packages need update/unmerge and defers to portage.
397
398 args:
399 targets - the list of targets to update
400 usepkg - copies the commandline option
401 """
402 # TODO(zbehan): This process is rather complex due to package.* handling.
403 # With some semantic changes over the original setup_board functionality,
404 # it can be considerably cleaned up.
405 mergemap = {}
406
407 # For each target, we do two things. Figure out the list of updates,
408 # and figure out the appropriate keywords/masks. Crossdev will initialize
409 # these, but they need to be regenerated on every update.
410 print 'Determining required toolchain updates...'
411 for target in targets:
412 # Record the highest needed version for each target, for masking purposes.
413 RemovePackageMask(target)
414 CreatePackageKeywords(target)
415 packagemasks = {}
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100416 for package in GetTargetPackages(target):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100417 # Portage name for the package
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100418 if IsPackageDisabled(target, package):
419 continue
420 pkg = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100421 current = GetInstalledPackageVersions(target, package)
422 desired = GetDesiredPackageVersions(target, package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100423 desired_num = VersionListToNumeric(target, package, desired)
424 mergemap[pkg] = set(desired_num).difference(current)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100425
426 # Pick the highest version for mask.
427 packagemasks[pkg] = portage.versions.best(desired_num)
428
429 CreatePackageMask(target, packagemasks)
430
431 packages = []
432 for pkg in mergemap:
433 for ver in mergemap[pkg]:
Zdenek Behan677b6d82012-04-11 05:31:47 +0200434 if ver != PACKAGE_NONE:
435 # Be a little more permissive for usepkg, the binaries may not exist.
436 packages.append('%s%s-%s' % ('<=' if usepkg else '=', pkg, ver))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100437
438 if not packages:
439 print 'Nothing to update!'
440 return
441
442 print 'Updating packages:'
443 print packages
444
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100445 cmd = [EMERGE_CMD, '--oneshot', '--update']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100446 if usepkg:
447 cmd.extend(['--getbinpkg', '--usepkgonly'])
448
449 cmd.extend(packages)
450 cros_build_lib.RunCommand(cmd)
451
452
453def CleanTargets(targets):
454 """Unmerges old packages that are assumed unnecessary."""
455 unmergemap = {}
456 for target in targets:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100457 for package in GetTargetPackages(target):
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100458 if IsPackageDisabled(target, package):
459 continue
460 pkg = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100461 current = GetInstalledPackageVersions(target, package)
462 desired = GetDesiredPackageVersions(target, package)
463 desired_num = VersionListToNumeric(target, package, desired)
464 assert set(desired).issubset(set(desired))
465 unmergemap[pkg] = set(current).difference(desired_num)
466
467 # Cleaning doesn't care about consistency and rebuilding package.* files.
468 packages = []
469 for pkg, vers in unmergemap.iteritems():
470 packages.extend('=%s-%s' % (pkg, ver) for ver in vers if ver != '9999')
471
472 if packages:
473 print 'Cleaning packages:'
474 print packages
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100475 cmd = [EMERGE_CMD, '--unmerge']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100476 cmd.extend(packages)
477 cros_build_lib.RunCommand(cmd)
478 else:
479 print 'Nothing to clean!'
480
481
482def SelectActiveToolchains(targets, suffixes):
483 """Runs gcc-config and binutils-config to select the desired.
484
485 args:
486 targets - the targets to select
487 """
488 for package in ['gcc', 'binutils']:
489 for target in targets:
490 # Pick the first version in the numbered list as the selected one.
491 desired = GetDesiredPackageVersions(target, package)
492 desired_num = VersionListToNumeric(target, package, desired)
493 desired = desired_num[0]
494 # *-config does not play revisions, strip them, keep just PV.
495 desired = portage.versions.pkgsplit('%s-%s' % (package, desired))[1]
496
497 if target == 'host':
498 # *-config is the only tool treating host identically (by tuple).
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100499 target = GetHostTuple()
Zdenek Behan508dcce2011-12-05 15:39:32 +0100500
501 # And finally, attach target to it.
502 desired = '%s-%s' % (target, desired)
503
504 # Target specific hacks
505 if package in suffixes:
506 if target in suffixes[package]:
507 desired += suffixes[package][target]
508
509 cmd = [ package + '-config', '-c', target ]
510 current = cros_build_lib.RunCommand(cmd, print_cmd=False,
511 redirect_stdout=True).output.splitlines()[0]
512 # Do not gcc-config when the current is live or nothing needs to be done.
513 if current != desired and current != '9999':
514 cmd = [ package + '-config', desired ]
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100515 cros_build_lib.RunCommand(cmd, print_cmd=False)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100516
517
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100518def UpdateToolchains(usepkg, deleteold, hostonly, targets_wanted):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100519 """Performs all steps to create a synchronized toolchain enviroment.
520
521 args:
522 arguments correspond to the given commandline flags
523 """
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100524 targets = set()
525 if not hostonly:
526 # For hostonly, we can skip most of the below logic, much of which won't
527 # work on bare systems where this is useful.
528 alltargets = GetAllTargets()
529 nonexistant = []
530 if targets_wanted == set(['all']):
531 targets = set(alltargets)
532 else:
533 targets = set(targets_wanted)
534 # Verify user input.
535 for target in targets_wanted:
536 if target not in alltargets:
537 nonexistant.append(target)
538 if nonexistant:
539 raise Exception("Invalid targets: " + ','.join(nonexistant))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100540
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100541 # First check and initialize all cross targets that need to be.
542 crossdev_targets = \
543 [t for t in targets if not TargetIsInitialized(t)]
544 if crossdev_targets:
545 InitializeCrossdevTargets(crossdev_targets, usepkg)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100546
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100547 # We want host updated.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100548 targets.add('host')
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100549
550 # Now update all packages.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100551 UpdateTargets(targets, usepkg)
552 SelectActiveToolchains(targets, CONFIG_TARGET_SUFFIXES)
553
554 if deleteold:
555 CleanTargets(targets)
556
557
Brian Harring30675052012-02-29 12:18:22 -0800558def main(argv):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100559 usage = """usage: %prog [options]
560
561 The script installs and updates the toolchains in your chroot.
562 """
563 parser = optparse.OptionParser(usage)
564 parser.add_option('-u', '--nousepkg',
565 action='store_false', dest='usepkg', default=True,
566 help=('Use prebuilt packages if possible.'))
567 parser.add_option('-d', '--deleteold',
568 action='store_true', dest='deleteold', default=False,
569 help=('Unmerge deprecated packages.'))
570 parser.add_option('-t', '--targets',
571 dest='targets', default='all',
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100572 help=('Comma separated list of tuples. '
573 'Special keyword \'host\' is allowed. Default: all.'))
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100574 parser.add_option('', '--hostonly',
575 dest='hostonly', default=False, action='store_true',
576 help=('Only setup the host toolchain. '
577 'Useful for bootstrapping chroot.'))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100578
Brian Harring30675052012-02-29 12:18:22 -0800579 (options, _remaining_arguments) = parser.parse_args(argv)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100580
Mike Frysingerb9a28fe2012-03-21 11:35:42 -0400581 # This has to be always ran as root.
582 if not os.getuid() == 0:
583 print "%s: This script must be run as root!" % sys.argv[0]
584 sys.exit(1)
585
Zdenek Behan508dcce2011-12-05 15:39:32 +0100586 targets = set(options.targets.split(','))
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100587 UpdateToolchains(options.usepkg, options.deleteold, options.hostonly, targets)