#!/usr/bin/env python3

import asyncio
import argparse
import json
import os
import platform
import re
import shlex
import shutil
import signal
import subprocess
import sys
import sysconfig
from asyncio import wait_for
from contextlib import asynccontextmanager
from datetime import datetime, timezone
from glob import glob
from os.path import abspath, basename, relpath
from pathlib import Path
from subprocess import CalledProcessError
from tempfile import TemporaryDirectory


SCRIPT_NAME = Path(__file__).name
ANDROID_DIR = Path(__file__).resolve().parent
PYTHON_DIR = ANDROID_DIR.parent
in_source_tree = (
    ANDROID_DIR.name == "Android" and (PYTHON_DIR / "pyconfig.h.in").exists()
)

ENV_SCRIPT = ANDROID_DIR / "android-env.sh"
TESTBED_DIR = ANDROID_DIR / "testbed"
CROSS_BUILD_DIR = PYTHON_DIR / "cross-build"

HOSTS = ["aarch64-linux-android", "x86_64-linux-android"]
APP_ID = "org.python.testbed"
DECODE_ARGS = ("UTF-8", "backslashreplace")


try:
    android_home = Path(os.environ['ANDROID_HOME'])
except KeyError:
    sys.exit("The ANDROID_HOME environment variable is required.")

adb = Path(
    f"{android_home}/platform-tools/adb"
    + (".exe" if os.name == "nt" else "")
)

gradlew = Path(
    f"{TESTBED_DIR}/gradlew"
    + (".bat" if os.name == "nt" else "")
)

# Whether we've seen any output from Python yet.
python_started = False

# Buffer for verbose output which will be displayed only if a test fails and
# there has been no output from Python.
hidden_output = []


def log_verbose(context, line, stream=sys.stdout):
    if context.verbose:
        stream.write(line)
    else:
        hidden_output.append((stream, line))


def delete_glob(pattern):
    # Path.glob doesn't accept non-relative patterns.
    for path in glob(str(pattern)):
        path = Path(path)
        print(f"Deleting {path} ...")
        if path.is_dir() and not path.is_symlink():
            shutil.rmtree(path)
        else:
            path.unlink()


def subdir(*parts, create=False):
    path = CROSS_BUILD_DIR.joinpath(*parts)
    if not path.exists():
        if not create:
            sys.exit(
                f"{path} does not exist. Create it by running the appropriate "
                f"`configure` subcommand of {SCRIPT_NAME}.")
        else:
            path.mkdir(parents=True)
    return path


def run(command, *, host=None, env=None, log=True, **kwargs):
    kwargs.setdefault("check", True)
    if env is None:
        env = os.environ.copy()

    if host:
        host_env = android_env(host)
        print_env(host_env)
        env.update(host_env)

    if log:
        print(">", join_command(command))
    return subprocess.run(command, env=env, **kwargs)


# Format a command so it can be copied into a shell. Like shlex.join, but also
# accepts arguments which are Paths, or a single string/Path outside of a list.
def join_command(args):
    if isinstance(args, (str, Path)):
        return str(args)
    else:
        return shlex.join(map(str, args))


# Format the environment so it can be pasted into a shell.
def print_env(env):
    for key, value in sorted(env.items()):
        print(f"export {key}={shlex.quote(value)}")


def android_env(host):
    if host:
        prefix = subdir(host) / "prefix"
    else:
        prefix = ANDROID_DIR / "prefix"
        sysconfig_files = prefix.glob("lib/python*/_sysconfigdata__android_*.py")
        sysconfig_filename = next(sysconfig_files).name
        host = re.fullmatch(r"_sysconfigdata__android_(.+).py", sysconfig_filename)[1]

    env_output = subprocess.run(
        f"set -eu; "
        f"HOST={host}; "
        f"PREFIX={prefix}; "
        f". {ENV_SCRIPT}; "
        f"export",
        check=True, shell=True, capture_output=True, encoding='utf-8',
    ).stdout

    env = {}
    for line in env_output.splitlines():
        # We don't require every line to match, as there may be some other
        # output from installing the NDK.
        if match := re.search(
            "^(declare -x |export )?(\\w+)=['\"]?(.*?)['\"]?$", line
        ):
            key, value = match[2], match[3]
            if os.environ.get(key) != value:
                env[key] = value

    if not env:
        raise ValueError(f"Found no variables in {ENV_SCRIPT.name} output:\n"
                         + env_output)
    return env


