blob: 938512835e0ae9bd8b329ebf0e5c73d38dfbafd3 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2020 The ChromiumOS Authors
George Burgess IV85e69332020-01-16 17:33:16 -08002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
George Burgess IV87c4dbf2022-03-21 12:05:11 -07005"""Determines all Chrome OS packages that are marked as `hot`.
George Burgess IV85e69332020-01-16 17:33:16 -08006
7Dumps results as a list of package names to a JSON file. Hotness is
8determined by statically analyzing an ebuild.
9
10Primarily intended for use by the Chrome OS toolchain team.
11"""
12
George Burgess IV85e69332020-01-16 17:33:16 -080013import json
Chris McDonald59650c32021-07-20 15:29:28 -060014import logging
George Burgess IV87c4dbf2022-03-21 12:05:11 -070015from pathlib import Path
16from typing import Iterable, List, Tuple
George Burgess IV85e69332020-01-16 17:33:16 -080017
18from chromite.lib import commandline
George Burgess IV85e69332020-01-16 17:33:16 -080019from chromite.lib import portage_util
20
21
George Burgess IV87c4dbf2022-03-21 12:05:11 -070022def contains_ebuild_hot_marker(file_path: Path):
Alex Klein1699fab2022-09-08 08:46:06 -060023 """Returns whether a file seems to be marked as hot."""
24 ebuild_contents = file_path.read_text(encoding="utf-8")
25 return "cros_optimize_package_for_speed" in ebuild_contents
George Burgess IV85e69332020-01-16 17:33:16 -080026
27
George Burgess IV87c4dbf2022-03-21 12:05:11 -070028def locate_all_package_ebuilds(
Alex Klein1699fab2022-09-08 08:46:06 -060029 overlays: Iterable[Path],
30) -> Iterable[Tuple[Path, str, List[Path]]]:
31 """Determines package -> ebuild mappings for all packages.
George Burgess IV85e69332020-01-16 17:33:16 -080032
Alex Klein1699fab2022-09-08 08:46:06 -060033 Yields a series of (package_path, package_name, [path_to_ebuilds]). This may
34 yield the same package name multiple times if it's available in multiple
35 overlays.
36 """
37 for overlay in overlays:
Alex Klein68b270c2023-04-14 14:42:50 -060038 # Note that portage_util.GetOverlayEBuilds can't be used here, since
39 # that specifically only searches for cros_workon candidates. We care
40 # about everything we can possibly build.
Alex Klein1699fab2022-09-08 08:46:06 -060041 for package_dir in overlay.glob("*/*"):
42 ebuilds = list(package_dir.glob("*.ebuild"))
43 if ebuilds:
44 package_name = f"{package_dir.parent.name}/{package_dir.name}"
45 yield package_dir, package_name, ebuilds
George Burgess IV85e69332020-01-16 17:33:16 -080046
47
George Burgess IV87c4dbf2022-03-21 12:05:11 -070048def locate_all_hot_env_packages(overlays: Iterable[Path]) -> Iterable[str]:
Alex Klein1699fab2022-09-08 08:46:06 -060049 """Yields packages marked hot by files in chromeos/config/env."""
50 for overlay in overlays:
51 env_dir = overlay / "chromeos" / "config" / "env"
52 for f in env_dir.glob("*/*"):
53 if f.is_file() and contains_ebuild_hot_marker(f):
54 yield f"{f.parent.name}/{f.name}"
George Burgess IV87c4dbf2022-03-21 12:05:11 -070055
56
57def main(argv: List[str]):
Alex Klein1699fab2022-09-08 08:46:06 -060058 parser = commandline.ArgumentParser(description=__doc__)
59 parser.add_argument("--output", required=True, type=Path)
60 opts = parser.parse_args(argv)
George Burgess IV85e69332020-01-16 17:33:16 -080061
Alex Klein1699fab2022-09-08 08:46:06 -060062 ebuilds_found = 0
63 packages_found = 0
64 merged_packages = 0
George Burgess IV87c4dbf2022-03-21 12:05:11 -070065
Alex Klein1699fab2022-09-08 08:46:06 -060066 overlays = portage_util.FindOverlays(overlay_type="both")
67 logging.debug("Found overlays %s", overlays)
68 overlays = [Path(x) for x in overlays]
George Burgess IV87c4dbf2022-03-21 12:05:11 -070069
Alex Klein1699fab2022-09-08 08:46:06 -060070 mappings = {x: True for x in locate_all_hot_env_packages(overlays)}
71 logging.debug("Found hot packages %r from env search", sorted(mappings))
72 for package_dir, package, ebuilds in locate_all_package_ebuilds(overlays):
73 packages_found += 1
74 ebuilds_found += len(ebuilds)
75 logging.debug(
76 "Found package %r in %r with ebuilds %r",
77 package,
78 package_dir,
79 ebuilds,
80 )
George Burgess IV85e69332020-01-16 17:33:16 -080081
Alex Klein1699fab2022-09-08 08:46:06 -060082 is_marked_hot = any(contains_ebuild_hot_marker(x) for x in ebuilds)
83 if is_marked_hot:
84 logging.debug("Package is marked as hot")
85 else:
86 logging.debug("Package is not marked as hot")
George Burgess IV85e69332020-01-16 17:33:16 -080087
Alex Klein1699fab2022-09-08 08:46:06 -060088 if package in mappings:
89 logging.warning(
90 "Multiple entries found for package %r; merging", package
91 )
92 merged_packages += 1
93 mappings[package] = is_marked_hot or mappings[package]
94 else:
95 mappings[package] = is_marked_hot
George Burgess IV85e69332020-01-16 17:33:16 -080096
Alex Klein1699fab2022-09-08 08:46:06 -060097 hot_packages = sorted(
98 package for package, is_hot in mappings.items() if is_hot
99 )
George Burgess IV85e69332020-01-16 17:33:16 -0800100
Alex Klein1699fab2022-09-08 08:46:06 -0600101 logging.info("%d ebuilds found", ebuilds_found)
102 logging.info("%d packages found", packages_found)
103 logging.info("%d packages merged", merged_packages)
104 logging.info("%d hot packages found, total", len(hot_packages))
George Burgess IV85e69332020-01-16 17:33:16 -0800105
Alex Klein1699fab2022-09-08 08:46:06 -0600106 opts.output.write_text(json.dumps(hot_packages), encoding="utf-8")