From a7f7ab6ef12005f4ca86c5a4934c33d2539a23e5 Mon Sep 17 00:00:00 2001 From: Shyamnath Premnadh Date: Tue, 10 Oct 2023 12:19:10 +0200 Subject: Deployment: More code fixes - Formatting and text updates. - extract_and_copy_jar() returns the extracted path to the jar directory - Buildozer class is now initialized when `pyside6-android-deploy` is run with --init. This is because it updates the recipes folder. - Buildozer defaults for Android NDK cannot be used anymore because `pyside6-android-deploy` uses llvm-readelf from the NDK to find the binary dependencies. - Change print statement to RuntimeError incase `main.py` does not exist - Change logging.exception to RuntimeError for the function `find_pyside_modules` Pick-to: 6.6 Task-number: PYSIDE-1612 Change-Id: I6ef5d5dfe9acae5f0029553ca2c6f07d91b6e462 Reviewed-by: Friedemann Kleint Reviewed-by: Qt CI Bot Reviewed-by: Cristian Maureira-Fredes --- sources/pyside-tools/android_deploy.py | 44 ++++++++++++---------- sources/pyside-tools/deploy.py | 6 +-- .../deploy_lib/android/android_helper.py | 11 ++---- .../pyside-tools/deploy_lib/android/buildozer.py | 2 +- sources/pyside-tools/deploy_lib/config.py | 19 +++++++--- sources/pyside-tools/deploy_lib/python_helper.py | 5 +-- 6 files changed, 46 insertions(+), 41 deletions(-) (limited to 'sources/pyside-tools') diff --git a/sources/pyside-tools/android_deploy.py b/sources/pyside-tools/android_deploy.py index 3c1dd5925..8c4f909db 100644 --- a/sources/pyside-tools/android_deploy.py +++ b/sources/pyside-tools/android_deploy.py @@ -29,7 +29,9 @@ from deploy_lib.android import (extract_and_copy_jar, get_wheel_android_arch, pyside6-android-deploy android -c /path/to/pysidedeploy.spec - Note: If --ndk-path and --sdk-path are not specified, the defaults from buildozer are used + Note: If --ndk-path and --sdk-path are not specified, the cache of the tool + `.pyside6_android_deploy` is checked in the user's HOME directory. If it is not found, the user + will have to manually download them. Prerequisities: Python main entrypoint file should be named "main.py" @@ -87,10 +89,10 @@ def main(name: str = None, pyside_wheel: Path = None, shiboken_wheel: Path = Non main_file = Path.cwd() / "main.py" generated_files_path = None if not main_file.exists(): - raise RuntimeError(dedent(""" - [DEPLOY] For android deployment to work, the main entrypoint Python file should be named - 'main.py' and it should be run from the application directory - """)) + raise RuntimeError(("[DEPLOY] For Android deployment to work, the main" + " entrypoint Python file should be named 'main.py'" + " and it should be run from the application" + " directory")) android_data = AndroidData(wheel_pyside=pyside_wheel, wheel_shiboken=shiboken_wheel, ndk_path=ndk_path, sdk_path=sdk_path) @@ -128,18 +130,25 @@ def main(name: str = None, pyside_wheel: Path = None, shiboken_wheel: Path = Non if not config.jars_dir or not Path(config.jars_dir).exists() and not dry_run: logging.info("[DEPLOY] Extract and copy jar files from PySide6 wheel to " f"{generated_files_path}") - extract_and_copy_jar(wheel_path=config.wheel_pyside, - generated_files_path=generated_files_path) - config.jars_dir = (generated_files_path / "jar" / "PySide6" / "jar").resolve() + config.jars_dir = extract_and_copy_jar(wheel_path=config.wheel_pyside, + generated_files_path=generated_files_path) # find architecture from wheel name if not config.arch: arch = get_wheel_android_arch(wheel=config.wheel_pyside) if not arch: raise RuntimeError("[DEPLOY] PySide wheel corrupted. Wheel name should end with" - "platform name") + "platform name") config.arch = arch + # TODO: include qml files from pysidedeploy.spec rather than from extensions + # buildozer currently includes all the files with .qml extension + + # init buildozer + Buildozer.dry_run = dry_run + logging.info("[DEPLOY] Creating buildozer.spec file") + Buildozer.initialize(pysidedeploy_config=config, generated_files_path=generated_files_path) + # writing config file if not dry_run: config.update_config() @@ -149,14 +158,6 @@ def main(name: str = None, pyside_wheel: Path = None, shiboken_wheel: Path = Non logging.info(f"[DEPLOY]: Config file {config.config_file} created") return - # TODO: include qml files from pysidedeploy.spec rather than from extensions - # buildozer currently includes all the files with .qml extension - - # init buildozer - Buildozer.dry_run = dry_run - logging.info("[DEPLOY] Creating buildozer.spec file") - Buildozer.initialize(pysidedeploy_config=config, generated_files_path=generated_files_path) - # run buildozer logging.info("[DEPLOY] Running buildozer deployment") Buildozer.create_executable(config.mode) @@ -166,7 +167,7 @@ def main(name: str = None, pyside_wheel: Path = None, shiboken_wheel: Path = Non buildozer_build_dir = config.project_dir / ".buildozer" if not buildozer_build_dir.exists(): logging.info(f"[DEPLOY] Unable to copy {buildozer_build_dir} to {generated_files_path}" - f"{buildozer_build_dir} does not exist") + f"{buildozer_build_dir} does not exist") logging.info(f"[DEPLOY] copy {buildozer_build_dir} to {generated_files_path}") shutil.move(buildozer_build_dir, generated_files_path) @@ -219,11 +220,14 @@ if __name__ == "__main__": required=not config_option_exists()) parser.add_argument("--ndk-path", type=lambda p: Path(p).resolve(), - help=("Path to Android Ndk. If omitted, the default from buildozer is used") + help=("Path to Android NDK. If omitted, the tool's cache at " + ".pyside6_android_deploy is checked to find the NDK") ) parser.add_argument("--sdk-path", type=lambda p: Path(p).resolve(), - help=("Path to Android Sdk. If omitted, the default from buildozer is used") + help=("Path to Android SDK. If omitted, the tool's cache at " + ".pyside6_android_deploy is checked to find the SDK. Otherwise " + "the default from buildozer is used.") ) parser.add_argument("--extra-ignore-dirs", type=str, help=HELP_EXTRA_IGNORE_DIRS) diff --git a/sources/pyside-tools/deploy.py b/sources/pyside-tools/deploy.py index e13d97385..0c75350d3 100644 --- a/sources/pyside-tools/deploy.py +++ b/sources/pyside-tools/deploy.py @@ -43,15 +43,13 @@ def main(main_file: Path = None, name: str = None, config_file: Path = None, ini force: bool = False): logging.basicConfig(level=loglevel) - - if not config_file and not main_file.exists(): - print(dedent(""" + if config_file and not config_file.exists() and not main_file.exists(): + raise RuntimeError(dedent(""" Directory does not contain main.py file. Please specify the main python entrypoint file or the config file. Run "pyside6-deploy desktop --help" to see info about cli options. pyside6-deploy exiting...""")) - return # Nuitka command to run command_str = None diff --git a/sources/pyside-tools/deploy_lib/android/android_helper.py b/sources/pyside-tools/deploy_lib/android/android_helper.py index 58efa0943..4489909d5 100644 --- a/sources/pyside-tools/deploy_lib/android/android_helper.py +++ b/sources/pyside-tools/deploy_lib/android/android_helper.py @@ -30,9 +30,9 @@ def create_recipe(version: str, component: str, wheel_path: str, generated_files ''' Create python_for_android recipe for PySide6 and shiboken6 ''' - qt_plugins = [] + qt_plugins = [] if plugins: - #split plugins based on category + # split plugins based on category for plugin in plugins: plugin_category, plugin_name = plugin.split('_', 1) qt_plugins.append((plugin_category, plugin_name)) @@ -70,7 +70,7 @@ def extract_and_copy_jar(wheel_path: Path, generated_files_path: Path) -> str: jar_files = [file for file in archive.namelist() if file.startswith("PySide6/jar")] for file in jar_files: archive.extract(file, jar_path) - return jar_path + return (jar_path / "PySide6" / "jar").resolve() if jar_files else None def get_wheel_android_arch(wheel: Path): @@ -89,11 +89,6 @@ def get_llvm_readobj(ndk_path: Path) -> Path: ''' Return the path to llvm_readobj from the Android Ndk ''' - if not ndk_path: - # fetch ndk path from buildozer - raise FileNotFoundError("[DEPLOY] Unable to find Ndk path. Please pass the Ndk path either" - " from the CLI or from pysidedeploy.spec") - # TODO: Requires change if Windows platform supports Android Deployment or if we # support host other than linux-x86_64 return (ndk_path / "toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-readobj") diff --git a/sources/pyside-tools/deploy_lib/android/buildozer.py b/sources/pyside-tools/deploy_lib/android/buildozer.py index 647951a09..3d187fa60 100644 --- a/sources/pyside-tools/deploy_lib/android/buildozer.py +++ b/sources/pyside-tools/deploy_lib/android/buildozer.py @@ -111,7 +111,7 @@ class BuildozerConfig(BaseConfig): self.set_value("app", "android.add_jars", ",".join(jars)) init_classes = ",".join(init_classes) - #extra arguments specific to Qt + # extra arguments specific to Qt extra_args = (f"--qt-libs={modules} --load-local-libs={local_libs}" f" --init-classes={init_classes}") self.set_value("app", "p4a.extra_args", extra_args) diff --git a/sources/pyside-tools/deploy_lib/config.py b/sources/pyside-tools/deploy_lib/config.py index b2b074a70..6859b1f76 100644 --- a/sources/pyside-tools/deploy_lib/config.py +++ b/sources/pyside-tools/deploy_lib/config.py @@ -132,21 +132,28 @@ class Config(BaseConfig): raise RuntimeError("[DEPLOY] Unable to find shiboken6 Android wheel") self.wheel_shiboken = Path(wheel_shiboken_temp).resolve() + self.ndk_path = None if android_data.ndk_path: + # from cli self.ndk_path = android_data.ndk_path else: + # from config ndk_path_temp = self.get_value("buildozer", "ndk_path") if ndk_path_temp: self.ndk_path = Path(ndk_path_temp) else: - self.ndk_path = (ANDROID_DEPLOY_CACHE / "android-ndk" + ndk_path_temp = (ANDROID_DEPLOY_CACHE / "android-ndk" / f"android-ndk-r{ANDROID_NDK_VERSION}") - if not self.ndk_path.exists(): - logging.info("[DEPLOY] Use default NDK from buildoer") + if ndk_path_temp.exists(): + self.ndk_path = ndk_path_temp if self.ndk_path: print(f"Using Android NDK: {str(self.ndk_path)}") + else: + raise FileNotFoundError("[DEPLOY] Unable to find Android NDK. Please pass the NDK " + "path either from the CLI or from pysidedeploy.spec") + self.sdk_path = None if android_data.sdk_path: self.sdk_path = android_data.sdk_path else: @@ -154,8 +161,10 @@ class Config(BaseConfig): if sdk_path_temp: self.sdk_path = Path(sdk_path_temp) else: - self.sdk_path = ANDROID_DEPLOY_CACHE / "android-sdk" - if not self.sdk_path.exists(): + sdk_path_temp = ANDROID_DEPLOY_CACHE / "android-sdk" + if sdk_path_temp.exists(): + self.sdk_path = sdk_path_temp + else: logging.info("[DEPLOY] Use default SDK from buildozer") if self.sdk_path: diff --git a/sources/pyside-tools/deploy_lib/python_helper.py b/sources/pyside-tools/deploy_lib/python_helper.py index 32bf04f2c..7a91ddfa1 100644 --- a/sources/pyside-tools/deploy_lib/python_helper.py +++ b/sources/pyside-tools/deploy_lib/python_helper.py @@ -62,10 +62,9 @@ def find_pyside_modules(project_dir: Path, extra_ignore_dirs: List[Path] = None, full_mod_name = imported_module.name if full_mod_name == "PySide6": logging.warning(IMPORT_WARNING_PYSIDE.format(str(py_file))) - except Exception as e: - logging.error(f"[DEPLOY] Finding module import failed on file {str(py_file)}") - raise e + raise RuntimeError(f"[DEPLOY] Finding module import failed on file {str(py_file)} with " + f"error {e}") return set(modules) -- cgit v1.2.3