def build_python_path():
    """The path to the build Python binary."""
    build_dir = subdir("build")
    binary = build_dir / "python"
    if not binary.is_file():
        binary = binary.with_suffix(".exe")
        if not binary.is_file():
            raise FileNotFoundError("Unable to find `python(.exe)` in "
                                    f"{build_dir}")

    return binary


def configure_build_python(context):
    if context.clean:
        clean("build")
    os.chdir(subdir("build", create=True))

    command = [relpath(PYTHON_DIR / "configure")]
    if context.args:
        command.extend(context.args)
    run(command)


def make_build_python(context):
    os.chdir(subdir("build"))
    run(["make", "-j", str(os.cpu_count())])


# To create new builds of these dependencies, usually all that's necessary is to
# push a tag to the cpython-android-source-deps repository, and GitHub Actions
# will do the rest.
#
# If you're a member of the Python core team, and you'd like to be able to push
# these tags yourself, please contact Malcolm Smith or Russell Keith-Magee.
def unpack_deps(host, prefix_dir):
    os.chdir(prefix_dir)
    deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download"
    for name_ver in ["bzip2-1.0.8-3", "libffi-3.4.4-3", "openssl-3.0.18-0",
                     "sqlite-3.50.4-0", "xz-5.4.6-1", "zstd-1.5.7-1"]:
        filename = f"{name_ver}-{host}.tar.gz"
        download(f"{deps_url}/{name_ver}/{filename}")
        shutil.unpack_archive(filename)
        os.remove(filename)


def download(url, target_dir="."):
    out_path = f"{target_dir}/{basename(url)}"
    run(["curl", "-Lf", "--retry", "5", "--retry-all-errors", "-o", out_path, url])
    return out_path


def configure_host_python(context):
    if context.clean:
        clean(context.host)

    host_dir = subdir(context.host, create=True)
    prefix_dir = host_dir / "prefix"
    if not prefix_dir.exists():
        prefix_dir.mkdir()
        unpack_deps(context.host, prefix_dir)

    os.chdir(host_dir)
    command = [
        # Basic cross-compiling configuration
        relpath(PYTHON_DIR / "configure"),
        f"--host={context.host}",
        f"--build={sysconfig.get_config_var('BUILD_GNU_TYPE')}",
        f"--with-build-python={build_python_path()}",
        "--without-ensurepip",

        # Android always uses a shared libpython.
        "--enable-shared",
        "--without-static-libpython",

        # Dependent libraries. The others are found using pkg-config: see
        # android-env.sh.
        f"--with-openssl={prefix_dir}",
    ]

    if context.args:
        command.extend(context.args)
    run(command, host=context.host)


def make_host_python(context):
    # The CFLAGS and LDFLAGS set in android-env include the prefix dir, so
    # delete any previous Python installation to prevent it being used during
    # the build.
    host_dir = subdir(context.host)
    prefix_dir = host_dir / "prefix"
    for pattern in ("include/python*", "lib/libpython*", "lib/python*"):
        delete_glob(f"{prefix_dir}/{pattern}")

    # The Android environment variables were already captured in the Makefile by
    # `configure`, and passing them again when running `make` may cause some
    # flags to be duplicated. So we don't use the `host` argument here.
    os.chdir(host_dir)
    run(["make", "-j", str(os.cpu_count())])

    # The `make install` output is very verbose and rarely useful, so
    # suppress it by default.
    run(
        ["make", "install", f"prefix={prefix_dir}"],
        capture_output=not context.verbose,
    )


def build_all(context):
    steps = [configure_build_python, make_build_python, configure_host_python,
             make_host_python]
    for step in steps:
        step(context)


def clean(host):
    delete_glob(CROSS_BUILD_DIR / host)


def clean_all(context):
    for host in HOSTS + ["build"]:
        clean(host)


