blob: 569dd9c196b5ca314eb9964ed67f3a91ccba33c0 [file] [log] [blame]
Ryan Cui6290f032012-11-20 15:44:43 -08001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Generates a sysroot tarball for building a specific package.
6
7Meant for use after setup_board and build_packages have been run.
8"""
9
Mike Frysinger383367e2014-09-16 15:06:17 -040010from __future__ import print_function
11
Ryan Cui6290f032012-11-20 15:44:43 -080012import os
13
Don Garrett88b8d782014-05-13 17:30:55 -070014from chromite.cbuildbot import constants
Ryan Cui6290f032012-11-20 15:44:43 -080015from chromite.lib import cros_build_lib
16from chromite.lib import commandline
17from chromite.lib import osutils
18from chromite.lib import sudo
Bertrand SIMONNETa5d8b552015-03-25 16:03:34 -070019from chromite.lib import sysroot_lib
Ryan Cui6290f032012-11-20 15:44:43 -080020
21DEFAULT_NAME = 'sysroot_%(package)s.tar.xz'
22PACKAGE_SEPARATOR = '/'
23SYSROOT = 'sysroot'
24
25
26def ParseCommandLine(argv):
27 """Parse args, and run environment-independent checks."""
28 parser = commandline.ArgumentParser(description=__doc__)
29 parser.add_argument('--board', required=True,
30 help=('The board to generate the sysroot for.'))
31 parser.add_argument('--package', required=True,
32 help=('The package to generate the sysroot for.'))
Michael Spang46c52fb2015-05-28 00:20:18 -040033 parser.add_argument('--out-dir', type='path', required=True,
Ryan Cui6290f032012-11-20 15:44:43 -080034 help='Directory to place the generated tarball.')
35 parser.add_argument('--out-file',
36 help=('The name to give to the tarball. Defaults to %r.'
37 % DEFAULT_NAME))
38 options = parser.parse_args(argv)
39
40 if not options.out_file:
41 options.out_file = DEFAULT_NAME % {
42 'package': options.package.replace(PACKAGE_SEPARATOR, '_')
43 }
44
45 return options
46
47
48class GenerateSysroot(object):
49 """Wrapper for generation functionality."""
50
51 PARALLEL_EMERGE = os.path.join(constants.CHROMITE_BIN_DIR, 'parallel_emerge')
52
53 def __init__(self, sysroot, options):
54 """Initialize
55
Mike Frysinger02e1e072013-11-10 22:11:34 -050056 Args:
Ryan Cui6290f032012-11-20 15:44:43 -080057 sysroot: Path to sysroot.
58 options: Parsed options.
59 """
60 self.sysroot = sysroot
61 self.options = options
David James78d2e942013-07-31 15:34:45 -070062 self.extra_env = {'ROOT': self.sysroot, 'USE': os.environ.get('USE', '')}
63
64 def _Emerge(self, *args, **kwargs):
65 """Emerge the given packages using parallel_emerge."""
66 cmd = [self.PARALLEL_EMERGE, '--board=%s' % self.options.board,
67 '--usepkgonly', '--noreplace'] + list(args)
68 kwargs.setdefault('extra_env', self.extra_env)
69 cros_build_lib.SudoRunCommand(cmd, **kwargs)
Ryan Cui6290f032012-11-20 15:44:43 -080070
71 def _InstallToolchain(self):
Bertrand SIMONNETa5d8b552015-03-25 16:03:34 -070072 # Create the sysroot's config.
Bertrand SIMONNETe2cec3f2015-04-06 16:12:54 -070073 sysroot = sysroot_lib.Sysroot(self.sysroot)
74 sysroot.WriteConfig(sysroot.GenerateBoardConfig(self.options.board))
Ryan Cui6290f032012-11-20 15:44:43 -080075 cros_build_lib.RunCommand(
76 [os.path.join(constants.CROSUTILS_DIR, 'install_toolchain'),
Bertrand SIMONNETc1db71d2015-03-24 12:54:36 -070077 '--noconfigure', '--sysroot', self.sysroot])
Ryan Cui6290f032012-11-20 15:44:43 -080078
79 def _InstallKernelHeaders(self):
David James78d2e942013-07-31 15:34:45 -070080 self._Emerge('sys-kernel/linux-headers')
Ryan Cui6290f032012-11-20 15:44:43 -080081
82 def _InstallBuildDependencies(self):
David James78d2e942013-07-31 15:34:45 -070083 # Calculate buildtime deps that are not runtime deps.
Yu-Ju Hongdd9bb2b2014-01-03 17:08:26 -080084 raw_sysroot = cros_build_lib.GetSysroot(board=self.options.board)
David James78d2e942013-07-31 15:34:45 -070085 cmd = ['qdepends', '-q', '-C', self.options.package]
Yu-Ju Hong3add4432014-01-30 11:46:15 -080086 output = cros_build_lib.RunCommand(
87 cmd, extra_env={'ROOT': raw_sysroot}, capture_output=True).output
David James78d2e942013-07-31 15:34:45 -070088
89 if output.count('\n') > 1:
90 raise AssertionError('Too many packages matched given package pattern')
91
92 # qdepend outputs "package: deps", so only grab the deps.
93 atoms = output.partition(':')[2].split()
94
95 # Install the buildtime deps.
96 if atoms:
97 self._Emerge(*atoms)
Ryan Cui6290f032012-11-20 15:44:43 -080098
99 def _CreateTarball(self):
Ryan Cuid6d13332012-11-28 16:35:22 -0800100 target = os.path.join(self.options.out_dir, self.options.out_file)
101 cros_build_lib.CreateTarball(target, self.sysroot, sudo=True)
Ryan Cui6290f032012-11-20 15:44:43 -0800102
103 def Perform(self):
104 """Generate the sysroot."""
105 self._InstallToolchain()
106 self._InstallKernelHeaders()
107 self._InstallBuildDependencies()
108 self._CreateTarball()
109
110
111def FinishParsing(options):
112 """Run environment dependent checks on parsed args."""
113 target = os.path.join(options.out_dir, options.out_file)
114 if os.path.exists(target):
115 cros_build_lib.Die('Output file %r already exists.' % target)
116
117 if not os.path.isdir(options.out_dir):
118 cros_build_lib.Die(
119 'Non-existent directory %r specified for --out-dir' % options.out_dir)
120
121
122def main(argv):
123 options = ParseCommandLine(argv)
124 FinishParsing(options)
125
Mike Frysinger8fd67dc2012-12-03 23:51:18 -0500126 cros_build_lib.AssertInsideChroot()
Ryan Cui6290f032012-11-20 15:44:43 -0800127
128 with sudo.SudoKeepAlive(ttyless_sudo=False):
David James4bc13702013-03-26 08:08:04 -0700129 with osutils.TempDir(set_global=True, sudo_rm=True) as tempdir:
Ryan Cui6290f032012-11-20 15:44:43 -0800130 sysroot = os.path.join(tempdir, SYSROOT)
131 os.mkdir(sysroot)
132 GenerateSysroot(sysroot, options).Perform()