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