def setup_ci():
    if "GITHUB_ACTIONS" in os.environ:
        # Enable emulator hardware acceleration
        # (https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/).
        if platform.system() == "Linux":
            run(
                ["sudo", "tee", "/etc/udev/rules.d/99-kvm4all.rules"],
                input='KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"\n',
                text=True,
            )
            run(["sudo", "udevadm", "control", "--reload-rules"])
            run(["sudo", "udevadm", "trigger", "--name-match=kvm"])

        # Free up disk space by deleting unused versions of the NDK
        # (https://github.com/freakboy3742/pyspamsum/pull/108).
        for line in ENV_SCRIPT.read_text().splitlines():
            if match := re.fullmatch(r"ndk_version=(.+)", line):
                ndk_version = match[1]
                break
        else:
            raise ValueError(f"Failed to find NDK version in {ENV_SCRIPT.name}")

        for item in (android_home / "ndk").iterdir():
            if item.name[0].isdigit() and item.name != ndk_version:
                delete_glob(item)


def setup_sdk():
    sdkmanager = android_home / (
        "cmdline-tools/latest/bin/sdkmanager"
        + (".bat" if os.name == "nt" else "")
    )

    # Gradle will fail if it needs to install an SDK package whose license
    # hasn't been accepted, so pre-accept all licenses.
    if not all((android_home / "licenses" / path).exists() for path in [
        "android-sdk-arm-dbt-license", "android-sdk-license"
    ]):
        run(
            [sdkmanager, "--licenses"],
            text=True,
            capture_output=True,
            input="y\n" * 100,
        )

    # Gradle may install this automatically, but we can't rely on that because
    # we need to run adb within the logcat task.
    if not adb.exists():
        run([sdkmanager, "platform-tools"])


# To avoid distributing compiled artifacts without corresponding source code,
# the Gradle wrapper is not included in the CPython repository. Instead, we
# extract it from the Gradle GitHub repository.
def setup_testbed():
    paths = ["gradlew", "gradlew.bat", "gradle/wrapper/gradle-wrapper.jar"]
    if all((TESTBED_DIR / path).exists() for path in paths):
        return

    # The wrapper version isn't important, as any version of the wrapper can
    # download any version of Gradle. The Gradle version actually used for the
    # build is specified in testbed/gradle/wrapper/gradle-wrapper.properties.
    version = "8.9.0"

    for path in paths:
        out_path = TESTBED_DIR / path
        out_path.parent.mkdir(exist_ok=True)
        download(
            f"https://raw.githubusercontent.com/gradle/gradle/v{version}/{path}",
            out_path.parent,
        )
        os.chmod(out_path, 0o755)


# run_testbed will build the app automatically, but it's useful to have this as
# a separate command to allow running the app outside of this script.
def build_testbed(context):
    setup_sdk()
    setup_testbed()
    run(
        [gradlew, "--console", "plain", "packageDebug", "packageDebugAndroidTest"],
        cwd=TESTBED_DIR,
    )


# Work around a bug involving sys.exit and TaskGroups
# (https://github.com/python/cpython/issues/101515).
def exit(*args):
    raise MySystemExit(*args)


class MySystemExit(Exception):
    pass


# The `test` subcommand runs all subprocesses through this context manager so
# that no matter what happens, they can always be cancelled from another task,
# and they will always be cleaned up on exit.
@asynccontextmanager
async def async_process(*args, **kwargs):
    process = await asyncio.create_subprocess_exec(*args, **kwargs)
    try:
        yield process
    finally:
        if process.returncode is None:
            # Allow a reasonably long time for Gradle to clean itself up,
            # because we don't want stale emulators left behind.
            timeout = 10
            process.terminate()
            try:
                await wait_for(process.wait(), timeout)
            except TimeoutError:
                print(
                    f"Command {args} did not terminate after {timeout} seconds "
                    f" - sending SIGKILL"
                )
                process.kill()

                # Even after killing the process we must still wait for it,
                # otherwise we'll get the warning "Exception ignored in __del__".
                await wait_for(process.wait(), timeout=1)


async def async_check_output(*args, **kwargs):
    async with async_process(
        *args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs
    ) as process:
        stdout, stderr = await process.communicate()
        if process.returncode == 0:
            return stdout.decode(*DECODE_ARGS)
        else:
            raise CalledProcessError(
                process.returncode, args,
                stdout.decode(*DECODE_ARGS), stderr.decode(*DECODE_ARGS)
            )


