Jack Rosenthal | 6a505ad | 2023-08-01 16:10:00 +0000 | [diff] [blame] | 1 | #!/usr/bin/env vpython3 |
| 2 | # Copyright 2023 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 | # [VPYTHON:BEGIN] |
| 7 | # python_version: "3.8" |
| 8 | # [VPYTHON:END] |
| 9 | """Bazel launcher wrapper. |
| 10 | |
| 11 | This script starts Bazel appropriate for the project you're working in. It's |
| 12 | currently used by ChromiumOS, but is intended for use and to be updated by any |
| 13 | depot_tools users who are using Bazel. |
| 14 | |
| 15 | In the case this script is not able to detect which project you're working in, |
| 16 | it will fall back to using the next "bazel" executable in your PATH. |
| 17 | """ |
| 18 | |
| 19 | import itertools |
| 20 | import os |
| 21 | from pathlib import Path |
| 22 | import shutil |
| 23 | import sys |
| 24 | from typing import List, Optional |
| 25 | |
| 26 | |
| 27 | def _find_bazel_cros() -> Optional[Path]: |
Mike Frysinger | 124bb8e | 2023-09-06 05:48:55 +0000 | [diff] [blame] | 28 | """Find the bazel launcher for ChromiumOS.""" |
| 29 | cwd = Path.cwd() |
| 30 | for parent in itertools.chain([cwd], cwd.parents): |
| 31 | bazel_launcher = parent / "chromite" / "bin" / "bazel" |
| 32 | if bazel_launcher.exists(): |
| 33 | return bazel_launcher |
| 34 | return None |
Jack Rosenthal | 6a505ad | 2023-08-01 16:10:00 +0000 | [diff] [blame] | 35 | |
| 36 | |
| 37 | def _find_next_bazel_in_path() -> Optional[Path]: |
Mike Frysinger | 124bb8e | 2023-09-06 05:48:55 +0000 | [diff] [blame] | 38 | """The fallback method: search the remainder of PATH for bazel.""" |
| 39 | # Remove depot_tools from PATH if present. |
| 40 | depot_tools = Path(__file__).resolve().parent |
| 41 | path_env = os.environ.get("PATH", os.defpath) |
| 42 | search_paths = [] |
| 43 | for path in path_env.split(os.pathsep): |
| 44 | if Path(path).resolve() != depot_tools: |
| 45 | search_paths.append(path) |
| 46 | new_path_env = os.pathsep.join(search_paths) |
| 47 | bazel = shutil.which("bazel", path=new_path_env) |
| 48 | if bazel: |
| 49 | return Path(bazel) |
| 50 | return None |
Jack Rosenthal | 6a505ad | 2023-08-01 16:10:00 +0000 | [diff] [blame] | 51 | |
| 52 | |
| 53 | # All functions used to search for Bazel (in order of search). |
| 54 | _SEARCH_FUNCTIONS = ( |
| 55 | _find_bazel_cros, |
| 56 | _find_next_bazel_in_path, |
| 57 | ) |
| 58 | |
| 59 | _FIND_FAILURE_MSG = """\ |
| 60 | ERROR: The depot_tools bazel launcher was unable to find an appropriate bazel |
| 61 | executable to use. |
| 62 | |
| 63 | For ChromiumOS developers: |
| 64 | Make sure your current directory is inside a ChromiumOS checkout (e.g., |
| 65 | ~/chromiumos). If you're already in a ChromiumOS checkout, it may be because |
| 66 | you're working on a branch that's too old (i.e., prior to Bazel). |
| 67 | |
| 68 | If you're not working on any of the above listed projects, this launcher assumes |
| 69 | that you have Bazel installed on your system somewhere else in PATH. Check that |
| 70 | it's actually installed.""" |
| 71 | |
| 72 | |
| 73 | def main(argv: List[str]) -> int: |
Mike Frysinger | 124bb8e | 2023-09-06 05:48:55 +0000 | [diff] [blame] | 74 | """Main.""" |
| 75 | for search_func in _SEARCH_FUNCTIONS: |
| 76 | bazel = search_func() |
| 77 | if bazel: |
| 78 | os.execv(bazel, [str(bazel), *argv]) |
Jack Rosenthal | 6a505ad | 2023-08-01 16:10:00 +0000 | [diff] [blame] | 79 | |
Mike Frysinger | 124bb8e | 2023-09-06 05:48:55 +0000 | [diff] [blame] | 80 | print(_FIND_FAILURE_MSG, file=sys.stderr) |
| 81 | return 1 |
Jack Rosenthal | 6a505ad | 2023-08-01 16:10:00 +0000 | [diff] [blame] | 82 | |
| 83 | |
| 84 | if __name__ == "__main__": |
Mike Frysinger | 124bb8e | 2023-09-06 05:48:55 +0000 | [diff] [blame] | 85 | sys.exit(main(sys.argv[1:])) |