blob: 867f015da52812a3b39a4318ea674131674e8f67 [file] [log] [blame]
Mike Frysingere58c0e22017-10-04 15:43:30 -04001# -*- coding: utf-8 -*-
Ryan Cui6290f032012-11-20 15:44:43 -08002# 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
Mike Frysinger383367e2014-09-16 15:06:17 -040011from __future__ import print_function
12
Ryan Cui6290f032012-11-20 15:44:43 -080013import os
14
Aviv Keshetb7519e12016-10-04 00:50:00 -070015from chromite.lib import constants
Ryan Cui6290f032012-11-20 15:44:43 -080016from chromite.lib import cros_build_lib
17from chromite.lib import commandline
18from chromite.lib import osutils
19from chromite.lib import sudo
Bertrand SIMONNETa5d8b552015-03-25 16:03:34 -070020from chromite.lib import sysroot_lib
Alex Klein8212d492018-08-27 07:47:23 -060021from chromite.lib import toolchain
Ryan Cui6290f032012-11-20 15:44:43 -080022
23DEFAULT_NAME = 'sysroot_%(package)s.tar.xz'
24PACKAGE_SEPARATOR = '/'
25SYSROOT = 'sysroot'
26
27
28def ParseCommandLine(argv):
29 """Parse args, and run environment-independent checks."""
30 parser = commandline.ArgumentParser(description=__doc__)
31 parser.add_argument('--board', required=True,
Alex Klein8212d492018-08-27 07:47:23 -060032 help='The board to generate the sysroot for.')
Ryan Cui6290f032012-11-20 15:44:43 -080033 parser.add_argument('--package', required=True,
Alex Klein8212d492018-08-27 07:47:23 -060034 help='The packages to generate the sysroot for.')
Manoj Gupta2c2a2a22018-02-12 13:13:32 -080035 parser.add_argument('--deps-only', action='store_true',
36 default=False,
37 help='Build dependencies only.')
Michael Spang46c52fb2015-05-28 00:20:18 -040038 parser.add_argument('--out-dir', type='path', required=True,
Ryan Cui6290f032012-11-20 15:44:43 -080039 help='Directory to place the generated tarball.')
Mike Frysinger8557a292017-08-15 11:23:51 -040040 parser.add_argument('--out-file', default=DEFAULT_NAME,
41 help='The name to give to the tarball. '
42 'Defaults to %(default)s.')
Ryan Cui6290f032012-11-20 15:44:43 -080043 options = parser.parse_args(argv)
44
Mike Frysinger8557a292017-08-15 11:23:51 -040045 options.out_file %= {
Manoj Gupta2c2a2a22018-02-12 13:13:32 -080046 'package': options.package.split()[0].replace(PACKAGE_SEPARATOR, '_'),
Mike Frysinger8557a292017-08-15 11:23:51 -040047 }
Ryan Cui6290f032012-11-20 15:44:43 -080048
49 return options
50
51
52class GenerateSysroot(object):
53 """Wrapper for generation functionality."""
54
55 PARALLEL_EMERGE = os.path.join(constants.CHROMITE_BIN_DIR, 'parallel_emerge')
56
57 def __init__(self, sysroot, options):
58 """Initialize
59
Mike Frysinger02e1e072013-11-10 22:11:34 -050060 Args:
Ryan Cui6290f032012-11-20 15:44:43 -080061 sysroot: Path to sysroot.
62 options: Parsed options.
63 """
64 self.sysroot = sysroot
65 self.options = options
David James78d2e942013-07-31 15:34:45 -070066 self.extra_env = {'ROOT': self.sysroot, 'USE': os.environ.get('USE', '')}
67
68 def _Emerge(self, *args, **kwargs):
69 """Emerge the given packages using parallel_emerge."""
70 cmd = [self.PARALLEL_EMERGE, '--board=%s' % self.options.board,
71 '--usepkgonly', '--noreplace'] + list(args)
72 kwargs.setdefault('extra_env', self.extra_env)
73 cros_build_lib.SudoRunCommand(cmd, **kwargs)
Ryan Cui6290f032012-11-20 15:44:43 -080074
75 def _InstallToolchain(self):
Bertrand SIMONNETa5d8b552015-03-25 16:03:34 -070076 # Create the sysroot's config.
Bertrand SIMONNETe2cec3f2015-04-06 16:12:54 -070077 sysroot = sysroot_lib.Sysroot(self.sysroot)
Alex Klein34581082018-12-03 12:56:53 -070078 sysroot.WriteConfig(sysroot.GenerateBoardSetupConfig(self.options.board))
Alex Klein8212d492018-08-27 07:47:23 -060079 toolchain.InstallToolchain(sysroot, configure=False)
Ryan Cui6290f032012-11-20 15:44:43 -080080
81 def _InstallKernelHeaders(self):
David James78d2e942013-07-31 15:34:45 -070082 self._Emerge('sys-kernel/linux-headers')
Ryan Cui6290f032012-11-20 15:44:43 -080083
84 def _InstallBuildDependencies(self):
David James78d2e942013-07-31 15:34:45 -070085 # Calculate buildtime deps that are not runtime deps.
Yu-Ju Hongdd9bb2b2014-01-03 17:08:26 -080086 raw_sysroot = cros_build_lib.GetSysroot(board=self.options.board)
Manoj Gupta2c2a2a22018-02-12 13:13:32 -080087 packages = []
88 if not self.options.deps_only:
89 packages = self.options.package.split()
90 else:
91 for pkg in self.options.package.split():
92 cmd = ['qdepends', '-q', '-C', pkg]
93 output = cros_build_lib.RunCommand(
94 cmd, extra_env={'ROOT': raw_sysroot}, capture_output=True).output
David James78d2e942013-07-31 15:34:45 -070095
Manoj Gupta2c2a2a22018-02-12 13:13:32 -080096 if output.count('\n') > 1:
97 raise AssertionError('Too many packages matched for given pattern')
David James78d2e942013-07-31 15:34:45 -070098
Manoj Gupta2c2a2a22018-02-12 13:13:32 -080099 # qdepend outputs "package: deps", so only grab the deps.
100 deps = output.partition(':')[2].split()
101 packages.extend(deps)
102 # Install the required packages.
103 if packages:
104 self._Emerge(*packages)
Ryan Cui6290f032012-11-20 15:44:43 -0800105
106 def _CreateTarball(self):
Ryan Cuid6d13332012-11-28 16:35:22 -0800107 target = os.path.join(self.options.out_dir, self.options.out_file)
108 cros_build_lib.CreateTarball(target, self.sysroot, sudo=True)
Ryan Cui6290f032012-11-20 15:44:43 -0800109
110 def Perform(self):
111 """Generate the sysroot."""
112 self._InstallToolchain()
113 self._InstallKernelHeaders()
114 self._InstallBuildDependencies()
115 self._CreateTarball()
116
117
118def FinishParsing(options):
119 """Run environment dependent checks on parsed args."""
120 target = os.path.join(options.out_dir, options.out_file)
121 if os.path.exists(target):
122 cros_build_lib.Die('Output file %r already exists.' % target)
123
124 if not os.path.isdir(options.out_dir):
125 cros_build_lib.Die(
126 'Non-existent directory %r specified for --out-dir' % options.out_dir)
127
128
129def main(argv):
130 options = ParseCommandLine(argv)
131 FinishParsing(options)
132
Mike Frysinger8fd67dc2012-12-03 23:51:18 -0500133 cros_build_lib.AssertInsideChroot()
Ryan Cui6290f032012-11-20 15:44:43 -0800134
135 with sudo.SudoKeepAlive(ttyless_sudo=False):
David James4bc13702013-03-26 08:08:04 -0700136 with osutils.TempDir(set_global=True, sudo_rm=True) as tempdir:
Ryan Cui6290f032012-11-20 15:44:43 -0800137 sysroot = os.path.join(tempdir, SYSROOT)
138 os.mkdir(sysroot)
139 GenerateSysroot(sysroot, options).Perform()