# Return a list of the serial numbers of connected devices. Emulators will have
# serials of the form "emulator-5678".
async def list_devices():
    serials = []
    header_found = False

    lines = (await async_check_output(adb, "devices")).splitlines()
    for line in lines:
        # Ignore blank lines, and all lines before the header.
        line = line.strip()
        if line == "List of devices attached":
            header_found = True
        elif header_found and line:
            try:
                serial, status = line.split()
            except ValueError:
                raise ValueError(f"failed to parse {line!r}")
            if status == "device":
                serials.append(serial)

    if not header_found:
        raise ValueError(f"failed to parse {lines}")
    return serials


async def find_device(context, initial_devices):
    if context.managed:
        print("Waiting for managed device - this may take several minutes")
        while True:
            new_devices = set(await list_devices()).difference(initial_devices)
            if len(new_devices) == 0:
                await asyncio.sleep(1)
            elif len(new_devices) == 1:
                serial = new_devices.pop()
                print(f"Serial: {serial}")
                return serial
            else:
                exit(f"Found more than one new device: {new_devices}")
    else:
        return context.connected


# An older version of this script in #121595 filtered the logs by UID instead.
# But logcat can't filter by UID until API level 31. If we ever switch back to
# filtering by UID, we'll also have to filter by time so we only show messages
# produced after the initial call to `stop_app`.
#
# We're more likely to miss the PID because it's shorter-lived, so there's a
# workaround in PythonSuite.kt to stop it being *too* short-lived.
async def find_pid(serial):
    print("Waiting for app to start - this may take several minutes")
    shown_error = False
    while True:
        try:
            # `pidof` requires API level 24 or higher. The level 23 emulator
            # includes it, but it doesn't work (it returns all processes).
            pid = (await async_check_output(
                adb, "-s", serial, "shell", "pidof", "-s", APP_ID
            )).strip()
        except CalledProcessError as e:
            # If the app isn't running yet, pidof gives no output. So if there
            # is output, there must have been some other error. However, this
            # sometimes happens transiently, especially when running a managed
            # emulator for the first time, so don't make it fatal.
            if (e.stdout or e.stderr) and not shown_error:
                print_called_process_error(e)
                print("This may be transient, so continuing to wait")
                shown_error = True
        else:
            # Some older devices (e.g. Nexus 4) return zero even when no process
            # was found, so check whether we actually got any output.
            if pid:
                print(f"PID: {pid}")
                return pid

        # Loop fairly rapidly to avoid missing a short-lived process.
        await asyncio.sleep(0.2)


async def logcat_task(context, initial_devices):
    # Gradle may need to do some large downloads of libraries and emulator
    # images. This will happen during find_device in --managed mode, or find_pid
    # in --connected mode.
    startup_timeout = 600
    serial = await wait_for(find_device(context, initial_devices), startup_timeout)
    pid = await wait_for(find_pid(serial), startup_timeout)

    # `--pid` requires API level 24 or higher.
    args = [adb, "-s", serial, "logcat", "--pid", pid,  "--format", "tag"]
    logcat_started = False
    async with async_process(
        *args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
    ) as process:
        while line := (await process.stdout.readline()).decode(*DECODE_ARGS):
            if match := re.fullmatch(r"([A-Z])/(.*)", line, re.DOTALL):
                logcat_started = True
                level, message = match.groups()
            else:
                # If the regex doesn't match, this is either a logcat startup
                # error, or the second or subsequent line of a multi-line
                # message. Python won't produce multi-line messages, but other
                # components might.
                level, message = None, line

            # Exclude high-volume messages which are rarely useful.
            if context.verbose < 2 and "from python test_syslog" in message:
                continue

            # Put high-level messages on stderr so they're highlighted in the
            # buildbot logs. This will include Python's own stderr.
            stream = (
                sys.stderr
                if level in ["W", "E", "F"]  # WARNING, ERROR, FATAL (aka ASSERT)
                else sys.stdout
            )

            # To simplify automated processing of the output, e.g. a buildbot
            # posting a failure notice on a GitHub PR, we strip the level and
            # tag indicators from Python's stdout and stderr.
            for prefix in ["python.stdout: ", "python.stderr: "]:
                if message.startswith(prefix):
                    global python_started
                    python_started = True
                    stream.write(message.removeprefix(prefix))
                    break
            else:
                # Non-Python messages add a lot of noise, but they may
                # sometimes help explain a failure.
                log_verbose(context, line, stream)

        # If the device disconnects while logcat is running, which always
        # happens in --managed mode, some versions of adb return non-zero.
        # Distinguish this from a logcat startup error by checking whether we've
        # received any logcat messages yet.
        status = await wait_for(process.wait(), timeout=1)
        if status != 0 and not logcat_started:
            raise CalledProcessError(status, args)


