xref: /aosp_15_r20/external/toolchain-utils/llvm_tools/chroot.py (revision 760c253c1ed00ce9abd48f8546f08516e57485fe)
1#!/usr/bin/env python3
2# Copyright 2020 The ChromiumOS Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Chroot helper functions."""
7
8import os
9from pathlib import Path
10import subprocess
11from typing import Iterable, List, Union
12
13
14def InChroot() -> bool:
15    """Returns True if currently in the chroot."""
16    return "CROS_WORKON_SRCROOT" in os.environ
17
18
19def VerifyInsideChroot() -> None:
20    """Checks whether the script invoked was executed in the chroot.
21
22    Raises:
23        AssertionError: The script was run outside the chroot.
24    """
25
26    assert InChroot(), "Script should be run inside the chroot."
27
28
29def VerifyOutsideChroot() -> None:
30    """Checks whether the script invoked was executed in the chroot.
31
32    Raises:
33        AssertionError: The script was run inside the chroot.
34    """
35
36    assert not InChroot(), "Script should be run outside the chroot."
37
38
39def VerifyChromeOSRoot(chromeos_root: Union[Path, str]) -> None:
40    """Checks whether the path actually points to ChromiumOS checkout root.
41
42    Raises:
43        AssertionError: The path is not ChromiumOS checkout root.
44    """
45
46    subdir = "src/third_party/chromiumos-overlay"
47    path = Path(chromeos_root).expanduser() / subdir
48    msg = f"Wrong ChromeOS path. No {subdir} directory in {chromeos_root} ."
49    assert path.is_dir(), msg
50
51
52def FindChromeOSRootAbove(chromeos_tree_path: Path) -> Path:
53    """Returns the root of a ChromeOS tree, given a path in said tree.
54
55    May return `chromeos_tree_path`, if that's already the root of the tree.
56
57    Raises:
58        ValueError if the given path is not in a ChromeOS tree.
59    """
60    if (chromeos_tree_path / ".repo").exists():
61        return chromeos_tree_path
62
63    for parent in chromeos_tree_path.parents:
64        if (parent / ".repo").exists():
65            return parent
66    raise ValueError(f"{chromeos_tree_path} is not in a repo checkout")
67
68
69def GetChrootEbuildPaths(
70    chromeos_root: Union[Path, str],
71    packages: Iterable[str],
72    chroot_name: str = "chroot",
73    out_dir: str = "out",
74) -> List[str]:
75    """Gets the chroot path(s) of the package(s).
76
77    Args:
78        chromeos_root: The absolute path to the chromeos tree to use.
79        packages: A list of a package/packages to
80        be used to find their chroot path.
81        chroot_name: name of the chroot to enter.
82        out_dir: name of the out directory for the chroot.
83
84    Returns:
85        A list of chroot paths of the packages' ebuild files.
86
87    Raises:
88        ValueError: Failed to get the chroot path of a package.
89    """
90
91    chroot_paths = []
92
93    cros_sdk = [
94        "cros_sdk",
95        f"--chroot={chroot_name}",
96        f"--out-dir={out_dir}",
97    ]
98
99    # Find the chroot path for each package's ebuild.
100    for package in packages:
101        chroot_path = subprocess.check_output(
102            cros_sdk + ["--", "equery", "w", package],
103            cwd=chromeos_root,
104            encoding="utf-8",
105        )
106        chroot_paths.append(chroot_path.strip())
107
108    return chroot_paths
109
110
111def ConvertChrootPathsToAbsolutePaths(
112    chromeos_root: str,
113    chroot_paths: List[str],
114) -> List[str]:
115    """Converts the chroot path(s) to absolute symlink path(s).
116
117    Args:
118        chromeos_root: The absolute path to the chroot.
119        chroot_paths: A list of chroot paths to convert to absolute paths.
120
121    Returns:
122        A list of absolute path(s).
123
124    Raises:
125        ValueError: Invalid prefix for the chroot path or
126        invalid chroot paths were provided.
127    """
128
129    abs_paths = []
130    chroot_prefix = "/mnt/host/source/"
131    # Iterate through the chroot paths.
132    # For each chroot file path, remove '/mnt/host/source/' prefix
133    # and combine the chroot path with the result and add it to the list.
134    for chroot_path in chroot_paths:
135        if not chroot_path.startswith(chroot_prefix):
136            raise ValueError(
137                "Invalid prefix for the chroot path: %s" % chroot_path
138            )
139        rel_path = chroot_path[len(chroot_prefix) :]
140        # combine the chromeos root path + '/src/...'
141        abs_path = os.path.join(chromeos_root, rel_path)
142        abs_paths.append(abs_path)
143    return abs_paths
144