George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 1 | # Copyright 2020 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 | |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 5 | """Determines all Chrome OS packages that are marked as `hot`. |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 6 | |
| 7 | Dumps results as a list of package names to a JSON file. Hotness is |
| 8 | determined by statically analyzing an ebuild. |
| 9 | |
| 10 | Primarily intended for use by the Chrome OS toolchain team. |
| 11 | """ |
| 12 | |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 13 | import json |
Chris McDonald | 59650c3 | 2021-07-20 15:29:28 -0600 | [diff] [blame] | 14 | import logging |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 15 | from pathlib import Path |
| 16 | from typing import Iterable, List, Tuple |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 17 | |
| 18 | from chromite.lib import commandline |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 19 | from chromite.lib import portage_util |
| 20 | |
| 21 | |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 22 | def contains_ebuild_hot_marker(file_path: Path): |
| 23 | """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 IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 26 | |
| 27 | |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 28 | def locate_all_package_ebuilds( |
| 29 | overlays: Iterable[Path]) -> Iterable[Tuple[Path, str, List[Path]]]: |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 30 | """Determines package -> ebuild mappings for all packages. |
| 31 | |
| 32 | Yields a series of (package_path, package_name, [path_to_ebuilds]). This may |
| 33 | yield the same package name multiple times if it's available in multiple |
| 34 | overlays. |
| 35 | """ |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 36 | for overlay in overlays: |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 37 | # Note that portage_util.GetOverlayEBuilds can't be used here, since that |
| 38 | # specifically only searches for cros_workon candidates. We care about |
| 39 | # everything we can possibly build. |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 40 | for package_dir in overlay.glob('*/*'): |
| 41 | ebuilds = list(package_dir.glob('*.ebuild')) |
| 42 | if ebuilds: |
| 43 | package_name = f'{package_dir.parent.name}/{package_dir.name}' |
| 44 | yield package_dir, package_name, ebuilds |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 45 | |
| 46 | |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 47 | def locate_all_hot_env_packages(overlays: Iterable[Path]) -> Iterable[str]: |
| 48 | """Yields packages marked hot by files in chromeos/config/env.""" |
| 49 | for overlay in overlays: |
| 50 | env_dir = overlay / 'chromeos' / 'config' / 'env' |
| 51 | for f in env_dir.glob('*/*'): |
| 52 | if f.is_file() and contains_ebuild_hot_marker(f): |
| 53 | yield f'{f.parent.name}/{f.name}' |
| 54 | |
| 55 | |
| 56 | def main(argv: List[str]): |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 57 | parser = commandline.ArgumentParser(description=__doc__) |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 58 | parser.add_argument('--output', required=True, type=Path) |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 59 | opts = parser.parse_args(argv) |
| 60 | |
| 61 | ebuilds_found = 0 |
| 62 | packages_found = 0 |
| 63 | merged_packages = 0 |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 64 | |
| 65 | overlays = portage_util.FindOverlays(overlay_type='both') |
| 66 | logging.debug('Found overlays %s', overlays) |
| 67 | overlays = [Path(x) for x in overlays] |
| 68 | |
| 69 | mappings = {x: True for x in locate_all_hot_env_packages(overlays)} |
| 70 | logging.debug('Found hot packages %r from env search', sorted(mappings)) |
| 71 | for package_dir, package, ebuilds in locate_all_package_ebuilds(overlays): |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 72 | packages_found += 1 |
| 73 | ebuilds_found += len(ebuilds) |
| 74 | logging.debug('Found package %r in %r with ebuilds %r', package, |
| 75 | package_dir, ebuilds) |
| 76 | |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 77 | is_marked_hot = any(contains_ebuild_hot_marker(x) for x in ebuilds) |
George Burgess IV | 85e6933 | 2020-01-16 17:33:16 -0800 | [diff] [blame] | 78 | if is_marked_hot: |
| 79 | logging.debug('Package is marked as hot') |
| 80 | else: |
| 81 | logging.debug('Package is not marked as hot') |
| 82 | |
| 83 | if package in mappings: |
| 84 | logging.warning('Multiple entries found for package %r; merging', package) |
| 85 | merged_packages += 1 |
| 86 | mappings[package] = is_marked_hot or mappings[package] |
| 87 | else: |
| 88 | mappings[package] = is_marked_hot |
| 89 | |
| 90 | hot_packages = sorted( |
| 91 | package for package, is_hot in mappings.items() if is_hot) |
| 92 | |
| 93 | logging.info('%d ebuilds found', ebuilds_found) |
| 94 | logging.info('%d packages found', packages_found) |
| 95 | logging.info('%d packages merged', merged_packages) |
| 96 | logging.info('%d hot packages found, total', len(hot_packages)) |
| 97 | |
George Burgess IV | 87c4dbf | 2022-03-21 12:05:11 -0700 | [diff] [blame^] | 98 | opts.output.write_text(json.dumps(hot_packages), encoding='utf-8') |