Mike Frysinger | f1ba7ad | 2022-09-12 05:42:57 -0400 | [diff] [blame] | 1 | # Copyright 2018 The ChromiumOS Authors |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | """Choose the profile for a board that has been or is being setup.""" |
| 6 | |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 7 | import functools |
Chris McDonald | 59650c3 | 2021-07-20 15:29:28 -0600 | [diff] [blame] | 8 | import logging |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 9 | import os |
Alex Klein | 9e7b29e | 2023-04-11 16:10:31 -0600 | [diff] [blame^] | 10 | from typing import Optional |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 11 | |
Mike Frysinger | 06a51c8 | 2021-04-06 11:39:17 -0400 | [diff] [blame] | 12 | from chromite.lib import build_target_lib |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 13 | from chromite.lib import commandline |
| 14 | from chromite.lib import cros_build_lib |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 15 | from chromite.lib import osutils |
| 16 | from chromite.lib import sysroot_lib |
| 17 | |
| 18 | |
| 19 | # Default value constants. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 20 | _DEFAULT_PROFILE = "base" |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 21 | |
| 22 | |
| 23 | def PathPrefixDecorator(f): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 24 | """Add a prefix to the path or paths returned by the decorated function. |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 25 | |
Alex Klein | 9e7b29e | 2023-04-11 16:10:31 -0600 | [diff] [blame^] | 26 | Will not prepend the prefix if the path already starts with the prefix, so |
| 27 | the decorator may be applied to functions that have mixed sources that may |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 28 | or may not already have applied them. This is especially useful for allowing |
| 29 | tests and CLI args a little more leniency in how paths are provided. |
| 30 | """ |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 31 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 32 | @functools.wraps(f) |
| 33 | def wrapper(*args, **kwargs): |
| 34 | result = f(*args, **kwargs) |
| 35 | prefix = PathPrefixDecorator.prefix |
Mike Frysinger | 18a4fe2 | 2022-04-21 21:12:23 -0400 | [diff] [blame] | 36 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 37 | if not prefix or not result: |
| 38 | # Nothing to do. |
| 39 | return result |
Mike Frysinger | 18a4fe2 | 2022-04-21 21:12:23 -0400 | [diff] [blame] | 40 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 41 | # Convert Path objects to str. |
| 42 | if isinstance(prefix, os.PathLike): |
| 43 | prefix = str(prefix) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 44 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 45 | if not isinstance(result, str): |
| 46 | # Transform each path in the collection. |
| 47 | new_result = [] |
| 48 | for path in result: |
| 49 | prefixed_path = os.path.join(prefix, path.lstrip(os.sep)) |
| 50 | new_result.append( |
| 51 | path if path.startswith(prefix) else prefixed_path |
| 52 | ) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 53 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 54 | return new_result |
| 55 | elif not result.startswith(prefix): |
| 56 | # Add the prefix. |
| 57 | return os.path.join(prefix, result.lstrip(os.sep)) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 58 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 59 | # An already prefixed path. |
| 60 | return result |
| 61 | |
| 62 | return wrapper |
| 63 | |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 64 | |
| 65 | PathPrefixDecorator.prefix = None |
| 66 | |
| 67 | |
| 68 | class Error(Exception): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 69 | """Base error for custom exceptions in this script.""" |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 70 | |
| 71 | |
| 72 | class InvalidArgumentsError(Error): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 73 | """Invalid arguments.""" |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 74 | |
| 75 | |
| 76 | class MakeProfileIsNotLinkError(Error): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 77 | """The make profile exists but is not a link.""" |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 78 | |
| 79 | |
| 80 | class ProfileDirectoryNotFoundError(Error): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 81 | """Unable to find the profile directory.""" |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 82 | |
| 83 | |
| 84 | def ChooseProfile(board, profile): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 85 | """Make the link to choose the profile, print relevant warnings. |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 86 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 87 | Args: |
| 88 | board: Board - the board being used. |
| 89 | profile: Profile - the profile being used. |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 90 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 91 | Raises: |
| 92 | OSError when the board's make_profile path exists and is not a link. |
| 93 | """ |
| 94 | if not os.path.isfile(os.path.join(profile.directory, "parent")): |
| 95 | logging.warning( |
| 96 | "Portage profile directory %s has no 'parent' file. " |
| 97 | "This likely means your profile directory is invalid and " |
| 98 | "build_packages will fail.", |
| 99 | profile.directory, |
| 100 | ) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 101 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 102 | current_profile = None |
| 103 | if os.path.exists(board.make_profile): |
Alex Klein | 9e7b29e | 2023-04-11 16:10:31 -0600 | [diff] [blame^] | 104 | # Only try to read if it exists; we only want it to raise an error when |
| 105 | # the path exists and is not a link. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 106 | try: |
| 107 | current_profile = os.readlink(board.make_profile) |
| 108 | except OSError: |
| 109 | raise MakeProfileIsNotLinkError( |
| 110 | "%s is not a link." % board.make_profile |
| 111 | ) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 112 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 113 | if current_profile == profile.directory: |
| 114 | # The existing link is what we were going to make, so nothing to do. |
| 115 | return |
| 116 | elif current_profile is not None: |
| 117 | # It exists and is changing, emit warning. |
| 118 | fmt = {"board": board.board_variant, "profile": profile.name} |
| 119 | msg = ( |
Alex Klein | 9e7b29e | 2023-04-11 16:10:31 -0600 | [diff] [blame^] | 120 | "You are switching profiles for a board that is already setup. " |
| 121 | "This can cause trouble for Portage. If you experience problems " |
| 122 | "with build_packages you may need to run:\n" |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 123 | "\t'setup_board --board %(board)s --force --profile %(profile)s'\n" |
| 124 | "\nAlternatively, you can correct the dependency graph by using " |
| 125 | "'emerge-%(board)s -c' or 'emerge-%(board)s -C <ebuild>'." |
| 126 | ) |
| 127 | logging.warning(msg, fmt) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 128 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 129 | # Make the symlink, overwrites existing link if one already exists. |
| 130 | osutils.SafeSymlink(profile.directory, board.make_profile, sudo=True) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 131 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 132 | # Update the profile override value. |
| 133 | if profile.override: |
| 134 | board.profile_override = profile.override |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 135 | |
| 136 | |
| 137 | class Profile(object): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 138 | """Simple data container class for the profile data.""" |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 139 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 140 | def __init__(self, name, directory, override): |
| 141 | self.name = name |
| 142 | self._directory = directory |
| 143 | self.override = override |
| 144 | |
| 145 | @property |
| 146 | @PathPrefixDecorator |
| 147 | def directory(self): |
| 148 | return self._directory |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 149 | |
| 150 | |
| 151 | def _GetProfile(opts, board): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 152 | """Get the profile list.""" |
| 153 | # Determine the override value - which profile is being selected. |
| 154 | override = opts.profile if opts.profile else board.profile_override |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 155 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 156 | profile = _DEFAULT_PROFILE |
| 157 | profile_directory = None |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 158 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 159 | if override and os.path.exists(override): |
| 160 | profile_directory = os.path.abspath(override) |
| 161 | profile = os.path.basename(profile_directory) |
| 162 | elif override: |
| 163 | profile = override |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 164 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 165 | if profile_directory is None: |
Alex Klein | 9e7b29e | 2023-04-11 16:10:31 -0600 | [diff] [blame^] | 166 | # Build profile directories in reverse order, so we can search from most |
| 167 | # to least specific. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 168 | profile_dirs = [ |
| 169 | "%s/profiles/%s" % (overlay, profile) |
| 170 | for overlay in reversed(board.overlays) |
| 171 | ] |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 172 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 173 | for profile_dir in profile_dirs: |
| 174 | if os.path.isdir(profile_dir): |
| 175 | profile_directory = profile_dir |
| 176 | break |
| 177 | else: |
| 178 | searched = ", ".join(profile_dirs) |
| 179 | raise ProfileDirectoryNotFoundError( |
| 180 | "Profile directory not found, searched in (%s)." % searched |
| 181 | ) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 182 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 183 | return Profile(profile, profile_directory, override) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 184 | |
| 185 | |
| 186 | class Board(object): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 187 | """Manage the board arguments and configs.""" |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 188 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 189 | # Files located on the board. |
| 190 | MAKE_PROFILE = "%(board_root)s/etc/portage/make.profile" |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 191 | |
Alex Klein | 9e7b29e | 2023-04-11 16:10:31 -0600 | [diff] [blame^] | 192 | def __init__( |
| 193 | self, |
| 194 | board: Optional[str] = None, |
| 195 | variant: Optional[str] = None, |
| 196 | board_root: Optional[str] = None, |
| 197 | ): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 198 | """Board constructor. |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 199 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 200 | board [+ variant] is given preference when both board and board_root are |
| 201 | provided. |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 202 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 203 | Preconditions: |
Alex Klein | 9e7b29e | 2023-04-11 16:10:31 -0600 | [diff] [blame^] | 204 | Either board and build_root are not None, or board_root is not None. |
| 205 | With board + build_root we can construct the board root. |
| 206 | With the board root we can have the board directory. |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 207 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 208 | Args: |
Alex Klein | 9e7b29e | 2023-04-11 16:10:31 -0600 | [diff] [blame^] | 209 | board: The board name. |
| 210 | variant: The variant name. TODO: Deprecate? |
| 211 | board_root: The boards fully qualified build directory path. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 212 | """ |
| 213 | if not board and not board_root: |
| 214 | # Enforce preconditions. |
| 215 | raise InvalidArgumentsError( |
| 216 | "Either board or board_root must be " "provided." |
| 217 | ) |
| 218 | elif board: |
| 219 | # The board and variant can be specified separately, or can both be |
| 220 | # contained in the board name, separated by an underscore. |
| 221 | board_split = board.split("_") |
| 222 | variant_default = variant |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 223 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 224 | self._board_root = None |
| 225 | else: |
| 226 | self._board_root = os.path.normpath(board_root) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 227 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 228 | board_split = os.path.basename(self._board_root).split("_") |
| 229 | variant_default = None |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 230 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 231 | self.board = board_split.pop(0) |
| 232 | self.variant = board_split.pop(0) if board_split else variant_default |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 233 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 234 | if self.variant: |
| 235 | self.board_variant = "%s_%s" % (self.board, self.variant) |
| 236 | else: |
| 237 | self.board_variant = self.board |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 238 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 239 | self.make_profile = self.MAKE_PROFILE % {"board_root": self.root} |
Alex Klein | 9e7b29e | 2023-04-11 16:10:31 -0600 | [diff] [blame^] | 240 | # This must come after the arguments required to build each variant of |
| 241 | # the build root have been processed. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 242 | self._sysroot_config = sysroot_lib.Sysroot(self.root) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 243 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 244 | @property |
| 245 | @PathPrefixDecorator |
| 246 | def root(self): |
| 247 | if self._board_root: |
| 248 | return self._board_root |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 249 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 250 | return build_target_lib.get_default_sysroot_path(self.board_variant) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 251 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 252 | @property |
| 253 | @PathPrefixDecorator |
| 254 | def overlays(self): |
| 255 | return self._sysroot_config.GetStandardField( |
| 256 | sysroot_lib.STANDARD_FIELD_BOARD_OVERLAY |
| 257 | ).split() |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 258 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 259 | @property |
| 260 | def profile_override(self): |
| 261 | return self._sysroot_config.GetCachedField("PROFILE_OVERRIDE") |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 262 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 263 | @profile_override.setter |
| 264 | def profile_override(self, value): |
| 265 | self._sysroot_config.SetCachedField("PROFILE_OVERRIDE", value) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 266 | |
| 267 | |
| 268 | def _GetBoard(opts): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 269 | """Factory method to build a Board from the parsed CLI arguments.""" |
| 270 | return Board( |
| 271 | board=opts.board, variant=opts.variant, board_root=opts.board_root |
| 272 | ) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 273 | |
| 274 | |
| 275 | def GetParser(): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 276 | """ArgumentParser builder and argument definitions.""" |
| 277 | parser = commandline.ArgumentParser(description=__doc__) |
| 278 | parser.add_argument( |
| 279 | "-b", |
| 280 | "--board", |
| 281 | default=os.environ.get("DEFAULT_BOARD"), |
| 282 | help="The name of the board to set up.", |
| 283 | ) |
| 284 | parser.add_argument( |
| 285 | "-r", |
| 286 | "--board-root", |
| 287 | type="path", |
| 288 | help="Board root where the profile should be created.", |
| 289 | ) |
| 290 | parser.add_argument( |
| 291 | "-p", "--profile", help="The portage configuration profile to use." |
| 292 | ) |
| 293 | parser.add_argument("--variant", help="Board variant.") |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 294 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 295 | group = parser.add_argument_group("Advanced options") |
| 296 | group.add_argument( |
| 297 | "--filesystem-prefix", |
| 298 | type="path", |
| 299 | help="Force filesystem accesses to be prefixed by the " "given path.", |
| 300 | ) |
| 301 | return parser |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 302 | |
| 303 | |
| 304 | def ParseArgs(argv): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 305 | """Parse and validate the arguments.""" |
| 306 | parser = GetParser() |
| 307 | opts = parser.parse_args(argv) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 308 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 309 | # See Board.__init__ Preconditions. |
| 310 | board_valid = opts.board is not None |
| 311 | board_root_valid = opts.board_root and os.path.exists(opts.board_root) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 312 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 313 | if not board_valid and not board_root_valid: |
| 314 | parser.error("Either board or board_root must be provided.") |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 315 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 316 | PathPrefixDecorator.prefix = opts.filesystem_prefix |
| 317 | del opts.filesystem_prefix |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 318 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 319 | opts.Freeze() |
| 320 | return opts |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 321 | |
| 322 | |
| 323 | def main(argv): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 324 | # Parse arguments. |
| 325 | opts = ParseArgs(argv) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 326 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 327 | # Build and validate the board and profile. |
| 328 | board = _GetBoard(opts) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 329 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 330 | if not os.path.exists(board.root): |
| 331 | cros_build_lib.Die( |
| 332 | "The board has not been setup, please run setup_board " "first." |
| 333 | ) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 334 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 335 | try: |
| 336 | profile = _GetProfile(opts, board) |
| 337 | except ProfileDirectoryNotFoundError as e: |
| 338 | cros_build_lib.Die(e) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 339 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 340 | # Change the profile to the selected. |
| 341 | logging.info("Selecting profile: %s for %s", profile.directory, board.root) |
Alex Klein | a2ceb19 | 2018-08-17 11:19:32 -0600 | [diff] [blame] | 342 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 343 | try: |
| 344 | ChooseProfile(board, profile) |
| 345 | except MakeProfileIsNotLinkError as e: |
| 346 | cros_build_lib.Die(e) |