blob: 2dc7a93015731b2bc3cf508978cc745190064017 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2022 The ChromiumOS Authors
Cindy Linc06b4ea2022-01-27 18:13:04 +00002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Jack Rosenthal769a0512023-05-25 18:04:50 -06005"""build_packages updates the set of binary packages needed by ChromiumOS.
Cindy Linc06b4ea2022-01-27 18:13:04 +00006
7The build_packages process cross compiles all packages that have been
8updated into the given sysroot and builds binary packages as a side-effect.
9The output packages will be used by the build_image script to create a
Jack Rosenthal769a0512023-05-25 18:04:50 -060010bootable ChromiumOS image.
Ram Chandrasekarbaa89632022-02-11 23:22:09 +000011
Jack Rosenthal769a0512023-05-25 18:04:50 -060012If packages are specified in the command line, only build those specific
13packages and any dependencies they might need.
Cindy Linc06b4ea2022-01-27 18:13:04 +000014"""
15
Ram Chandrasekarbaa89632022-02-11 23:22:09 +000016import argparse
Alex Kleinfba23ba2022-02-03 11:58:48 -070017import logging
Cindy Linc06b4ea2022-01-27 18:13:04 +000018import os
Mike Frysinger807d8282022-04-28 22:45:17 -040019from typing import List, Optional, Tuple
Alex Kleinfba23ba2022-02-03 11:58:48 -070020import urllib.error
21import urllib.request
Cindy Linc06b4ea2022-01-27 18:13:04 +000022
Lizzy Presland453237c2023-05-31 00:16:15 +000023from chromite.third_party.opentelemetry import trace
24
Cindy Lin7487daa2022-02-23 04:14:10 +000025from chromite.lib import build_target_lib
Alex Kleina39dc982022-02-03 12:13:14 -070026from chromite.lib import commandline
Cindy Linc06b4ea2022-01-27 18:13:04 +000027from chromite.lib import cros_build_lib
Cindy Lin7487daa2022-02-23 04:14:10 +000028from chromite.lib import sysroot_lib
Ram Chandrasekarbdec0f02022-02-24 01:20:17 +000029from chromite.service import sysroot
Lizzy Presland453237c2023-05-31 00:16:15 +000030from chromite.utils import telemetry
Cindy Linb7f89a42022-05-23 16:50:00 +000031from chromite.utils import timer
Cindy Linc06b4ea2022-01-27 18:13:04 +000032
33
Alex Klein1699fab2022-09-08 08:46:06 -060034def build_shell_bool_style_args(
35 parser: commandline.ArgumentParser,
36 name: str,
37 default_val: bool,
38 help_str: str,
39 deprecation_note: str,
40 alternate_name: Optional[str] = None,
41) -> None:
42 """Build the shell boolean input argument equivalent.
Alex Kleina39dc982022-02-03 12:13:14 -070043
Alex Klein1699fab2022-09-08 08:46:06 -060044 There are two cases which we will need to handle,
45 case 1: A shell boolean arg, which doesn't need to be re-worded in python.
46 case 2: A shell boolean arg, which needs to be re-worded in python.
47 Example below.
48 For Case 1, for a given input arg name 'argA', we create three python
49 arguments.
50 --argA, --noargA, --no-argA. The arguments --argA and --no-argA will be
51 retained after deprecating --noargA.
52 For Case 2, for a given input arg name 'arg_A' we need to use alternate
53 argument name 'arg-A'. we create four python arguments in this case.
54 --arg_A, --noarg_A, --arg-A, --no-arg-A. The first two arguments will be
55 deprecated later.
56 TODO(b/218522717): Remove the creation of --noargA in case 1 and --arg_A and
57 --noarg_A in case 2.
Ram Chandrasekarbaa89632022-02-11 23:22:09 +000058
Alex Klein1699fab2022-09-08 08:46:06 -060059 Args:
Trent Apted66736d82023-05-25 10:38:28 +100060 parser: The parser to update.
61 name: The input argument name. This will be used as 'dest' variable
62 name.
63 default_val: The default value to assign.
64 help_str: The help string for the input argument.
65 deprecation_note: A deprecation note to use.
66 alternate_name: Alternate argument to be used after deprecation.
Alex Klein1699fab2022-09-08 08:46:06 -060067 """
68 arg = f"--{name}"
69 shell_narg = f"--no{name}"
70 py_narg = f"--no-{name}"
71 alt_arg = f"--{alternate_name}" if alternate_name else None
72 alt_py_narg = f"--no-{alternate_name}" if alternate_name else None
73 default_val_str = f"{help_str} (Default: %(default)s)."
Ram Chandrasekarbaa89632022-02-11 23:22:09 +000074
Alex Klein1699fab2022-09-08 08:46:06 -060075 if alternate_name:
76 parser.add_argument(
77 alt_arg,
78 action="store_true",
79 default=default_val,
80 dest=name,
81 help=default_val_str,
82 )
83 parser.add_argument(
84 alt_py_narg,
85 action="store_false",
86 dest=name,
87 help="Don't " + help_str.lower(),
88 )
89
Ram Chandrasekarbaa89632022-02-11 23:22:09 +000090 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -060091 arg,
92 action="store_true",
Ram Chandrasekarbaa89632022-02-11 23:22:09 +000093 default=default_val,
94 dest=name,
Alex Klein1699fab2022-09-08 08:46:06 -060095 deprecated=deprecation_note % alt_arg if alternate_name else None,
96 help=default_val_str if not alternate_name else argparse.SUPPRESS,
97 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +000098 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -060099 shell_narg,
100 action="store_false",
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000101 dest=name,
Alex Klein1699fab2022-09-08 08:46:06 -0600102 deprecated=deprecation_note % alt_py_narg
103 if alternate_name
104 else py_narg,
105 help=argparse.SUPPRESS,
106 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000107
Alex Klein1699fab2022-09-08 08:46:06 -0600108 if not alternate_name:
109 parser.add_argument(
110 py_narg,
111 action="store_false",
112 dest=name,
113 help="Don't " + help_str.lower(),
114 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000115
116
117def get_parser() -> commandline.ArgumentParser:
Alex Klein1699fab2022-09-08 08:46:06 -0600118 """Creates the cmdline argparser, populates the options and description.
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000119
Alex Klein1699fab2022-09-08 08:46:06 -0600120 Returns:
Trent Apted66736d82023-05-25 10:38:28 +1000121 Argument parser.
Alex Klein1699fab2022-09-08 08:46:06 -0600122 """
123 deprecation_note = "Argument will be removed July, 2022. Use %s instead."
124 parser = commandline.ArgumentParser(description=__doc__)
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000125
Alex Klein1699fab2022-09-08 08:46:06 -0600126 parser.add_argument(
127 "-b",
128 "--board",
129 "--build-target",
130 dest="board",
131 default=cros_build_lib.GetDefaultBoard(),
132 help="The board to build packages for.",
133 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000134
Alex Klein1699fab2022-09-08 08:46:06 -0600135 build_shell_bool_style_args(
136 parser,
137 "usepkg",
138 True,
139 "Use binary packages to bootstrap when possible.",
140 deprecation_note,
141 )
142 build_shell_bool_style_args(
143 parser,
144 "usepkgonly",
145 False,
146 "Use binary packages only to bootstrap; abort if any are missing.",
147 deprecation_note,
148 )
149 build_shell_bool_style_args(
150 parser, "workon", True, "Force-build workon packages.", deprecation_note
151 )
152 build_shell_bool_style_args(
153 parser,
154 "withrevdeps",
155 True,
156 "Calculate reverse dependencies on changed ebuilds.",
157 deprecation_note,
158 )
159 build_shell_bool_style_args(
160 parser,
161 "cleanbuild",
162 False,
163 "Perform a clean build; delete sysroot if it exists before building.",
164 deprecation_note,
165 )
166 build_shell_bool_style_args(
167 parser,
168 "pretend",
169 False,
170 "Pretend building packages, just display which packages would have "
171 "been installed.",
172 deprecation_note,
173 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000174
Alex Klein1699fab2022-09-08 08:46:06 -0600175 # The --sysroot flag specifies the environment variables ROOT and PKGDIR.
176 # This allows fetching and emerging of all packages to specified sysroot.
177 # Note that --sysroot will setup the board normally in /build/$BOARD, if
178 # it's not setup yet. It also expects the toolchain to already be installed
179 # in the sysroot.
180 # --usepkgonly and --norebuild are required, because building is not
181 # supported when board_root is set.
182 parser.add_argument(
183 "--sysroot", type="path", help="Emerge packages to sysroot."
184 )
185 parser.add_argument(
186 "--board_root",
187 type="path",
188 dest="sysroot",
189 deprecated=deprecation_note % "--sysroot",
190 help=argparse.SUPPRESS,
191 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000192
Alex Klein1699fab2022-09-08 08:46:06 -0600193 # CPU Governor related options.
194 group = parser.add_argument_group("CPU Governor Options")
195 build_shell_bool_style_args(
196 group,
197 "autosetgov",
198 False,
199 "Automatically set cpu governor to 'performance'.",
200 deprecation_note,
201 )
202 build_shell_bool_style_args(
203 group,
204 "autosetgov_sticky",
205 False,
206 "Remember --autosetgov setting for future runs.",
207 deprecation_note,
208 alternate_name="autosetgov-sticky",
209 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000210
Alex Klein1699fab2022-09-08 08:46:06 -0600211 # Chrome building related options.
212 group = parser.add_argument_group("Chrome Options")
213 build_shell_bool_style_args(
214 group,
215 "use_any_chrome",
216 True,
217 "Use any Chrome prebuilt available, even if the prebuilt doesn't "
218 "match exactly.",
219 deprecation_note,
220 alternate_name="use-any-chrome",
221 )
222 build_shell_bool_style_args(
223 group,
224 "internal",
225 False,
Alex Kleind7197402023-04-05 13:05:29 -0600226 "Build the internal version of chrome (set the chrome_internal USE "
227 "flag).",
Alex Klein1699fab2022-09-08 08:46:06 -0600228 deprecation_note,
229 )
230 build_shell_bool_style_args(
231 group,
232 "chrome",
233 False,
234 "Ensure chrome instead of chromium. Alias for "
235 "--internal --no-use-any-chrome.",
236 deprecation_note,
237 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000238
Alex Klein1699fab2022-09-08 08:46:06 -0600239 # Setup board related options.
240 group = parser.add_argument_group("Setup Board Config Options")
241 build_shell_bool_style_args(
242 group,
243 "skip_chroot_upgrade",
244 False,
245 "Skip the automatic chroot upgrade; use with care.",
246 deprecation_note,
247 alternate_name="skip-chroot-upgrade",
248 )
249 build_shell_bool_style_args(
250 group,
251 "skip_toolchain_update",
252 False,
253 "Skip automatic toolchain update",
254 deprecation_note,
255 alternate_name="skip-toolchain-update",
256 )
257 build_shell_bool_style_args(
258 group,
259 "skip_setup_board",
260 False,
261 "Skip running setup_board. Implies "
262 "--skip-chroot-upgrade --skip-toolchain-update.",
263 deprecation_note,
264 alternate_name="skip-setup-board",
265 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000266
Alex Klein1699fab2022-09-08 08:46:06 -0600267 # Image Type selection related options.
268 group = parser.add_argument_group("Image Type Options")
269 build_shell_bool_style_args(
270 group,
271 "withdev",
272 True,
273 "Build useful developer friendly utilities.",
274 deprecation_note,
275 )
276 build_shell_bool_style_args(
277 group,
278 "withdebug",
279 True,
280 "Build debug versions of Chromium-OS-specific packages.",
281 deprecation_note,
282 )
283 build_shell_bool_style_args(
284 group, "withfactory", True, "Build factory installer.", deprecation_note
285 )
286 build_shell_bool_style_args(
287 group,
288 "withtest",
289 True,
290 "Build packages required for testing.",
291 deprecation_note,
292 )
293 build_shell_bool_style_args(
294 group,
295 "withautotest",
296 True,
297 "Build autotest client code.",
298 deprecation_note,
299 )
300 build_shell_bool_style_args(
301 group,
302 "withdebugsymbols",
303 False,
304 "Install the debug symbols for all packages.",
305 deprecation_note,
306 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000307
Alex Klein1699fab2022-09-08 08:46:06 -0600308 # Advanced Options.
309 group = parser.add_argument_group("Advanced Options")
310 group.add_argument(
311 "--accept-licenses", help="Licenses to append to the accept list."
312 )
313 group.add_argument(
314 "--accept_licenses",
315 deprecated=deprecation_note % "--accept-licenses",
316 help=argparse.SUPPRESS,
317 )
318 build_shell_bool_style_args(
319 group,
320 "eclean",
321 True,
322 "Run eclean to delete old binpkgs.",
323 deprecation_note,
324 )
325 group.add_argument(
326 "--jobs",
327 type=int,
328 default=os.cpu_count(),
Trent Apted66736d82023-05-25 10:38:28 +1000329 help="Number of packages to build in parallel. (Default: %(default)s)",
Alex Klein1699fab2022-09-08 08:46:06 -0600330 )
331 build_shell_bool_style_args(
332 group,
333 "rebuild",
334 True,
335 "Automatically rebuild dependencies.",
336 deprecation_note,
337 )
338 # TODO(b/218522717): Remove the --nonorebuild argument support.
339 group.add_argument(
340 "--nonorebuild",
341 action="store_true",
342 dest="rebuild",
343 deprecated=deprecation_note % "--rebuild",
344 help=argparse.SUPPRESS,
345 )
346 build_shell_bool_style_args(
347 group,
348 "expandedbinhosts",
349 True,
350 "Allow expanded binhost inheritance.",
351 deprecation_note,
352 )
353 group.add_argument(
354 "--backtrack",
355 type=int,
356 default=sysroot.BACKTRACK_DEFAULT,
357 help="See emerge --backtrack.",
358 )
Alex Klein062d7282022-07-28 09:03:26 -0600359
Alex Klein1699fab2022-09-08 08:46:06 -0600360 # The --reuse-pkgs-from-local-boards flag tells Portage to share binary
361 # packages between boards that are built locally, so that the total time
362 # required to build several boards is reduced. This flag is only useful
363 # when you are not able to use remote binary packages, since remote binary
364 # packages are usually more up to date than anything you have locally.
365 build_shell_bool_style_args(
366 group,
367 "reuse_pkgs_from_local_boards",
368 False,
369 "Bootstrap from local packages instead of remote packages.",
370 deprecation_note,
371 alternate_name="reuse-pkgs-from-local-boards",
372 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000373
Alex Klein1699fab2022-09-08 08:46:06 -0600374 # --run-goma option is designed to be used on bots.
Alex Kleind7197402023-04-05 13:05:29 -0600375 # If you're trying to build packages with goma in your local dev env, this
376 # is *not* the option you're looking for. Please see comments below.
Alex Klein1699fab2022-09-08 08:46:06 -0600377 # This option; 1) starts goma, 2) builds packages (expecting that goma is
378 # used), then 3) stops goma explicitly.
379 # 4) is a request from the goma team, so that stats/logs can be taken.
Fumitoshi Ukai00becd42023-01-13 12:51:26 +0900380 # Note: GOMA_DIR is expected to be passed via env var.
Alex Klein1699fab2022-09-08 08:46:06 -0600381 #
382 # In local dev env cases, compiler_proxy is expected to keep running.
383 # In such a case;
384 # $ python ${GOMA_DIR}/goma_ctl.py ensure_start
385 # $ build_packages (... and options without --run-goma ...)
386 # is an expected commandline sequence. If you set --run-goma flag while
387 # compiler_proxy is already running, the existing compiler_proxy will be
388 # stopped.
389 build_shell_bool_style_args(
390 group,
391 "run_goma",
392 False,
Alex Kleind7197402023-04-05 13:05:29 -0600393 "When set, (re)starts goma, builds packages, and then stops goma.",
Alex Klein1699fab2022-09-08 08:46:06 -0600394 deprecation_note,
395 alternate_name="run-goma",
396 )
397 # This option is for building chrome remotely.
398 # 1) starts reproxy 2) builds chrome with reproxy and 3) stops reproxy so
399 # logs/stats can be collected.
400 # Note: RECLIENT_DIR and REPROXY_CFG env var will be deprecated July, 2022.
401 # Use --reclient-dir and --reproxy-cfg input options instead.
402 build_shell_bool_style_args(
403 group,
404 "run_remoteexec",
405 False,
406 "If set to true, starts RBE reproxy, builds packages, and then stops "
407 "reproxy.",
408 deprecation_note,
409 )
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000410
Alex Klein1699fab2022-09-08 08:46:06 -0600411 parser.add_argument("packages", nargs="*", help="Packages to build.")
412 return parser
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000413
414
Alex Klein1699fab2022-09-08 08:46:06 -0600415def parse_args(
416 argv: List[str],
417) -> Tuple[commandline.ArgumentParser, commandline.ArgumentNamespace]:
418 """Parse and validate CLI arguments.
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000419
Alex Klein1699fab2022-09-08 08:46:06 -0600420 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000421 argv: Arguments passed via CLI.
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000422
Alex Klein1699fab2022-09-08 08:46:06 -0600423 Returns:
Trent Apted66736d82023-05-25 10:38:28 +1000424 Tuple having the below two,
425 Argument Parser
426 Validated argument namespace.
Alex Klein1699fab2022-09-08 08:46:06 -0600427 """
428 parser = get_parser()
429 opts = parser.parse_args(argv)
Ram Chandrasekarbdec0f02022-02-24 01:20:17 +0000430
Alex Klein1699fab2022-09-08 08:46:06 -0600431 if opts.chrome:
432 opts.internal_chrome = True
433 opts.use_any_chrome = False
Ram Chandrasekarbdec0f02022-02-24 01:20:17 +0000434
Alex Klein1699fab2022-09-08 08:46:06 -0600435 opts.setup_board_run_config = sysroot.SetupBoardRunConfig(
436 force=opts.cleanbuild,
437 usepkg=opts.usepkg,
438 jobs=opts.jobs,
439 quiet=True,
440 update_toolchain=not opts.skip_toolchain_update,
441 upgrade_chroot=not opts.skip_chroot_upgrade,
442 local_build=opts.reuse_pkgs_from_local_boards,
443 expanded_binhost_inheritance=opts.expandedbinhosts,
Cindy Linadc610a2023-05-23 18:46:12 +0000444 use_cq_prebuilts=opts.usepkg,
Alex Klein1699fab2022-09-08 08:46:06 -0600445 backtrack=opts.backtrack,
446 )
447 opts.build_run_config = sysroot.BuildPackagesRunConfig(
448 usepkg=opts.usepkg,
449 install_debug_symbols=opts.withdebugsymbols,
450 packages=opts.packages,
451 use_goma=opts.run_goma,
452 use_remoteexec=opts.run_remoteexec,
453 incremental_build=opts.withrevdeps,
454 dryrun=opts.pretend,
455 usepkgonly=opts.usepkgonly,
456 workon=opts.workon,
457 install_auto_test=opts.withautotest,
458 autosetgov=opts.autosetgov,
459 autosetgov_sticky=opts.autosetgov_sticky,
460 use_any_chrome=opts.use_any_chrome,
461 internal_chrome=opts.internal,
462 clean_build=opts.cleanbuild,
463 eclean=opts.eclean,
464 rebuild_dep=opts.rebuild,
465 jobs=opts.jobs,
466 local_pkg=opts.reuse_pkgs_from_local_boards,
467 dev_image=opts.withdev,
468 factory_image=opts.withfactory,
469 test_image=opts.withtest,
470 debug_version=opts.withdebug,
471 backtrack=opts.backtrack,
472 )
473 opts.Freeze()
474 return parser, opts
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000475
476
Lizzy Presland453237c2023-05-31 00:16:15 +0000477tracer = trace.get_tracer(__name__)
478
479
Alex Klein1699fab2022-09-08 08:46:06 -0600480@timer.timed("Elapsed time (build_packages)")
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000481def main(argv: Optional[List[str]] = None) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600482 commandline.RunInsideChroot()
483 parser, opts = parse_args(argv)
Ram Chandrasekarbaa89632022-02-11 23:22:09 +0000484
Lizzy Presland453237c2023-05-31 00:16:15 +0000485 build_packages(parser, opts)
486
487
488@tracer.start_as_current_span("scripts.build_packages.build_packages")
489def build_packages(
490 parser: commandline.ArgumentParser, opts: commandline.ArgumentNamespace
491):
Alex Kleind7197402023-04-05 13:05:29 -0600492 # If the opts.board is not set, then it means user hasn't specified a
493 # default board in 'src/scripts/.default_board' and didn't specify it as
494 # input argument.
Alex Klein1699fab2022-09-08 08:46:06 -0600495 if not opts.board:
496 parser.error("--board is required")
Ram Chandrasekarbdec0f02022-02-24 01:20:17 +0000497
Alex Klein1699fab2022-09-08 08:46:06 -0600498 build_target = build_target_lib.BuildTarget(
499 opts.board, build_root=opts.sysroot
500 )
501 board_root = sysroot_lib.Sysroot(build_target.root)
Cindy Lin7487daa2022-02-23 04:14:10 +0000502
Alex Kleinfba23ba2022-02-03 11:58:48 -0700503 try:
Alex Klein1699fab2022-09-08 08:46:06 -0600504 # TODO(xcl): Update run_configs to have a common base set of configs for
505 # setup_board and build_packages.
506 if not opts.skip_setup_board:
507 sysroot.SetupBoard(
508 build_target,
509 accept_licenses=opts.accept_licenses,
510 run_configs=opts.setup_board_run_config,
511 )
Sergey Frolovf988de72023-03-06 20:05:21 -0700512
Alex Klein1699fab2022-09-08 08:46:06 -0600513 sysroot.BuildPackages(build_target, board_root, opts.build_run_config)
514 except sysroot_lib.PackageInstallError as e:
515 try:
516 with urllib.request.urlopen(
517 "https://chromiumos-status.appspot.com/current?format=raw"
Sergey Frolov7cf6c0b2022-06-06 16:47:44 -0600518 ) as request:
Alex Klein1699fab2022-09-08 08:46:06 -0600519 logging.notice("Tree Status: %s", request.read().decode())
520 except urllib.error.HTTPError:
521 pass
522 cros_build_lib.Die(e)