def stop_app(serial):
    run([adb, "-s", serial, "shell", "am", "force-stop", APP_ID], log=False)


async def gradle_task(context):
    env = os.environ.copy()
    if context.managed:
        task_prefix = context.managed
    else:
        task_prefix = "connected"
        env["ANDROID_SERIAL"] = context.connected

    if context.ci_mode:
        context.args[0:0] = [
            # See _add_ci_python_opts in libregrtest/main.py.
            "-W", "error", "-bb", "-E",

            # Randomization is disabled because order-dependent failures are
            # much less likely to pass on a rerun in single-process mode.
            "-m", "test",
            f"--{context.ci_mode}-ci", "--single-process", "--no-randomize"
        ]

    if not any(arg in context.args for arg in ["-c", "-m"]):
        context.args[0:0] = ["-m", "test"]

    args = [
        gradlew, "--console", "plain", f"{task_prefix}DebugAndroidTest",
    ] + [
        f"-P{name}={value}"
        for name, value in [
            ("python.sitePackages", context.site_packages),
            ("python.cwd", context.cwd),
            (
                "android.testInstrumentationRunnerArguments.pythonArgs",
                json.dumps(context.args),
            ),
        ]
        if value
    ]
    if context.verbose >= 2:
        args.append("--info")
    log_verbose(context, f"> {join_command(args)}\n")

    try:
        async with async_process(
            *args, cwd=TESTBED_DIR, env=env,
            stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
        ) as process:
            while line := (await process.stdout.readline()).decode(*DECODE_ARGS):
                # Gradle may take several minutes to install SDK packages, so
                # it's worth showing those messages even in non-verbose mode.
                if line.startswith('Preparing "Install'):
                    sys.stdout.write(line)
                else:
                    log_verbose(context, line)

            status = await wait_for(process.wait(), timeout=1)
            if status == 0:
                exit(0)
            else:
                raise CalledProcessError(status, args)
    finally:
        # Gradle does not stop the tests when interrupted.
        if context.connected:
            stop_app(context.connected)


async def run_testbed(context):
    setup_ci()
    setup_sdk()
    setup_testbed()

    if context.managed:
        # In this mode, Gradle will create a device with an unpredictable name.
        # So we save a list of the running devices before starting Gradle, and
        # find_device then waits for a new device to appear.
        initial_devices = await list_devices()
    else:
        # In case the previous shutdown was unclean, make sure the app isn't
        # running, otherwise we might show logs from a previous run. This is
        # unnecessary in --managed mode, because Gradle creates a new emulator
        # every time.
        stop_app(context.connected)
        initial_devices = None

    try:
        async with asyncio.TaskGroup() as tg:
            tg.create_task(logcat_task(context, initial_devices))
            tg.create_task(gradle_task(context))
    except* MySystemExit as e:
        raise SystemExit(*e.exceptions[0].args) from None
    except* CalledProcessError as e:
        # If Python produced no output, then the user probably wants to see the
        # verbose output to explain why the test failed.
        if not python_started:
            for stream, line in hidden_output:
                stream.write(line)

        # Extract it from the ExceptionGroup so it can be handled by `main`.
        raise e.exceptions[0]


def package_version(prefix_dir):
    patchlevel_glob = f"{prefix_dir}/include/python*/patchlevel.h"
    patchlevel_paths = glob(patchlevel_glob)
    if len(patchlevel_paths) != 1:
        sys.exit(f"{patchlevel_glob} matched {len(patchlevel_paths)} paths.")

    for line in open(patchlevel_paths[0]):
        if match := re.fullmatch(r'\s*#define\s+PY_VERSION\s+"(.+)"\s*', line):
            version = match[1]
            break
    else:
        sys.exit(f"Failed to find Python version in {patchlevel_paths[0]}.")

    # If not building against a tagged commit, add a timestamp to the version.
    # Follow the PyPA version number rules, as this will make it easier to
    # process with other tools.
    if version.endswith("+"):
        version += datetime.now(timezone.utc).strftime("%Y%m%d.%H%M%S")

    return version


