Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 1 | # 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 |
| 8 | import optparse |
| 9 | import os |
| 10 | |
| 11 | |
| 12 | # Local imports |
| 13 | import chromite.lib.cros_build_lib as cros_lib |
| 14 | from chromite.shell import utils |
| 15 | from chromite.shell import subcmd |
| 16 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 17 | # TODO(sjg): I would prefer that these methods be inside the BuildCmd() class. |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 18 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 19 | |
| 20 | def _DoMakeChroot(cros_env, chroot_config, clean_first): |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 21 | """Build the chroot, if needed. |
| 22 | |
| 23 | Args: |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 24 | cros_env: Chromite environment to use for this command. |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 25 | 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 Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 34 | cros_env.GetOperation().Info('%s already exists, skipping make_chroot.' % |
| 35 | chroot_dir) |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 36 | return |
| 37 | |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 38 | # Put together command. |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 39 | arg_list = [ |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 40 | '--chroot="%s"' % chroot_dir, |
| 41 | chroot_config.get('CHROOT', 'make_chroot_flags'), |
| 42 | ] |
| 43 | if clean_first: |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 44 | arg_list.insert(0, '--replace') |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 45 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 46 | cros_env.RunScript('MAKING THE CHROOT', './make_chroot', arg_list) |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 47 | |
| 48 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 49 | def _DoSetupBoard(cros_env, build_config, clean_first): |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 50 | """Setup the board, if needed. |
| 51 | |
| 52 | This just runs the setup_board command with the proper args, if needed. |
| 53 | |
| 54 | Args: |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 55 | cros_env: Chromite environment to use for this command. |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 56 | 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 Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 62 | cros_env.GetOperation().Info('%s already exists, skipping setup_board.' % |
| 63 | board_dir) |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 64 | return |
| 65 | |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 66 | # Put together command. |
| 67 | cmd_list = [ |
Doug Anderson | 6f53061 | 2011-02-11 13:19:25 -0800 | [diff] [blame] | 68 | '--board="%s"' % build_config.get('DEFAULT', 'target'), |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 69 | build_config.get('BUILD', 'setup_board_flags'), |
| 70 | ] |
| 71 | if clean_first: |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 72 | arg_list.insert(0, '--force') |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 73 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 74 | cros_env.RunScript('SETTING UP THE BOARD', './setup_board', arg_list) |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 75 | |
| 76 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 77 | def _DoBuildPackages(cros_env, build_config): |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 78 | """Build packages. |
| 79 | |
| 80 | This just runs the build_packages command with the proper args. |
| 81 | |
| 82 | Args: |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 83 | cros_env: Chromite environment to use for this command. |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 84 | build_config: A SafeConfigParser representing the build config. |
| 85 | """ |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 86 | |
| 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 Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 90 | arg_list = ['--board="%s"' % build_config.get('DEFAULT', 'target'), |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 91 | build_config.get('BUILD', 'build_packages_flags') |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 92 | ] |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 93 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 94 | cros_env.RunScript('BUILDING PACKAGES', './build_packages', arg_list, |
| 95 | shell_vars=build_config.get('BUILD', 'build_packages_environ')) |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 96 | |
| 97 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 98 | def _DoBuildImage(cros_env, build_config): |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 99 | """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 Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 106 | |
| 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 Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 110 | arg_list = ['--board="%s"' % build_config.get('DEFAULT', 'target'), |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 111 | build_config.get('IMAGE', 'build_image_flags') |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 112 | ] |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 113 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 114 | cros_env.RunScript('BUILDING THE IMAGE', './build_image', arg_list, |
| 115 | shell_vars=build_config.get('IMAGE', 'build_image_environ')) |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 116 | |
| 117 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 118 | def _DoImagePostProcessing(cros_env, build_config): |
Doug Anderson | 36f7542 | 2011-02-11 13:34:08 -0800 | [diff] [blame] | 119 | """Do post processing steps after the build image runs. |
| 120 | |
| 121 | Args: |
| 122 | build_config: A SafeConfigParser representing the build config. |
| 123 | """ |
Doug Anderson | 36f7542 | 2011-02-11 13:34:08 -0800 | [diff] [blame] | 124 | # 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 Anderson | 36f7542 | 2011-02-11 13:34:08 -0800 | [diff] [blame] | 129 | # 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 Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 134 | cros_env.RunScript('IMAGING POST-PROCESS: %s' % step_name, '', [cmd]) |
Doug Anderson | 36f7542 | 2011-02-11 13:34:08 -0800 | [diff] [blame] | 135 | |
| 136 | |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 137 | class 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) |
Simon Glass | f4616ab | 2011-03-30 13:19:16 -0700 | [diff] [blame] | 159 | # This option won't work until a later CL plumbs in optparse |
| 160 | #parser.add_option('--clean', default=False, action='store_true', |
| 161 | #help='Clean before building.') |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 162 | (options, argv) = parser.parse_args(raw_argv[1:]) |
Simon Glass | d13175d | 2011-04-04 10:06:03 -0700 | [diff] [blame^] | 163 | options.clean = False |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 164 | |
| 165 | # Load the build config if needed... |
| 166 | if not loaded_config: |
| 167 | argv, build_config = utils.GetBuildConfigFromArgs(argv) |
| 168 | if argv: |
| 169 | cros_lib.Die('Unknown arguments: %s' % ' '.join(argv)) |
| 170 | |
| 171 | if not cros_lib.IsInsideChroot(): |
| 172 | # Note: we only want to clean the chroot if they do --clean and have the |
| 173 | # host target. If they do --clean and have a board target, it means |
| 174 | # that they just want to clean the board... |
| 175 | want_clean_chroot = options.clean and build_config is None |
| 176 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 177 | _DoMakeChroot(self.cros_env, chroot_config, want_clean_chroot) |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 178 | |
| 179 | if build_config is not None: |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 180 | self._oper.Info('ENTERING THE CHROOT') |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 181 | utils.EnterChroot(chroot_config, (self, 'Run'), raw_argv, |
| 182 | build_config=build_config, loaded_config=True) |
| 183 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 184 | self._oper.Info('Done building.') |
Doug Anderson | a9b1090 | 2011-02-01 17:54:31 -0800 | [diff] [blame] | 185 | else: |
| 186 | if build_config is None: |
| 187 | cros_lib.Die("You can't build the host chroot from within the chroot.") |
| 188 | |
Simon Glass | 5329b93 | 2011-03-14 16:49:04 -0700 | [diff] [blame] | 189 | _DoSetupBoard(self.cros_env, build_config, options.clean) |
| 190 | _DoBuildPackages(self.cros_env, build_config) |
| 191 | _DoBuildImage(self.cros_env, build_config) |
| 192 | _DoImagePostProcessing(self.cros_env, build_config) |