blob: 4b6a6580b5237bcbdda4e6b91c5c30138e2db100 [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 Behan331f9822012-04-13 05:02:36 +020027EMERGE_CMD = os.path.join(
28 constants.SOURCE_ROOT, 'chromite/bin/parallel_emerge')
29CROS_OVERLAY_LIST_CMD = os.path.join(
30 constants.SOURCE_ROOT, 'src/platform/dev/host/cros_overlay_list')
Zdenek Behan508dcce2011-12-05 15:39:32 +010031PACKAGE_STABLE = '[stable]'
32PACKAGE_NONE = '[none]'
33SRC_ROOT = os.path.realpath(constants.SOURCE_ROOT)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010034
35CHROMIUMOS_OVERLAY = '/usr/local/portage/chromiumos'
36STABLE_OVERLAY = '/usr/local/portage/stable'
37CROSSDEV_OVERLAY = '/usr/local/portage/crossdev'
Zdenek Behan508dcce2011-12-05 15:39:32 +010038
39
40# TODO: The versions are stored here very much like in setup_board.
41# The goal for future is to differentiate these using a config file.
42# This is done essentially by messing with GetDesiredPackageVersions()
43DEFAULT_VERSION = PACKAGE_STABLE
44DEFAULT_TARGET_VERSION_MAP = {
Zdenek Behan508dcce2011-12-05 15:39:32 +010045}
46TARGET_VERSION_MAP = {
Zdenek Behan508dcce2011-12-05 15:39:32 +010047 'host' : {
48 'binutils' : '2.21.1',
49 'gdb' : PACKAGE_NONE,
50 },
51}
52# Overrides for {gcc,binutils}-config, pick a package with particular suffix.
53CONFIG_TARGET_SUFFIXES = {
54 'binutils' : {
55 'i686-pc-linux-gnu' : '-gold',
56 'x86_64-cros-linux-gnu' : '-gold',
57 },
58}
Zdenek Behan508dcce2011-12-05 15:39:32 +010059# Global per-run cache that will be filled ondemand in by GetPackageMap()
60# function as needed.
61target_version_map = {
62}
63
64
Zdenek Behan4eb6fd22012-03-12 17:00:56 +010065# Global variable cache. It has to be a descendant of 'object', rather than
66# instance thereof, because attributes cannot be set on 'object' instances.
67class VariableCache(object):
68 pass
69VAR_CACHE = VariableCache()
70
71
Zdenek Behan508dcce2011-12-05 15:39:32 +010072def GetPackageMap(target):
73 """Compiles a package map for the given target from the constants.
74
75 Uses a cache in target_version_map, that is dynamically filled in as needed,
76 since here everything is static data and the structuring is for ease of
77 configurability only.
78
79 args:
80 target - the target for which to return a version map
81
82 returns a map between packages and desired versions in internal format
83 (using the PACKAGE_* constants)
84 """
85 if target in target_version_map:
86 return target_version_map[target]
87
88 # Start from copy of the global defaults.
89 result = copy.copy(DEFAULT_TARGET_VERSION_MAP)
90
Zdenek Behanf4d18a02012-03-22 15:45:05 +010091 for pkg in GetTargetPackages(target):
Zdenek Behan508dcce2011-12-05 15:39:32 +010092 # prefer any specific overrides
93 if pkg in TARGET_VERSION_MAP.get(target, {}):
94 result[pkg] = TARGET_VERSION_MAP[target][pkg]
95 else:
96 # finally, if not already set, set a sane default
97 result.setdefault(pkg, DEFAULT_VERSION)
98 target_version_map[target] = result
99 return result
100
101
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100102def GetHostTuple():
103 """Returns compiler tuple for the host system.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100104
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100105 Caches the result, because the command can be fairly expensive, and never
106 changes throughout a single run.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100107 """
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100108 CACHE_ATTR = '_host_tuple'
Zdenek Behan508dcce2011-12-05 15:39:32 +0100109
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100110 val = getattr(VAR_CACHE, CACHE_ATTR, None)
111 if val is None:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100112 val = portage.settings['CHOST']
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100113 setattr(VAR_CACHE, CACHE_ATTR, val)
114 return val
115
116
117def GetCrossdevConf(target):
118 """Returns a map of crossdev provided variables about a tuple."""
119 CACHE_ATTR = '_target_tuple_map'
120
121 val = getattr(VAR_CACHE, CACHE_ATTR, {})
122 if not target in val:
123 # Find out the crossdev tuple.
124 target_tuple = target
125 if target == 'host':
126 target_tuple = GetHostTuple()
127 # Catch output of crossdev.
128 out = cros_build_lib.RunCommand(['crossdev', '--show-target-cfg',
129 '--ex-gdb', target_tuple],
130 print_cmd=False, redirect_stdout=True).output.splitlines()
131 # List of tuples split at the first '=', converted into dict.
132 val[target] = dict([x.split('=', 1) for x in out])
133 setattr(VAR_CACHE, CACHE_ATTR, {})
134 return val[target]
135
136
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100137def GetTargetPackages(target):
138 """Returns a list of packages for a given target."""
139 conf = GetCrossdevConf(target)
140 # Undesired packages are denoted by empty ${pkg}_pn variable.
141 return [x for x in conf['crosspkgs'].strip("'").split() if conf[x+'_pn']]
142
143
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100144# Portage helper functions:
145def GetPortagePackage(target, package):
146 """Returns a package name for the given target."""
147 conf = GetCrossdevConf(target)
148 # Portage category:
Zdenek Behan508dcce2011-12-05 15:39:32 +0100149 if target == 'host':
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100150 category = conf[package + '_category']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100151 else:
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100152 category = conf['category']
153 # Portage package:
154 pn = conf[package + '_pn']
155 # Final package name:
156 assert(category)
157 assert(pn)
158 return '%s/%s' % (category, pn)
159
160
161def GetPortageKeyword(target):
162 """Returns a portage friendly keyword for a given target."""
163 return GetCrossdevConf(target)['arch']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100164
165
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100166def IsPackageDisabled(target, package):
167 """Returns if the given package is not used for the target."""
168 return GetDesiredPackageVersions(target, package) == [PACKAGE_NONE]
169
Zdenek Behan508dcce2011-12-05 15:39:32 +0100170# Tree interface functions. They help with retrieving data about the current
171# state of the tree:
172def GetAllTargets():
173 """Get the complete list of targets.
174
175 returns the list of cross targets for the current tree
176 """
Zdenek Behan331f9822012-04-13 05:02:36 +0200177 cmd = [CROS_OVERLAY_LIST_CMD, '--all_boards']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100178 overlays = cros_build_lib.RunCommand(cmd, print_cmd=False,
179 redirect_stdout=True).output.splitlines()
180 targets = set()
181 for overlay in overlays:
182 config = os.path.join(overlay, 'toolchain.conf')
183 if os.path.exists(config):
184 with open(config) as config_file:
185 lines = config_file.read().splitlines()
186 for line in lines:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100187 line = line.split('#', 1)[0]
188 targets.update(line.split())
Zdenek Behan508dcce2011-12-05 15:39:32 +0100189
190 # Remove the host target as that is not a cross-target. Replace with 'host'.
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100191 targets.discard(GetHostTuple())
Zdenek Behan508dcce2011-12-05 15:39:32 +0100192 return targets
193
194
195def GetInstalledPackageVersions(target, package):
196 """Extracts the list of current versions of a target, package pair.
197
198 args:
199 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
200
201 returns the list of versions of the package currently installed.
202 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100203 versions = []
204 # This is the package name in terms of portage.
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100205 atom = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100206 for pkg in portage.db['/']['vartree'].dbapi.match(atom):
207 version = portage.versions.cpv_getversion(pkg)
208 versions.append(version)
209 return versions
210
211
Zdenek Behan508dcce2011-12-05 15:39:32 +0100212def GetStablePackageVersion(target, package):
213 """Extracts the current stable version for a given package.
214
215 args:
216 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
217
218 returns a string containing the latest version.
219 """
Zdenek Behan508dcce2011-12-05 15:39:32 +0100220 keyword = GetPortageKeyword(target)
221 extra_env = {'ACCEPT_KEYWORDS' : '-* ' + keyword}
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100222 atom = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100223 cpv = cros_build_lib.RunCommand(['portageq', 'best_visible', '/', atom],
224 print_cmd=False, redirect_stdout=True,
225 extra_env=extra_env).output.splitlines()[0]
226 return portage.versions.cpv_getversion(cpv)
227
228
229def VersionListToNumeric(target, package, versions):
230 """Resolves keywords in a given version list for a particular package.
231
232 Resolving means replacing PACKAGE_STABLE with the actual number.
233
234 args:
235 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
236 versions - list of versions to resolve
237
238 returns list of purely numeric versions equivalent to argument
239 """
240 resolved = []
241 for version in versions:
242 if version == PACKAGE_STABLE:
243 resolved.append(GetStablePackageVersion(target, package))
244 elif version != PACKAGE_NONE:
245 resolved.append(version)
246 return resolved
247
248
249def GetDesiredPackageVersions(target, package):
250 """Produces the list of desired versions for each target, package pair.
251
252 The first version in the list is implicitly treated as primary, ie.
253 the version that will be initialized by crossdev and selected.
254
255 If the version is PACKAGE_STABLE, it really means the current version which
256 is emerged by using the package atom with no particular version key.
257 Since crossdev unmasks all packages by default, this will actually
258 mean 'unstable' in most cases.
259
260 args:
261 target, package - the target/package to operate on eg. i686-pc-linux-gnu,gcc
262
263 returns a list composed of either a version string, PACKAGE_STABLE
264 """
265 packagemap = GetPackageMap(target)
266
267 versions = []
268 if package in packagemap:
269 versions.append(packagemap[package])
270
271 return versions
272
273
274def TargetIsInitialized(target):
275 """Verifies if the given list of targets has been correctly initialized.
276
277 This determines whether we have to call crossdev while emerging
278 toolchain packages or can do it using emerge. Emerge is naturally
279 preferred, because all packages can be updated in a single pass.
280
281 args:
282 targets - list of individual cross targets which are checked
283
284 returns True if target is completely initialized
285 returns False otherwise
286 """
287 # Check if packages for the given target all have a proper version.
288 try:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100289 for package in GetTargetPackages(target):
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100290 # Do we even want this package && is it initialized?
291 if not IsPackageDisabled(target, package) and \
292 not GetInstalledPackageVersions(target, package):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100293 return False
294 return True
295 except cros_build_lib.RunCommandError:
296 # Fails - The target has likely never been initialized before.
297 return False
298
299
300def RemovePackageMask(target):
301 """Removes a package.mask file for the given platform.
302
303 The pre-existing package.mask files can mess with the keywords.
304
305 args:
306 target - the target for which to remove the file
307 """
308 maskfile = os.path.join('/etc/portage/package.mask', 'cross-' + target)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100309 try:
310 os.unlink(maskfile)
311 except EnvironmentError as e:
312 if e.errno != errno.ENOENT:
313 raise
Zdenek Behan508dcce2011-12-05 15:39:32 +0100314
315
316def CreatePackageMask(target, masks):
317 """[Re]creates a package.mask file for the given platform.
318
319 args:
320 target - the given target on which to operate
321 masks - a map of package : version,
322 where version is the highest permissible version (mask >)
323 """
324 maskfile = os.path.join('/etc/portage/package.mask', 'cross-' + target)
325 assert not os.path.exists(maskfile)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100326 cros_build_lib.SafeMakedirs(os.path.dirname(maskfile))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100327
328 with open(maskfile, 'w') as f:
329 for pkg, m in masks.items():
330 f.write('>%s-%s\n' % (pkg, m))
331
332
333def CreatePackageKeywords(target):
334 """[Re]create a package.keywords file for the platform.
335
336 This sets all package.keywords files to unmask all stable/testing packages.
337 TODO: Note that this approach should be deprecated and is only done for
338 compatibility reasons. In the future, we'd like to stop using keywords
339 altogether, and keep just stable unmasked.
340
341 args:
342 target - target for which to recreate package.keywords
343 """
344 maskfile = os.path.join('/etc/portage/package.keywords', 'cross-' + target)
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100345 try:
346 os.unlink(maskfile)
347 except EnvironmentError as e:
348 if e.errno != errno.ENOENT:
349 raise
350 cros_build_lib.SafeMakedirs(os.path.dirname(maskfile))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100351
352 keyword = GetPortageKeyword(target)
353
354 with open(maskfile, 'w') as f:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100355 for pkg in GetTargetPackages(target):
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100356 if IsPackageDisabled(target, pkg):
357 continue
358 f.write('%s %s ~%s\n' %
359 (GetPortagePackage(target, pkg), keyword, keyword))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100360
361
362# Main functions performing the actual update steps.
363def InitializeCrossdevTargets(targets, usepkg):
364 """Calls crossdev to initialize a cross target.
365 args:
366 targets - the list of targets to initialize using crossdev
367 usepkg - copies the commandline opts
368 """
369 print 'The following targets need to be re-initialized:'
370 print targets
Zdenek Behan508dcce2011-12-05 15:39:32 +0100371
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100372 extra_env = { 'FEATURES' : 'splitdebug' }
Zdenek Behan508dcce2011-12-05 15:39:32 +0100373 for target in targets:
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100374 cmd = ['crossdev', '--show-fail-log',
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100375 '-t', target]
Zdenek Behan508dcce2011-12-05 15:39:32 +0100376 # Pick stable by default, and override as necessary.
377 cmd.extend(['-P', '--oneshot'])
378 if usepkg:
379 cmd.extend(['-P', '--getbinpkg',
380 '-P', '--usepkgonly',
381 '--without-headers'])
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100382
383 cmd.extend(['--overlays', '%s %s' % (CHROMIUMOS_OVERLAY, STABLE_OVERLAY)])
384 cmd.extend(['--ov-output', CROSSDEV_OVERLAY])
Zdenek Behan508dcce2011-12-05 15:39:32 +0100385
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100386 for pkg in GetTargetPackages(target):
387 if pkg == 'gdb':
388 # Gdb does not have selectable versions.
389 cmd.append('--ex-gdb')
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100390 continue
Zdenek Behan508dcce2011-12-05 15:39:32 +0100391 # The first of the desired versions is the "primary" one.
392 version = GetDesiredPackageVersions(target, pkg)[0]
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100393 cmd.extend(['--%s' % pkg, version])
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100394 cros_build_lib.RunCommand(cmd, extra_env=extra_env)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100395
396
397def UpdateTargets(targets, usepkg):
398 """Determines which packages need update/unmerge and defers to portage.
399
400 args:
401 targets - the list of targets to update
402 usepkg - copies the commandline option
403 """
404 # TODO(zbehan): This process is rather complex due to package.* handling.
405 # With some semantic changes over the original setup_board functionality,
406 # it can be considerably cleaned up.
407 mergemap = {}
408
409 # For each target, we do two things. Figure out the list of updates,
410 # and figure out the appropriate keywords/masks. Crossdev will initialize
411 # these, but they need to be regenerated on every update.
412 print 'Determining required toolchain updates...'
413 for target in targets:
414 # Record the highest needed version for each target, for masking purposes.
415 RemovePackageMask(target)
416 CreatePackageKeywords(target)
417 packagemasks = {}
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100418 for package in GetTargetPackages(target):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100419 # Portage name for the package
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100420 if IsPackageDisabled(target, package):
421 continue
422 pkg = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100423 current = GetInstalledPackageVersions(target, package)
424 desired = GetDesiredPackageVersions(target, package)
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100425 desired_num = VersionListToNumeric(target, package, desired)
426 mergemap[pkg] = set(desired_num).difference(current)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100427
428 # Pick the highest version for mask.
429 packagemasks[pkg] = portage.versions.best(desired_num)
430
431 CreatePackageMask(target, packagemasks)
432
433 packages = []
434 for pkg in mergemap:
435 for ver in mergemap[pkg]:
Zdenek Behan677b6d82012-04-11 05:31:47 +0200436 if ver != PACKAGE_NONE:
437 # Be a little more permissive for usepkg, the binaries may not exist.
438 packages.append('%s%s-%s' % ('<=' if usepkg else '=', pkg, ver))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100439
440 if not packages:
441 print 'Nothing to update!'
442 return
443
444 print 'Updating packages:'
445 print packages
446
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100447 cmd = [EMERGE_CMD, '--oneshot', '--update']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100448 if usepkg:
449 cmd.extend(['--getbinpkg', '--usepkgonly'])
450
451 cmd.extend(packages)
452 cros_build_lib.RunCommand(cmd)
453
454
455def CleanTargets(targets):
456 """Unmerges old packages that are assumed unnecessary."""
457 unmergemap = {}
458 for target in targets:
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100459 for package in GetTargetPackages(target):
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100460 if IsPackageDisabled(target, package):
461 continue
462 pkg = GetPortagePackage(target, package)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100463 current = GetInstalledPackageVersions(target, package)
464 desired = GetDesiredPackageVersions(target, package)
465 desired_num = VersionListToNumeric(target, package, desired)
466 assert set(desired).issubset(set(desired))
467 unmergemap[pkg] = set(current).difference(desired_num)
468
469 # Cleaning doesn't care about consistency and rebuilding package.* files.
470 packages = []
471 for pkg, vers in unmergemap.iteritems():
472 packages.extend('=%s-%s' % (pkg, ver) for ver in vers if ver != '9999')
473
474 if packages:
475 print 'Cleaning packages:'
476 print packages
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100477 cmd = [EMERGE_CMD, '--unmerge']
Zdenek Behan508dcce2011-12-05 15:39:32 +0100478 cmd.extend(packages)
479 cros_build_lib.RunCommand(cmd)
480 else:
481 print 'Nothing to clean!'
482
483
484def SelectActiveToolchains(targets, suffixes):
485 """Runs gcc-config and binutils-config to select the desired.
486
487 args:
488 targets - the targets to select
489 """
490 for package in ['gcc', 'binutils']:
491 for target in targets:
492 # Pick the first version in the numbered list as the selected one.
493 desired = GetDesiredPackageVersions(target, package)
494 desired_num = VersionListToNumeric(target, package, desired)
495 desired = desired_num[0]
496 # *-config does not play revisions, strip them, keep just PV.
497 desired = portage.versions.pkgsplit('%s-%s' % (package, desired))[1]
498
499 if target == 'host':
500 # *-config is the only tool treating host identically (by tuple).
Zdenek Behanf4d18a02012-03-22 15:45:05 +0100501 target = GetHostTuple()
Zdenek Behan508dcce2011-12-05 15:39:32 +0100502
503 # And finally, attach target to it.
504 desired = '%s-%s' % (target, desired)
505
506 # Target specific hacks
507 if package in suffixes:
508 if target in suffixes[package]:
509 desired += suffixes[package][target]
510
511 cmd = [ package + '-config', '-c', target ]
512 current = cros_build_lib.RunCommand(cmd, print_cmd=False,
513 redirect_stdout=True).output.splitlines()[0]
514 # Do not gcc-config when the current is live or nothing needs to be done.
515 if current != desired and current != '9999':
516 cmd = [ package + '-config', desired ]
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100517 cros_build_lib.RunCommand(cmd, print_cmd=False)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100518
519
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100520def UpdateToolchains(usepkg, deleteold, hostonly, targets_wanted):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100521 """Performs all steps to create a synchronized toolchain enviroment.
522
523 args:
524 arguments correspond to the given commandline flags
525 """
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100526 targets = set()
527 if not hostonly:
528 # For hostonly, we can skip most of the below logic, much of which won't
529 # work on bare systems where this is useful.
530 alltargets = GetAllTargets()
531 nonexistant = []
532 if targets_wanted == set(['all']):
533 targets = set(alltargets)
534 else:
535 targets = set(targets_wanted)
536 # Verify user input.
537 for target in targets_wanted:
538 if target not in alltargets:
539 nonexistant.append(target)
540 if nonexistant:
541 raise Exception("Invalid targets: " + ','.join(nonexistant))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100542
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100543 # First check and initialize all cross targets that need to be.
544 crossdev_targets = \
545 [t for t in targets if not TargetIsInitialized(t)]
546 if crossdev_targets:
547 InitializeCrossdevTargets(crossdev_targets, usepkg)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100548
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100549 # We want host updated.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100550 targets.add('host')
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100551
552 # Now update all packages.
Zdenek Behan508dcce2011-12-05 15:39:32 +0100553 UpdateTargets(targets, usepkg)
554 SelectActiveToolchains(targets, CONFIG_TARGET_SUFFIXES)
555
556 if deleteold:
557 CleanTargets(targets)
558
559
Brian Harring30675052012-02-29 12:18:22 -0800560def main(argv):
Zdenek Behan508dcce2011-12-05 15:39:32 +0100561 usage = """usage: %prog [options]
562
563 The script installs and updates the toolchains in your chroot.
564 """
565 parser = optparse.OptionParser(usage)
566 parser.add_option('-u', '--nousepkg',
567 action='store_false', dest='usepkg', default=True,
568 help=('Use prebuilt packages if possible.'))
569 parser.add_option('-d', '--deleteold',
570 action='store_true', dest='deleteold', default=False,
571 help=('Unmerge deprecated packages.'))
572 parser.add_option('-t', '--targets',
573 dest='targets', default='all',
Zdenek Behan4eb6fd22012-03-12 17:00:56 +0100574 help=('Comma separated list of tuples. '
575 'Special keyword \'host\' is allowed. Default: all.'))
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100576 parser.add_option('', '--hostonly',
577 dest='hostonly', default=False, action='store_true',
578 help=('Only setup the host toolchain. '
579 'Useful for bootstrapping chroot.'))
Zdenek Behan508dcce2011-12-05 15:39:32 +0100580
Brian Harring30675052012-02-29 12:18:22 -0800581 (options, _remaining_arguments) = parser.parse_args(argv)
Zdenek Behan508dcce2011-12-05 15:39:32 +0100582
Mike Frysingerb9a28fe2012-03-21 11:35:42 -0400583 # This has to be always ran as root.
584 if not os.getuid() == 0:
585 print "%s: This script must be run as root!" % sys.argv[0]
586 sys.exit(1)
587
Zdenek Behan508dcce2011-12-05 15:39:32 +0100588 targets = set(options.targets.split(','))
Zdenek Behan7e33b4e2012-03-12 17:00:56 +0100589 UpdateToolchains(options.usepkg, options.deleteold, options.hostonly, targets)