def package(context):
    prefix_dir = subdir(context.host, "prefix")
    version = package_version(prefix_dir)

    with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir:
        temp_dir = Path(temp_dir)

        # Include all tracked files from the Android directory.
        for line in run(
            ["git", "ls-files"],
            cwd=ANDROID_DIR, capture_output=True, text=True, log=False,
        ).stdout.splitlines():
            src = ANDROID_DIR / line
            dst = temp_dir / line
            dst.parent.mkdir(parents=True, exist_ok=True)
            shutil.copy2(src, dst, follow_symlinks=False)

        # Include anything from the prefix directory which could be useful
        # either for embedding Python in an app, or building third-party
        # packages against it.
        for rel_dir, patterns in [
            ("include", ["openssl*", "python*", "sqlite*"]),
            ("lib", ["engines-3", "libcrypto*.so", "libpython*", "libsqlite*",
                     "libssl*.so", "ossl-modules", "python*"]),
            ("lib/pkgconfig", ["*crypto*", "*ssl*", "*python*", "*sqlite*"]),
        ]:
            for pattern in patterns:
                for src in glob(f"{prefix_dir}/{rel_dir}/{pattern}"):
                    dst = temp_dir / relpath(src, prefix_dir.parent)
                    dst.parent.mkdir(parents=True, exist_ok=True)
                    if Path(src).is_dir():
                        shutil.copytree(
                            src, dst, symlinks=True,
                            ignore=lambda *args: ["__pycache__"]
                        )
                    else:
                        shutil.copy2(src, dst, follow_symlinks=False)

        # Strip debug information.
        if not context.debug:
            so_files = glob(f"{temp_dir}/**/*.so", recursive=True)
            run([android_env(context.host)["STRIP"], *so_files], log=False)

        dist_dir = subdir(context.host, "dist", create=True)
        package_path = shutil.make_archive(
            f"{dist_dir}/python-{version}-{context.host}", "gztar", temp_dir
        )
        print(f"Wrote {package_path}")
        return package_path


def ci(context):
    for step in [
        configure_build_python,
        make_build_python,
        configure_host_python,
        make_host_python,
        package,
    ]:
        caption = (
            step.__name__.replace("_", " ")
            .capitalize()
            .replace("python", "Python")
        )
        print(f"::group::{caption}")
        result = step(context)
        if step is package:
            package_path = result
        print("::endgroup::")

    if (
        "GITHUB_ACTIONS" in os.environ
        and (platform.system(), platform.machine()) != ("Linux", "x86_64")
    ):
        print(
            "Skipping tests: GitHub Actions does not support the Android "
            "emulator on this platform."
        )
    else:
        with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir:
            print("::group::Tests")

            # Prove the package is self-contained by using it to run the tests.
            shutil.unpack_archive(package_path, temp_dir)
            launcher_args = [
                "--managed", "maxVersion", "-v", f"--{context.ci_mode}-ci"
            ]
            run(
                ["./android.py", "test", *launcher_args],
                cwd=temp_dir
            )
            print("::endgroup::")


def env(context):
    print_env(android_env(getattr(context, "host", None)))


# Handle SIGTERM the same way as SIGINT. This ensures that if we're terminated
# by the buildbot worker, we'll make an attempt to clean up our subprocesses.
def install_signal_handler():
    def signal_handler(*args):
        os.kill(os.getpid(), signal.SIGINT)

    signal.signal(signal.SIGTERM, signal_handler)


