blob: a99f35f5e317ebf7d46a8b83f1dd29a2ac09c3fd [file] [log] [blame]
Doug Andersona9b10902011-02-01 17:54:31 -08001# Copyright (c) 2011 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"""Implementation of the 'build' chromite command."""
6
7# Python imports
8import optparse
9import os
10
11
12# Local imports
13import chromite.lib.cros_build_lib as cros_lib
14from chromite.shell import utils
15from chromite.shell import subcmd
16
Simon Glass5329b932011-03-14 16:49:04 -070017# TODO(sjg): I would prefer that these methods be inside the BuildCmd() class.
Doug Andersona9b10902011-02-01 17:54:31 -080018
Simon Glass5329b932011-03-14 16:49:04 -070019
20def _DoMakeChroot(cros_env, chroot_config, clean_first):
Doug Andersona9b10902011-02-01 17:54:31 -080021 """Build the chroot, if needed.
22
23 Args:
Simon Glass5329b932011-03-14 16:49:04 -070024 cros_env: Chromite environment to use for this command.
Doug Andersona9b10902011-02-01 17:54:31 -080025 chroot_config: A SafeConfigParser representing the config for the chroot.
26 clean_first: Delete any old chroot first.
27 """
28 # Skip this whole command if things already exist.
29 # TODO(dianders): Theoretically, calling make_chroot a second time is OK
30 # and "fixes up" the chroot. ...but build_packages will do the fixups
31 # anyway (I think), so this isn't that important.
32 chroot_dir = utils.GetChrootAbsDir(chroot_config)
33 if (not clean_first) and utils.DoesChrootExist(chroot_config):
Simon Glass5329b932011-03-14 16:49:04 -070034 cros_env.GetOperation().Info('%s already exists, skipping make_chroot.' %
35 chroot_dir)
Doug Andersona9b10902011-02-01 17:54:31 -080036 return
37
Doug Andersona9b10902011-02-01 17:54:31 -080038 # Put together command.
Simon Glass5329b932011-03-14 16:49:04 -070039 arg_list = [
Doug Andersona9b10902011-02-01 17:54:31 -080040 '--chroot="%s"' % chroot_dir,
41 chroot_config.get('CHROOT', 'make_chroot_flags'),
42 ]
43 if clean_first:
Simon Glass5329b932011-03-14 16:49:04 -070044 arg_list.insert(0, '--replace')
Doug Andersona9b10902011-02-01 17:54:31 -080045
Simon Glass5329b932011-03-14 16:49:04 -070046 cros_env.RunScript('MAKING THE CHROOT', './make_chroot', arg_list)
Doug Andersona9b10902011-02-01 17:54:31 -080047
48
Simon Glass5329b932011-03-14 16:49:04 -070049def _DoSetupBoard(cros_env, build_config, clean_first):
Doug Andersona9b10902011-02-01 17:54:31 -080050 """Setup the board, if needed.
51
52 This just runs the setup_board command with the proper args, if needed.
53
54 Args:
Simon Glass5329b932011-03-14 16:49:04 -070055 cros_env: Chromite environment to use for this command.
Doug Andersona9b10902011-02-01 17:54:31 -080056 build_config: A SafeConfigParser representing the build config.
57 clean_first: Delete any old board config first.
58 """
59 # Skip this whole command if things already exist.
60 board_dir = utils.GetBoardDir(build_config)
61 if (not clean_first) and os.path.isdir(board_dir):
Simon Glass5329b932011-03-14 16:49:04 -070062 cros_env.GetOperation().Info('%s already exists, skipping setup_board.' %
63 board_dir)
Doug Andersona9b10902011-02-01 17:54:31 -080064 return
65
Doug Andersona9b10902011-02-01 17:54:31 -080066 # Put together command.
67 cmd_list = [
Doug Anderson6f530612011-02-11 13:19:25 -080068 '--board="%s"' % build_config.get('DEFAULT', 'target'),
Doug Andersona9b10902011-02-01 17:54:31 -080069 build_config.get('BUILD', 'setup_board_flags'),
70 ]
71 if clean_first:
Simon Glass5329b932011-03-14 16:49:04 -070072 arg_list.insert(0, '--force')
Doug Andersona9b10902011-02-01 17:54:31 -080073
Simon Glass5329b932011-03-14 16:49:04 -070074 cros_env.RunScript('SETTING UP THE BOARD', './setup_board', arg_list)
Doug Andersona9b10902011-02-01 17:54:31 -080075
76
Simon Glass5329b932011-03-14 16:49:04 -070077def _DoBuildPackages(cros_env, build_config):
Doug Andersona9b10902011-02-01 17:54:31 -080078 """Build packages.
79
80 This just runs the build_packages command with the proper args.
81
82 Args:
Simon Glass5329b932011-03-14 16:49:04 -070083 cros_env: Chromite environment to use for this command.
Doug Andersona9b10902011-02-01 17:54:31 -080084 build_config: A SafeConfigParser representing the build config.
85 """
Doug Andersona9b10902011-02-01 17:54:31 -080086
87 # Put together command. We're going to force the shell to do all of the
88 # splitting of arguments, since we're throwing all of the flags from the
89 # config file in there.
Simon Glass5329b932011-03-14 16:49:04 -070090 arg_list = ['--board="%s"' % build_config.get('DEFAULT', 'target'),
Doug Andersona9b10902011-02-01 17:54:31 -080091 build_config.get('BUILD', 'build_packages_flags')
Simon Glass5329b932011-03-14 16:49:04 -070092 ]
Doug Andersona9b10902011-02-01 17:54:31 -080093
Simon Glass5329b932011-03-14 16:49:04 -070094 cros_env.RunScript('BUILDING PACKAGES', './build_packages', arg_list,
95 shell_vars=build_config.get('BUILD', 'build_packages_environ'))
Doug Andersona9b10902011-02-01 17:54:31 -080096
97
Simon Glass5329b932011-03-14 16:49:04 -070098def _DoBuildImage(cros_env, build_config):
Doug Andersona9b10902011-02-01 17:54:31 -080099 """Build an image.
100
101 This just runs the build_image command with the proper args.
102
103 Args:
104 build_config: A SafeConfigParser representing the build config.
105 """
Doug Andersona9b10902011-02-01 17:54:31 -0800106
107 # Put together command. We're going to force the shell to do all of the
108 # splitting of arguments, since we're throwing all of the flags from the
109 # config file in there.
Simon Glass5329b932011-03-14 16:49:04 -0700110 arg_list = ['--board="%s"' % build_config.get('DEFAULT', 'target'),
Doug Andersona9b10902011-02-01 17:54:31 -0800111 build_config.get('IMAGE', 'build_image_flags')
Simon Glass5329b932011-03-14 16:49:04 -0700112 ]
Doug Andersona9b10902011-02-01 17:54:31 -0800113
Simon Glass5329b932011-03-14 16:49:04 -0700114 cros_env.RunScript('BUILDING THE IMAGE', './build_image', arg_list,
115 shell_vars=build_config.get('IMAGE', 'build_image_environ'))
Doug Andersona9b10902011-02-01 17:54:31 -0800116
117
Simon Glass5329b932011-03-14 16:49:04 -0700118def _DoImagePostProcessing(cros_env, build_config):
Doug Anderson36f75422011-02-11 13:34:08 -0800119 """Do post processing steps after the build image runs.
120
121 Args:
122 build_config: A SafeConfigParser representing the build config.
123 """
Doug Anderson36f75422011-02-11 13:34:08 -0800124 # The user specifies a list of "steps" in this space-separated variable.
125 # We'll use each step name to construct other variable names to look for
126 # the actual commands.
127 steps = build_config.get('IMAGE', 'post_process_steps')
128 for step_name in steps.split():
Doug Anderson36f75422011-02-11 13:34:08 -0800129 # Get the name of the variable that the user stored the cmd in.
130 cmd_var_name = 'post_process_%s_cmd' % step_name
131
132 # Run the command. Exceptions will cause the program to exit.
133 cmd = build_config.get('IMAGE', cmd_var_name)
Simon Glass5329b932011-03-14 16:49:04 -0700134 cros_env.RunScript('IMAGING POST-PROCESS: %s' % step_name, '', [cmd])
Doug Anderson36f75422011-02-11 13:34:08 -0800135
136
Doug Andersona9b10902011-02-01 17:54:31 -0800137class BuildCmd(subcmd.ChromiteCmd):
138 """Build the chroot (if needed), the packages for a target, and the image."""
139
140 def Run(self, raw_argv, chroot_config=None,
141 loaded_config=False, build_config=None):
142 """Run the command.
143
144 Args:
145 raw_argv: Command line arguments, including this command's name, but not
146 the chromite command name or chromite options.
147 chroot_config: A SafeConfigParser for the chroot config; or None chromite
148 was called from within the chroot.
149 loaded_config: If True, we've already loaded the config.
150 build_config: None when called normally, but contains the SafeConfigParser
151 for the build config if we call ourselves with _DoEnterChroot(). Note
152 that even when called through _DoEnterChroot(), could still be None
153 if user chose 'HOST' as the target.
154 """
155 # Parse options for command...
156 usage_str = ('usage: %%prog [chromite_options] %s [options] [target]' %
157 raw_argv[0])
158 parser = optparse.OptionParser(usage=usage_str)
159 parser.add_option('--clean', default=False, action='store_true',
160 help='Clean before building.')
161 (options, argv) = parser.parse_args(raw_argv[1:])
162
163 # Load the build config if needed...
164 if not loaded_config:
165 argv, build_config = utils.GetBuildConfigFromArgs(argv)
166 if argv:
167 cros_lib.Die('Unknown arguments: %s' % ' '.join(argv))
168
169 if not cros_lib.IsInsideChroot():
170 # Note: we only want to clean the chroot if they do --clean and have the
171 # host target. If they do --clean and have a board target, it means
172 # that they just want to clean the board...
173 want_clean_chroot = options.clean and build_config is None
174
Simon Glass5329b932011-03-14 16:49:04 -0700175 _DoMakeChroot(self.cros_env, chroot_config, want_clean_chroot)
Doug Andersona9b10902011-02-01 17:54:31 -0800176
177 if build_config is not None:
Simon Glass5329b932011-03-14 16:49:04 -0700178 self._oper.Info('ENTERING THE CHROOT')
Doug Andersona9b10902011-02-01 17:54:31 -0800179 utils.EnterChroot(chroot_config, (self, 'Run'), raw_argv,
180 build_config=build_config, loaded_config=True)
181
Simon Glass5329b932011-03-14 16:49:04 -0700182 self._oper.Info('Done building.')
Doug Andersona9b10902011-02-01 17:54:31 -0800183 else:
184 if build_config is None:
185 cros_lib.Die("You can't build the host chroot from within the chroot.")
186
Simon Glass5329b932011-03-14 16:49:04 -0700187 _DoSetupBoard(self.cros_env, build_config, options.clean)
188 _DoBuildPackages(self.cros_env, build_config)
189 _DoBuildImage(self.cros_env, build_config)
190 _DoImagePostProcessing(self.cros_env, build_config)