blob: 556de9dfbb17ed28d7f76cb09ebc147f9d45c0e8 [file] [log] [blame]
Ryan Cui6290f032012-11-20 15:44:43 -08001#!/usr/bin/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"""Generates a sysroot tarball for building a specific package.
7
8Meant for use after setup_board and build_packages have been run.
9"""
10
11import os
12
13from chromite.buildbot import constants
14from chromite.lib import cros_build_lib
15from chromite.lib import commandline
16from chromite.lib import osutils
17from chromite.lib import sudo
18
19DEFAULT_NAME = 'sysroot_%(package)s.tar.xz'
20PACKAGE_SEPARATOR = '/'
21SYSROOT = 'sysroot'
22
23
24def ParseCommandLine(argv):
25 """Parse args, and run environment-independent checks."""
26 parser = commandline.ArgumentParser(description=__doc__)
27 parser.add_argument('--board', required=True,
28 help=('The board to generate the sysroot for.'))
29 parser.add_argument('--package', required=True,
30 help=('The package to generate the sysroot for.'))
31 parser.add_argument('--out-dir', type=osutils.ExpandPath, required=True,
32 help='Directory to place the generated tarball.')
33 parser.add_argument('--out-file',
34 help=('The name to give to the tarball. Defaults to %r.'
35 % DEFAULT_NAME))
36 options = parser.parse_args(argv)
37
38 if not options.out_file:
39 options.out_file = DEFAULT_NAME % {
40 'package': options.package.replace(PACKAGE_SEPARATOR, '_')
41 }
42
43 return options
44
45
46class GenerateSysroot(object):
47 """Wrapper for generation functionality."""
48
49 PARALLEL_EMERGE = os.path.join(constants.CHROMITE_BIN_DIR, 'parallel_emerge')
50
51 def __init__(self, sysroot, options):
52 """Initialize
53
54 Arguments:
55 sysroot: Path to sysroot.
56 options: Parsed options.
57 """
58 self.sysroot = sysroot
59 self.options = options
David James78d2e942013-07-31 15:34:45 -070060 self.extra_env = {'ROOT': self.sysroot, 'USE': os.environ.get('USE', '')}
61
62 def _Emerge(self, *args, **kwargs):
63 """Emerge the given packages using parallel_emerge."""
64 cmd = [self.PARALLEL_EMERGE, '--board=%s' % self.options.board,
65 '--usepkgonly', '--noreplace'] + list(args)
66 kwargs.setdefault('extra_env', self.extra_env)
67 cros_build_lib.SudoRunCommand(cmd, **kwargs)
Ryan Cui6290f032012-11-20 15:44:43 -080068
69 def _InstallToolchain(self):
70 cros_build_lib.RunCommand(
71 [os.path.join(constants.CROSUTILS_DIR, 'install_toolchain'),
72 '--noconfigure', '--board_root', self.sysroot, '--board',
73 self.options.board])
74
75 def _InstallKernelHeaders(self):
David James78d2e942013-07-31 15:34:45 -070076 self._Emerge('sys-kernel/linux-headers')
Ryan Cui6290f032012-11-20 15:44:43 -080077
78 def _InstallBuildDependencies(self):
David James78d2e942013-07-31 15:34:45 -070079 # Calculate buildtime deps that are not runtime deps.
80 raw_sysroot = '/build/%s' % (self.options.board,)
81 cmd = ['qdepends', '-q', '-C', self.options.package]
82 output = cros_build_lib.RunCommandCaptureOutput(
83 cmd, extra_env={'ROOT': raw_sysroot}).output
84
85 if output.count('\n') > 1:
86 raise AssertionError('Too many packages matched given package pattern')
87
88 # qdepend outputs "package: deps", so only grab the deps.
89 atoms = output.partition(':')[2].split()
90
91 # Install the buildtime deps.
92 if atoms:
93 self._Emerge(*atoms)
Ryan Cui6290f032012-11-20 15:44:43 -080094
95 def _CreateTarball(self):
Ryan Cuid6d13332012-11-28 16:35:22 -080096 target = os.path.join(self.options.out_dir, self.options.out_file)
97 cros_build_lib.CreateTarball(target, self.sysroot, sudo=True)
Ryan Cui6290f032012-11-20 15:44:43 -080098
99 def Perform(self):
100 """Generate the sysroot."""
101 self._InstallToolchain()
102 self._InstallKernelHeaders()
103 self._InstallBuildDependencies()
104 self._CreateTarball()
105
106
107def FinishParsing(options):
108 """Run environment dependent checks on parsed args."""
109 target = os.path.join(options.out_dir, options.out_file)
110 if os.path.exists(target):
111 cros_build_lib.Die('Output file %r already exists.' % target)
112
113 if not os.path.isdir(options.out_dir):
114 cros_build_lib.Die(
115 'Non-existent directory %r specified for --out-dir' % options.out_dir)
116
117
118def main(argv):
119 options = ParseCommandLine(argv)
120 FinishParsing(options)
121
Mike Frysinger8fd67dc2012-12-03 23:51:18 -0500122 cros_build_lib.AssertInsideChroot()
Ryan Cui6290f032012-11-20 15:44:43 -0800123
124 with sudo.SudoKeepAlive(ttyless_sudo=False):
David James4bc13702013-03-26 08:08:04 -0700125 with osutils.TempDir(set_global=True, sudo_rm=True) as tempdir:
Ryan Cui6290f032012-11-20 15:44:43 -0800126 sysroot = os.path.join(tempdir, SYSROOT)
127 os.mkdir(sysroot)
128 GenerateSysroot(sysroot, options).Perform()