def parse_args():
    parser = argparse.ArgumentParser()
    subcommands = parser.add_subparsers(dest="subcommand", required=True)

    def add_parser(*args, **kwargs):
        parser = subcommands.add_parser(*args, **kwargs)
        parser.add_argument(
            "-v", "--verbose", action="count", default=0,
            help="Show verbose output. Use twice to be even more verbose.")
        return parser

    # Subcommands
    build = add_parser(
        "build", help="Run configure-build, make-build, configure-host and "
        "make-host")
    configure_build = add_parser(
        "configure-build", help="Run `configure` for the build Python")
    add_parser(
        "make-build", help="Run `make` for the build Python")
    configure_host = add_parser(
        "configure-host", help="Run `configure` for Android")
    make_host = add_parser(
        "make-host", help="Run `make` for Android")

    add_parser("clean", help="Delete all build directories")
    add_parser("build-testbed", help="Build the testbed app")
    test = add_parser("test", help="Run the testbed app")
    package = add_parser("package", help="Make a release package")
    ci = add_parser("ci", help="Run build, package and test")
    env = add_parser("env", help="Print environment variables")

    # Common arguments
    for subcommand in [build, configure_build, configure_host, ci]:
        subcommand.add_argument(
            "--clean", action="store_true", default=False, dest="clean",
            help="Delete the relevant build directories first")

    host_commands = [build, configure_host, make_host, package, ci]
    if in_source_tree:
        host_commands.append(env)
    for subcommand in host_commands:
        subcommand.add_argument(
            "host", metavar="HOST", choices=HOSTS,
            help="Host triplet: choices=[%(choices)s]")

    for subcommand in [build, configure_build, configure_host, ci]:
        subcommand.add_argument("args", nargs="*",
                                help="Extra arguments to pass to `configure`")

    # Test arguments
    device_group = test.add_mutually_exclusive_group(required=True)
    device_group.add_argument(
        "--connected", metavar="SERIAL", help="Run on a connected device. "
        "Connect it yourself, then get its serial from `adb devices`.")
    device_group.add_argument(
        "--managed", metavar="NAME", help="Run on a Gradle-managed device. "
        "These are defined in `managedDevices` in testbed/app/build.gradle.kts.")

    test.add_argument(
        "--site-packages", metavar="DIR", type=abspath,
        help="Directory to copy as the app's site-packages.")
    test.add_argument(
        "--cwd", metavar="DIR", type=abspath,
        help="Directory to copy as the app's working directory.")
    test.add_argument(
        "args", nargs="*", help=f"Python command-line arguments. "
        f"Separate them from {SCRIPT_NAME}'s own arguments with `--`. "
        f"If neither -c nor -m are included, `-m test` will be prepended, "
        f"which will run Python's own test suite.")

    # Package arguments.
    for subcommand in [package, ci]:
        subcommand.add_argument(
            "-g", action="store_true", default=False, dest="debug",
            help="Include debug information in package")

    # CI arguments
    for subcommand in [test, ci]:
        group = subcommand.add_mutually_exclusive_group(required=subcommand is ci)
        group.add_argument(
            "--fast-ci", action="store_const", dest="ci_mode", const="fast",
            help="Add test arguments for GitHub Actions")
        group.add_argument(
            "--slow-ci", action="store_const", dest="ci_mode", const="slow",
            help="Add test arguments for buildbots")

    return parser.parse_args()


def main():
    install_signal_handler()

    # Under the buildbot, stdout is not a TTY, but we must still flush after
    # every line to make sure our output appears in the correct order relative
    # to the output of our subprocesses.
    for stream in [sys.stdout, sys.stderr]:
        stream.reconfigure(line_buffering=True)

    context = parse_args()
    dispatch = {
        "configure-build": configure_build_python,
        "make-build": make_build_python,
        "configure-host": configure_host_python,
        "make-host": make_host_python,
        "build": build_all,
        "clean": clean_all,
        "build-testbed": build_testbed,
        "test": run_testbed,
        "package": package,
        "ci": ci,
        "env": env,
    }

    try:
        result = dispatch[context.subcommand](context)
        if asyncio.iscoroutine(result):
            asyncio.run(result)
    except CalledProcessError as e:
        print_called_process_error(e)
        sys.exit(1)


def print_called_process_error(e):
    for stream_name in ["stdout", "stderr"]:
        content = getattr(e, stream_name)
        if isinstance(content, bytes):
            content = content.decode(*DECODE_ARGS)
        stream = getattr(sys, stream_name)
        if content:
            stream.write(content)
            if not content.endswith("\n"):
                stream.write("\n")

    # shlex uses single quotes, so we surround the command with double quotes.
    print(
        f'Command "{join_command(e.cmd)}" returned exit status {e.returncode}'
    )


if __name__ == "__main__":
    main()
