aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com>2023-05-11 19:33:34 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2023-05-11 19:33:34 +0000
commitfecd0a62a29da3c73fb9de960dce35c4989838cc (patch)
tree0c4e5432d39ac564ea08ae26532332f2f3edbdc6
parent03fa0df328cb0d3431dccb5f6b07f81ee6916c6d (diff)
parent9005bf2fb644176ef527913ab875fd1d0be48fe3 (diff)
downloadndk-fecd0a62a29da3c73fb9de960dce35c4989838cc.tar.gz
Merge changes Ic6286481,I94e1370e,Ibdd0c2d4
* changes: Remove unused MultiFileModule. Move ndk-stack to PythonApplication as well. Convert ndk-gdb to a PEP-441 zip application.
-rw-r--r--ndk/builds.py144
-rwxr-xr-xndk/checkbuild.py34
-rwxr-xr-xndkgdb.py (renamed from ndk-gdb.py)4
-rw-r--r--ndkstack.py (renamed from ndk-stack.py)4
4 files changed, 138 insertions, 48 deletions
diff --git a/ndk/builds.py b/ndk/builds.py
index 5b2df5b00..af6cad23e 100644
--- a/ndk/builds.py
+++ b/ndk/builds.py
@@ -22,7 +22,9 @@ from __future__ import annotations
import shutil
import stat
import subprocess
+import sys
import textwrap
+import zipapp
from enum import Enum, auto, unique
from pathlib import Path, PureWindowsPath
from typing import Any, Dict, Iterator, List, Optional, Set
@@ -403,28 +405,6 @@ class FileModule(Module):
shutil.copy2(self.src, install_path)
-class MultiFileModule(Module):
- """A module that installs multiple files to the NDK.
-
- This is similar to FileModule, but allows multiple files to be installed
- with a single module.
- """
-
- @property
- def files(self) -> Iterator[Path]:
- """List of absolute paths to files to be installed."""
- yield from []
-
- def build(self) -> None:
- pass
-
- def install(self) -> None:
- install_dir = self.get_install_path()
- install_dir.mkdir(parents=True, exist_ok=True)
- for file_path in self.files:
- shutil.copy2(file_path, install_dir)
-
-
class ScriptShortcutModule(Module):
"""A module that installs a shortcut to another script in the NDK.
@@ -526,6 +506,126 @@ class PythonPackage(Module):
pass
+class PythonApplication(Module):
+ """A PEP 441 Python Zip Application.
+
+ https://peps.python.org/pep-0441/
+
+ A Python Zip Application is a zipfile of a Python package with an entry point that
+ is runnable by the Python interpreter. PythonApplication will create a the pyz
+ application with its bundled dependencies and a launcher script that will invoke it
+ using the NDK's bundled Python interpreter.
+ """
+
+ package: Path
+ pip_dependencies: list[Path] = []
+ copy_to_python_path: list[Path] = []
+ main: str
+
+ def build(self) -> None:
+ if self._staging.exists():
+ shutil.rmtree(self._staging)
+ self._staging.mkdir(parents=True)
+
+ if self.package.is_file():
+ shutil.copy(self.package, self._staging / self.package.name)
+ (self._staging / "__init__.py").touch()
+ else:
+ shutil.copytree(self.package, self._staging / self.package.name)
+
+ for path in self.copy_to_python_path:
+ if path.is_file():
+ shutil.copy(path, self._staging / path.name)
+ else:
+ shutil.copytree(path, self._staging / path.name)
+
+ if self.pip_dependencies:
+ # Apparently pip doesn't want us to use it as a library.
+ # https://pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program
+ subprocess.run(
+ [
+ sys.executable,
+ "-m",
+ "pip",
+ "install",
+ "--target",
+ self._staging,
+ *self.pip_dependencies,
+ ],
+ check=True,
+ )
+
+ zipapp.create_archive(
+ source=self._staging,
+ target=self._pyz_build_location,
+ main=self.main,
+ filter=self.zipapp_file_filter,
+ )
+
+ @staticmethod
+ def zipapp_file_filter(path: Path) -> bool:
+ if ".git" in path.parts:
+ return False
+ if "__pycache__" in path.parts:
+ return False
+ if ".mypy_cache" in path.parts:
+ return False
+ if ".pytest_cache" in path.parts:
+ return False
+ if path.suffix in {".pyc", ".pyo"}:
+ return False
+ return True
+
+ def install(self) -> None:
+ install_path = self.get_install_path()
+ install_path.parent.mkdir(parents=True, exist_ok=True)
+ shutil.copy(self._pyz_build_location, install_path)
+ self.create_launcher()
+
+ def create_launcher(self) -> None:
+ if self.host is Host.Windows64:
+ self.create_cmd_launcher()
+ else:
+ self.create_bash_launcher()
+
+ def create_cmd_launcher(self) -> None:
+ self.get_install_path().with_name(f"{self.name}.cmd").write_text(
+ textwrap.dedent(
+ f"""\
+ @echo off
+ setlocal
+ set ANDROID_NDK_PYTHON=%~dp0..\\..\\..\\toolchains\\llvm\\prebuilt\\windows-x86_64\\python3\\python.exe
+ set SHELL=cmd
+ "%ANDROID_NDK_PYTHON%" -u "%~dp0{self.get_install_path().name}" %*
+ """
+ )
+ )
+
+ def create_bash_launcher(self) -> None:
+ launcher = self.get_install_path().with_name(self.name)
+ launcher.write_text(
+ textwrap.dedent(
+ f"""\
+ #!/usr/bin/env bash
+ THIS_DIR=$(cd "$(dirname "$0")" && pwd)
+ ANDROID_NDK_ROOT=$(cd "$THIS_DIR/../../.." && pwd)
+ . "$ANDROID_NDK_ROOT/build/tools/ndk_bin_common.sh"
+ "$ANDROID_NDK_PYTHON" "$THIS_DIR/{self.get_install_path().name}" "$@"
+ """
+ )
+ )
+ mode = launcher.stat().st_mode
+ launcher.chmod(mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
+
+ @property
+ def _staging(self) -> Path:
+ return self.intermediate_out_dir / self.name
+
+ @property
+ def _pyz_build_location(self) -> Path:
+ return self.intermediate_out_dir / self.get_install_path().name
+
+
class LintModule(Module):
def build(self) -> None:
self.run()
diff --git a/ndk/checkbuild.py b/ndk/checkbuild.py
index 55ceb90e1..19d535d7b 100755
--- a/ndk/checkbuild.py
+++ b/ndk/checkbuild.py
@@ -1726,18 +1726,18 @@ class Changelog(ndk.builds.FileModule):
@register
-class NdkGdb(ndk.builds.MultiFileModule):
+class NdkGdb(ndk.builds.PythonApplication):
name = "ndk-gdb"
- install_path = Path("prebuilt/{host}/bin")
+ install_path = Path("prebuilt/{host}/bin/ndkgdb.pyz")
notice = NDK_DIR / "NOTICE"
-
- @property
- def files(self) -> Iterator[Path]:
- yield NDK_DIR / "ndk-gdb"
- yield NDK_DIR / "ndk-gdb.py"
-
- if self.host.is_windows:
- yield NDK_DIR / "ndk-gdb.cmd"
+ package = NDK_DIR / "ndkgdb.py"
+ main = "ndkgdb:main"
+ pip_dependencies = [
+ ANDROID_DIR / "development/python-packages/adb",
+ ]
+ copy_to_python_path = [
+ ANDROID_DIR / "development/python-packages/gdbrunner",
+ ]
@register
@@ -1757,18 +1757,12 @@ class NdkLldbShortcut(ndk.builds.ScriptShortcutModule):
@register
-class NdkStack(ndk.builds.MultiFileModule):
+class NdkStack(ndk.builds.PythonApplication):
name = "ndk-stack"
- install_path = Path("prebuilt/{host}/bin")
+ install_path = Path("prebuilt/{host}/bin/ndkstack.pyz")
notice = NDK_DIR / "NOTICE"
-
- @property
- def files(self) -> Iterator[Path]:
- yield NDK_DIR / "ndk-stack"
- yield NDK_DIR / "ndk-stack.py"
-
- if self.host.is_windows:
- yield NDK_DIR / "ndk-stack.cmd"
+ package = NDK_DIR / "ndkstack.py"
+ main = "ndkstack:main"
@register
diff --git a/ndk-gdb.py b/ndkgdb.py
index 1054e8310..cd10b8cae 100755
--- a/ndk-gdb.py
+++ b/ndkgdb.py
@@ -29,10 +29,6 @@ import sys
import time
import xml.etree.cElementTree as ElementTree
-# Shared functions across gdbclient.py and ndk-gdb.py.
-# ndk-gdb is installed to $NDK/prebuilt/<platform>/bin
-NDK_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../.."))
-sys.path.append(os.path.join(NDK_PATH, "python-packages"))
import adb
import gdbrunner
diff --git a/ndk-stack.py b/ndkstack.py
index 2e7aa8f75..7f5a55d50 100644
--- a/ndk-stack.py
+++ b/ndkstack.py
@@ -315,7 +315,7 @@ class FrameInfo:
return None
-def main(argv):
+def main(argv=None):
""" "Program entry point."""
parser = argparse.ArgumentParser(
description="Symbolizes Android crashes.",
@@ -425,4 +425,4 @@ def main(argv):
if __name__ == "__main__":
- main(sys.argv[1:])
+ main()