diff options
author | Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> | 2023-05-11 19:33:34 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2023-05-11 19:33:34 +0000 |
commit | fecd0a62a29da3c73fb9de960dce35c4989838cc (patch) | |
tree | 0c4e5432d39ac564ea08ae26532332f2f3edbdc6 | |
parent | 03fa0df328cb0d3431dccb5f6b07f81ee6916c6d (diff) | |
parent | 9005bf2fb644176ef527913ab875fd1d0be48fe3 (diff) | |
download | ndk-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.py | 144 | ||||
-rwxr-xr-x | ndk/checkbuild.py | 34 | ||||
-rwxr-xr-x | ndkgdb.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 @@ -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() |