blob: b26922a70cb8becc41c09cbfa075bda9390bd6ee [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
17
David James03156362011-03-04 20:28:26 -080018def _DoMakeChroot(chroot_config, clean_first):
Doug Andersona9b10902011-02-01 17:54:31 -080019 """Build the chroot, if needed.
20
21 Args:
22 chroot_config: A SafeConfigParser representing the config for the chroot.
23 clean_first: Delete any old chroot first.
24 """
25 # Skip this whole command if things already exist.
26 # TODO(dianders): Theoretically, calling make_chroot a second time is OK
27 # and "fixes up" the chroot. ...but build_packages will do the fixups
28 # anyway (I think), so this isn't that important.
29 chroot_dir = utils.GetChrootAbsDir(chroot_config)
30 if (not clean_first) and utils.DoesChrootExist(chroot_config):
David James03156362011-03-04 20:28:26 -080031 cros_lib.Info('%s already exists, skipping make_chroot.' % chroot_dir)
Doug Andersona9b10902011-02-01 17:54:31 -080032 return
33
David James03156362011-03-04 20:28:26 -080034 cros_lib.Info('MAKING THE CHROOT')
35
Doug Andersona9b10902011-02-01 17:54:31 -080036 # Put together command.
David James03156362011-03-04 20:28:26 -080037 cmd_list = [
38 './make_chroot',
Doug Andersona9b10902011-02-01 17:54:31 -080039 '--chroot="%s"' % chroot_dir,
40 chroot_config.get('CHROOT', 'make_chroot_flags'),
41 ]
42 if clean_first:
David James03156362011-03-04 20:28:26 -080043 cmd_list.insert(1, '--replace')
Doug Andersona9b10902011-02-01 17:54:31 -080044
David James03156362011-03-04 20:28:26 -080045 # We're going convert to a string and force the shell to do all of the
46 # splitting of arguments, since we're throwing all of the flags from the
47 # config file in there.
48 cmd = ' '.join(cmd_list)
49
50 # We'll put CWD as src/scripts when running the command. Since everyone
51 # running by hand has their cwd there, it is probably the safest.
52 cwd = os.path.join(utils.SRCROOT_PATH, 'src', 'scripts')
53
54 # Run it. Exceptions will cause the program to exit.
55 cros_lib.RunCommand(cmd, shell=True, cwd=cwd, ignore_sigint=True)
Doug Andersona9b10902011-02-01 17:54:31 -080056
57
David James03156362011-03-04 20:28:26 -080058def _DoSetupBoard(build_config, clean_first):
Doug Andersona9b10902011-02-01 17:54:31 -080059 """Setup the board, if needed.
60
61 This just runs the setup_board command with the proper args, if needed.
62
63 Args:
64 build_config: A SafeConfigParser representing the build config.
65 clean_first: Delete any old board config first.
66 """
67 # Skip this whole command if things already exist.
68 board_dir = utils.GetBoardDir(build_config)
69 if (not clean_first) and os.path.isdir(board_dir):
David James03156362011-03-04 20:28:26 -080070 cros_lib.Info('%s already exists, skipping setup_board.' % board_dir)
Doug Andersona9b10902011-02-01 17:54:31 -080071 return
72
David James03156362011-03-04 20:28:26 -080073 cros_lib.Info('SETTING UP THE BOARD')
74
Doug Andersona9b10902011-02-01 17:54:31 -080075 # Put together command.
76 cmd_list = [
David James03156362011-03-04 20:28:26 -080077 './setup_board',
Doug Anderson6f530612011-02-11 13:19:25 -080078 '--board="%s"' % build_config.get('DEFAULT', 'target'),
Doug Andersona9b10902011-02-01 17:54:31 -080079 build_config.get('BUILD', 'setup_board_flags'),
80 ]
81 if clean_first:
David James03156362011-03-04 20:28:26 -080082 cmd_list.insert(1, '--force')
Doug Andersona9b10902011-02-01 17:54:31 -080083
David James03156362011-03-04 20:28:26 -080084 # We're going convert to a string and force the shell to do all of the
85 # splitting of arguments, since we're throwing all of the flags from the
86 # config file in there.
87 cmd = ' '.join(cmd_list)
88
89 # We'll put CWD as src/scripts when running the command. Since everyone
90 # running by hand has their cwd there, it is probably the safest.
91 cwd = os.path.join(utils.SRCROOT_PATH, 'src', 'scripts')
92
93 # Run it. Exceptions will cause the program to exit.
94 cros_lib.RunCommand(cmd, shell=True, cwd=cwd, ignore_sigint=True)
Doug Andersona9b10902011-02-01 17:54:31 -080095
96
David James03156362011-03-04 20:28:26 -080097def _DoBuildPackages(build_config):
Doug Andersona9b10902011-02-01 17:54:31 -080098 """Build packages.
99
100 This just runs the build_packages command with the proper args.
101
102 Args:
103 build_config: A SafeConfigParser representing the build config.
104 """
David James03156362011-03-04 20:28:26 -0800105 cros_lib.Info('BUILDING PACKAGES')
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.
David James03156362011-03-04 20:28:26 -0800110 cmd = '%s ./build_packages --board="%s" %s' % (
111 build_config.get('BUILD', 'build_packages_environ'),
112 build_config.get('DEFAULT', 'target'),
Doug Andersona9b10902011-02-01 17:54:31 -0800113 build_config.get('BUILD', 'build_packages_flags')
David James03156362011-03-04 20:28:26 -0800114 )
Doug Andersona9b10902011-02-01 17:54:31 -0800115
David James03156362011-03-04 20:28:26 -0800116 # We'll put CWD as src/scripts when running the command. Since everyone
117 # running by hand has their cwd there, it is probably the safest.
118 cwd = os.path.join(utils.SRCROOT_PATH, 'src', 'scripts')
119
120 # Run it. Exceptions will cause the program to exit.
121 cros_lib.RunCommand(cmd, shell=True, cwd=cwd, ignore_sigint=True)
Doug Andersona9b10902011-02-01 17:54:31 -0800122
123
David James03156362011-03-04 20:28:26 -0800124def _DoBuildImage(build_config):
Doug Andersona9b10902011-02-01 17:54:31 -0800125 """Build an image.
126
127 This just runs the build_image command with the proper args.
128
129 Args:
130 build_config: A SafeConfigParser representing the build config.
131 """
David James03156362011-03-04 20:28:26 -0800132 cros_lib.Info('BUILDING THE IMAGE')
Doug Andersona9b10902011-02-01 17:54:31 -0800133
134 # Put together command. We're going to force the shell to do all of the
135 # splitting of arguments, since we're throwing all of the flags from the
136 # config file in there.
David James03156362011-03-04 20:28:26 -0800137 cmd = '%s ./build_image --board="%s" %s' % (
138 build_config.get('IMAGE', 'build_image_environ'),
139 build_config.get('DEFAULT', 'target'),
Doug Andersona9b10902011-02-01 17:54:31 -0800140 build_config.get('IMAGE', 'build_image_flags')
David James03156362011-03-04 20:28:26 -0800141 )
Doug Andersona9b10902011-02-01 17:54:31 -0800142
David James03156362011-03-04 20:28:26 -0800143 # We'll put CWD as src/scripts when running the command. Since everyone
144 # running by hand has their cwd there, it is probably the safest.
145 cwd = os.path.join(utils.SRCROOT_PATH, 'src', 'scripts')
146
147 # Run it. Exceptions will cause the program to exit.
148 cros_lib.RunCommand(cmd, shell=True, cwd=cwd, ignore_sigint=True)
Doug Andersona9b10902011-02-01 17:54:31 -0800149
150
David James03156362011-03-04 20:28:26 -0800151def _DoImagePostProcessing(build_config):
Doug Anderson36f75422011-02-11 13:34:08 -0800152 """Do post processing steps after the build image runs.
153
154 Args:
155 build_config: A SafeConfigParser representing the build config.
156 """
David James03156362011-03-04 20:28:26 -0800157 # We'll put CWD as src/scripts when running the commands, since many of these
158 # legacy commands live in src/scripts.
159 # TODO(dianders): Don't set CWD once crosutils are properly installed.
160 cwd = os.path.join(utils.SRCROOT_PATH, 'src', 'scripts')
161
Doug Anderson36f75422011-02-11 13:34:08 -0800162 # The user specifies a list of "steps" in this space-separated variable.
163 # We'll use each step name to construct other variable names to look for
164 # the actual commands.
165 steps = build_config.get('IMAGE', 'post_process_steps')
166 for step_name in steps.split():
David James03156362011-03-04 20:28:26 -0800167 cros_lib.Info('IMAGING POST-PROCESS: %s' % step_name)
168
Doug Anderson36f75422011-02-11 13:34:08 -0800169 # Get the name of the variable that the user stored the cmd in.
170 cmd_var_name = 'post_process_%s_cmd' % step_name
171
172 # Run the command. Exceptions will cause the program to exit.
173 cmd = build_config.get('IMAGE', cmd_var_name)
David James03156362011-03-04 20:28:26 -0800174 cros_lib.RunCommand(cmd, shell=True, cwd=cwd, ignore_sigint=True)
Doug Anderson36f75422011-02-11 13:34:08 -0800175
176
Doug Andersona9b10902011-02-01 17:54:31 -0800177class BuildCmd(subcmd.ChromiteCmd):
178 """Build the chroot (if needed), the packages for a target, and the image."""
179
180 def Run(self, raw_argv, chroot_config=None,
181 loaded_config=False, build_config=None):
182 """Run the command.
183
184 Args:
185 raw_argv: Command line arguments, including this command's name, but not
186 the chromite command name or chromite options.
187 chroot_config: A SafeConfigParser for the chroot config; or None chromite
188 was called from within the chroot.
189 loaded_config: If True, we've already loaded the config.
190 build_config: None when called normally, but contains the SafeConfigParser
191 for the build config if we call ourselves with _DoEnterChroot(). Note
192 that even when called through _DoEnterChroot(), could still be None
193 if user chose 'HOST' as the target.
194 """
195 # Parse options for command...
196 usage_str = ('usage: %%prog [chromite_options] %s [options] [target]' %
197 raw_argv[0])
198 parser = optparse.OptionParser(usage=usage_str)
199 parser.add_option('--clean', default=False, action='store_true',
200 help='Clean before building.')
201 (options, argv) = parser.parse_args(raw_argv[1:])
202
203 # Load the build config if needed...
204 if not loaded_config:
205 argv, build_config = utils.GetBuildConfigFromArgs(argv)
206 if argv:
207 cros_lib.Die('Unknown arguments: %s' % ' '.join(argv))
208
209 if not cros_lib.IsInsideChroot():
210 # Note: we only want to clean the chroot if they do --clean and have the
211 # host target. If they do --clean and have a board target, it means
212 # that they just want to clean the board...
213 want_clean_chroot = options.clean and build_config is None
214
David James03156362011-03-04 20:28:26 -0800215 _DoMakeChroot(chroot_config, want_clean_chroot)
Doug Andersona9b10902011-02-01 17:54:31 -0800216
217 if build_config is not None:
218 utils.EnterChroot(chroot_config, (self, 'Run'), raw_argv,
219 build_config=build_config, loaded_config=True)
220
David James03156362011-03-04 20:28:26 -0800221 cros_lib.Info('Done building.')
Doug Andersona9b10902011-02-01 17:54:31 -0800222 else:
223 if build_config is None:
224 cros_lib.Die("You can't build the host chroot from within the chroot.")
225
David James03156362011-03-04 20:28:26 -0800226 _DoSetupBoard(build_config, options.clean)
227 _DoBuildPackages(build_config)
228 _DoBuildImage(build_config)
229 _DoImagePostProcessing(build_config)