aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside-tools
diff options
context:
space:
mode:
authorShyamnath Premnadh <Shyamnath.Premnadh@qt.io>2023-10-23 13:50:08 +0200
committerShyamnath Premnadh <Shyamnath.Premnadh@qt.io>2023-11-28 15:58:37 +0100
commit120a14487c86c96cf4818e04b9e919be6495151d (patch)
tree00f1515dac19c32d5e50134d924e3980eb090e8f /sources/pyside-tools
parent782c0757f43651e25f17cd28cda07f8293c3c107 (diff)
Deployment: Code Refactoring
- Move android related configurations into a new class AndroidConfig. This class inherits from the class Config. - Move configuration related code sections from `android_deploy.py` to `android_config.py` - get_config() renamed to create_config_file(). This simplifies a lot of code and makes Android deployment independent of Desktop deployment. - Move `generated_files_path` to `config.py`. As a result, `generated_files_path` does not need to be passed as parameter to to functions like `cleanup()`, `finalize()`, `Buildozer.initialize()` as config is already passed. - generated_files_path expression changed. This is because we assume the project_dir is always the parent of the source_file (i.e. main.py) - `Buildozer` import removed from `android/__init__.py` to prevent circular import issues. - Change buildozer commands to use "python -m" as prefix. Pick-to: 6.6 Task-number: PYSIDE-1612 Change-Id: Ie460dc459908dab44de82c3e269b806aff2c27c5 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'sources/pyside-tools')
-rw-r--r--sources/pyside-tools/android_deploy.py71
-rw-r--r--sources/pyside-tools/deploy.py28
-rw-r--r--sources/pyside-tools/deploy_lib/__init__.py6
-rw-r--r--sources/pyside-tools/deploy_lib/android/__init__.py8
-rw-r--r--sources/pyside-tools/deploy_lib/android/android_config.py242
-rw-r--r--sources/pyside-tools/deploy_lib/android/buildozer.py19
-rw-r--r--sources/pyside-tools/deploy_lib/config.py199
-rw-r--r--sources/pyside-tools/deploy_lib/deploy_util.py34
-rw-r--r--sources/pyside-tools/deploy_lib/python_helper.py4
9 files changed, 327 insertions, 284 deletions
diff --git a/sources/pyside-tools/android_deploy.py b/sources/pyside-tools/android_deploy.py
index 8ac8aa510..ef39d66b4 100644
--- a/sources/pyside-tools/android_deploy.py
+++ b/sources/pyside-tools/android_deploy.py
@@ -8,11 +8,11 @@ import traceback
from pathlib import Path
from textwrap import dedent
-from deploy_lib import (MAJOR_VERSION, cleanup, config_option_exists,
- find_pyside_modules, get_config,
- install_python_dependencies, setup_python)
-from deploy_lib.android import (AndroidData, Buildozer, extract_and_copy_jar,
- get_wheel_android_arch)
+from deploy_lib import (setup_python, create_config_file, cleanup, install_python_dependencies,
+ config_option_exists, MAJOR_VERSION)
+from deploy_lib.android import AndroidData, AndroidConfig
+from deploy_lib.android.buildozer import Buildozer
+
""" pyside6-android-deploy deployment tool
@@ -87,7 +87,6 @@ def main(name: str = None, pyside_wheel: Path = None, shiboken_wheel: Path = Non
extra_modules.append(extra_module)
main_file = Path.cwd() / "main.py"
- generated_files_path = None
if not main_file.exists():
raise RuntimeError(("[DEPLOY] For Android deployment to work, the main"
" entrypoint Python file should be named 'main.py'"
@@ -98,16 +97,25 @@ def main(name: str = None, pyside_wheel: Path = None, shiboken_wheel: Path = Non
ndk_path=ndk_path, sdk_path=sdk_path)
python = setup_python(dry_run=dry_run, force=force, init=init)
- config = get_config(python_exe=python.exe, dry_run=dry_run, config_file=config_file,
- main_file=main_file, android_data=android_data, is_android=True)
+
+ config_file_exists = config_file and Path(config_file).exists()
+
+ if config_file_exists:
+ logging.info(f"[DEPLOY] Using existing config file {config_file}")
+ else:
+ config_file = create_config_file(dry_run=dry_run, config_file=config_file,
+ main_file=main_file)
+
+ config = AndroidConfig(config_file=config_file, source_file=main_file,
+ python_exe=python.exe, dry_run=dry_run, android_data=android_data,
+ existing_config_file=config_file_exists,
+ extra_ignore_dirs=extra_ignore_dirs)
if not config.wheel_pyside and not config.wheel_shiboken:
raise RuntimeError(f"[DEPLOY] No PySide{MAJOR_VERSION} and Shiboken{MAJOR_VERSION} wheels"
"found")
- source_file = config.project_dir / config.source_file
- generated_files_path = source_file.parent / "deployment"
- cleanup(generated_files_path=generated_files_path, config=config, is_android=True)
+ cleanup(config=config, is_android=True)
install_python_dependencies(config=config, python=python, init=init,
packages="android_packages", is_android=True)
@@ -117,29 +125,11 @@ def main(name: str = None, pyside_wheel: Path = None, shiboken_wheel: Path = Non
config.title = name
try:
- # check which modules are needed
- if not config.modules:
- config.modules = find_pyside_modules(project_dir=config.project_dir,
- extra_ignore_dirs=extra_ignore_dirs,
- project_data=config.project_data)
- logging.info("The following PySide modules were found from the python files of "
- f"the project {config.modules}")
- config.modules.extend(extra_modules)
-
- # extract out and copy .jar files to {generated_files_path}
- 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}")
- 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")
- config.arch = arch
+ config.modules += extra_modules
+
+ # this cannot be done when config file is initialized because cleanup() removes it
+ # so this can only be done after the cleanup()
+ config.find_and_set_jars_dir()
# TODO: include qml files from pysidedeploy.spec rather than from extensions
# buildozer currently includes all the files with .qml extension
@@ -147,7 +137,7 @@ def main(name: str = None, pyside_wheel: Path = None, shiboken_wheel: Path = Non
# 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)
+ Buildozer.initialize(pysidedeploy_config=config)
# writing config file
if not dry_run:
@@ -167,17 +157,16 @@ 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 "
- f"{generated_files_path}. {buildozer_build_dir} does not exist")
- logging.info(f"[DEPLOY] Copying {str(buildozer_build_dir)} to "
- f"{str(generated_files_path)}")
- shutil.move(buildozer_build_dir, generated_files_path)
+ f"{config.generated_files_path}. {buildozer_build_dir} does not exist")
+ logging.info(f"[DEPLOY] copy {buildozer_build_dir} to {config.generated_files_path}")
+ shutil.move(buildozer_build_dir, config.generated_files_path)
logging.info(f"[DEPLOY] apk created in {config.exe_dir}")
except Exception:
print(f"Exception occurred: {traceback.format_exc()}")
finally:
- if generated_files_path and config and not keep_deployment_files:
- cleanup(generated_files_path=generated_files_path, config=config, is_android=True)
+ if config.generated_files_path and config and not keep_deployment_files:
+ cleanup(config=config, is_android=True)
logging.info("[DEPLOY] End")
diff --git a/sources/pyside-tools/deploy.py b/sources/pyside-tools/deploy.py
index b19fbb0d1..f5197b6cf 100644
--- a/sources/pyside-tools/deploy.py
+++ b/sources/pyside-tools/deploy.py
@@ -35,7 +35,7 @@ from pathlib import Path
from textwrap import dedent
from deploy_lib import (MAJOR_VERSION, Config, cleanup, config_option_exists,
- finalize, get_config, install_python_dependencies,
+ finalize, create_config_file, install_python_dependencies,
setup_python)
@@ -54,22 +54,26 @@ def main(main_file: Path = None, name: str = None, config_file: Path = None, ini
# Nuitka command to run
command_str = None
- generated_files_path = None
config = None
logging.info("[DEPLOY] Start")
python = setup_python(dry_run=dry_run, force=force, init=init)
- config = get_config(python_exe=python.exe, dry_run=dry_run, config_file=config_file,
- main_file=main_file)
+ config_file_exists = config_file and Path(config_file).exists()
+
+ if config_file_exists:
+ logging.info(f"[DEPLOY] Using existing config file {config_file}")
+ else:
+ config_file = create_config_file(dry_run=dry_run, config_file=config_file,
+ main_file=main_file)
+
+ config = Config(config_file=config_file, source_file=main_file, python_exe=python.exe,
+ dry_run=dry_run, existing_config_file=config_file_exists)
# set application name
if name:
config.title = name
- source_file = config.project_dir / config.source_file
-
- generated_files_path = source_file.parent / "deployment"
- cleanup(generated_files_path=generated_files_path, config=config)
+ cleanup(config=config)
install_python_dependencies(config=config, python=python, init=init,
packages="packages")
@@ -96,17 +100,17 @@ def main(main_file: Path = None, name: str = None, config_file: Path = None, ini
logging.info("[DEPLOY] Deploying application")
command_str = python.create_executable(
- source_file=source_file,
+ source_file=config.source_file,
extra_args=config.extra_args,
config=config,
)
except Exception:
print(f"[DEPLOY] Exception occurred: {traceback.format_exc()}")
finally:
- if generated_files_path and config:
- finalize(generated_files_path=generated_files_path, config=config)
+ if config.generated_files_path and config:
+ finalize(config=config)
if not keep_deployment_files:
- cleanup(generated_files_path=generated_files_path, config=Config)
+ cleanup(config=config)
logging.info("[DEPLOY] End")
return command_str
diff --git a/sources/pyside-tools/deploy_lib/__init__.py b/sources/pyside-tools/deploy_lib/__init__.py
index 468a03673..a8ac99bde 100644
--- a/sources/pyside-tools/deploy_lib/__init__.py
+++ b/sources/pyside-tools/deploy_lib/__init__.py
@@ -6,8 +6,8 @@ MAJOR_VERSION = 6
EXE_FORMAT = ".exe" if sys.platform == "win32" else ".bin"
from .commands import run_command
-from .config import BaseConfig, Config
from .nuitka_helper import Nuitka
-from .deploy_util import (cleanup, config_option_exists, finalize, get_config,
- install_python_dependencies, setup_python)
from .python_helper import PythonExecutable, find_pyside_modules
+from .config import BaseConfig, Config
+from .deploy_util import (cleanup, finalize, create_config_file, setup_python,
+ install_python_dependencies, config_option_exists)
diff --git a/sources/pyside-tools/deploy_lib/android/__init__.py b/sources/pyside-tools/deploy_lib/android/__init__.py
index 907e12e1f..ba7a2b4e9 100644
--- a/sources/pyside-tools/deploy_lib/android/__init__.py
+++ b/sources/pyside-tools/deploy_lib/android/__init__.py
@@ -1,7 +1,7 @@
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-from .android_helper import (AndroidData, create_recipe, extract_and_copy_jar,
- find_lib_dependencies, find_qtlibs_in_wheel,
- get_llvm_readobj, get_wheel_android_arch)
-from .buildozer import Buildozer
+from .android_helper import (create_recipe, extract_and_copy_jar, get_wheel_android_arch,
+ AndroidData, get_llvm_readobj, find_lib_dependencies,
+ find_qtlibs_in_wheel)
+from .android_config import AndroidConfig
diff --git a/sources/pyside-tools/deploy_lib/android/android_config.py b/sources/pyside-tools/deploy_lib/android/android_config.py
new file mode 100644
index 000000000..a6b2cf052
--- /dev/null
+++ b/sources/pyside-tools/deploy_lib/android/android_config.py
@@ -0,0 +1,242 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+import logging
+
+from typing import List
+from pathlib import Path
+
+from . import extract_and_copy_jar, get_wheel_android_arch
+from .. import Config, find_pyside_modules
+
+ANDROID_NDK_VERSION = "25c"
+ANDROID_DEPLOY_CACHE = Path.home() / ".pyside6_android_deploy"
+
+
+class AndroidConfig(Config):
+ """
+ Wrapper class around pysidedeploy.spec file for pyside6-android-deploy
+ """
+ def __init__(self, config_file: Path, source_file: Path, python_exe: Path, dry_run: bool,
+ android_data, existing_config_file: bool = False,
+ extra_ignore_dirs: List[str] = None):
+ super().__init__(config_file=config_file, source_file=source_file, python_exe=python_exe,
+ dry_run=dry_run, existing_config_file=existing_config_file)
+
+ self.extra_ignore_dirs = extra_ignore_dirs
+
+ if android_data.wheel_pyside:
+ self.wheel_pyside = android_data.wheel_pyside
+ else:
+ wheel_pyside_temp = self.get_value("qt", "wheel_pyside")
+ if not wheel_pyside_temp:
+ raise RuntimeError("[DEPLOY] Unable to find PySide6 Android wheel")
+ self.wheel_pyside = Path(wheel_pyside_temp).resolve()
+
+ if android_data.wheel_shiboken:
+ self.wheel_shiboken = android_data.wheel_shiboken
+ else:
+ wheel_shiboken_temp = self.get_value("qt", "wheel_shiboken")
+ if not wheel_shiboken_temp:
+ 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:
+ ndk_path_temp = (ANDROID_DEPLOY_CACHE / "android-ndk"
+ / f"android-ndk-r{ANDROID_NDK_VERSION}")
+ 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:
+ sdk_path_temp = self.get_value("buildozer", "sdk_path")
+ if sdk_path_temp:
+ self.sdk_path = Path(sdk_path_temp)
+ else:
+ 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:
+ print(f"Using Android SDK: {str(self.sdk_path)}")
+
+ recipe_dir_temp = self.get_value("buildozer", "recipe_dir")
+ self.recipe_dir = Path(recipe_dir_temp) if recipe_dir_temp else None
+
+ self._jars_dir = []
+ jars_dir_temp = self.get_value("buildozer", "jars_dir")
+ if jars_dir_temp and Path(jars_dir_temp).resolve().exists():
+ self.jars_dir = Path(jars_dir_temp).resolve()
+
+ self._modules = []
+ if self.get_value("buildozer", "modules"):
+ self.modules = self.get_value("buildozer", "modules").split(",")
+ else:
+ self._find_and_set_pysidemodules()
+
+ self._arch = None
+ if self.get_value("buildozer", "arch"):
+ self.arch = self.get_value("buildozer", "arch")
+ else:
+ self._find_and_set_arch()
+
+ self._local_libs = []
+ if self.get_value("buildozer", "local_libs"):
+ self.local_libs = self.get_value("buildozer", "local_libs").split(",")
+
+ self._qt_plugins = []
+ if self.get_value("qt", "plugins"):
+ self._qt_plugins = self.get_value("qt", "plugins").split(",")
+
+ self._mode = self.get_value("buildozer", "mode")
+
+ @property
+ def qt_plugins(self):
+ return self._qt_plugins
+
+ @qt_plugins.setter
+ def qt_plugins(self, qt_plugins):
+ self._qt_plugins = qt_plugins
+ self.set_value("qt", "plugins", ",".join(qt_plugins))
+
+ @property
+ def ndk_path(self):
+ return self._ndk_path
+
+ @ndk_path.setter
+ def ndk_path(self, ndk_path: Path):
+ self._ndk_path = ndk_path.resolve() if ndk_path else None
+ if self._ndk_path:
+ self.set_value("buildozer", "ndk_path", str(self._ndk_path))
+
+ @property
+ def sdk_path(self) -> Path:
+ return self._sdk_path
+
+ @sdk_path.setter
+ def sdk_path(self, sdk_path: Path):
+ self._sdk_path = sdk_path.resolve() if sdk_path else None
+ if self._sdk_path:
+ self.set_value("buildozer", "sdk_path", str(self._sdk_path))
+
+ @property
+ def arch(self):
+ return self._arch
+
+ @arch.setter
+ def arch(self, arch):
+ self._arch = arch
+ self.set_value("buildozer", "arch", arch)
+
+ @property
+ def mode(self):
+ return self._mode
+
+ @property
+ def modules(self):
+ return self._modules
+
+ @modules.setter
+ def modules(self, modules):
+ self._modules = modules
+ self.set_value("buildozer", "modules", ",".join(modules))
+
+ @property
+ def local_libs(self):
+ return self._local_libs
+
+ @local_libs.setter
+ def local_libs(self, local_libs):
+ self._local_libs = local_libs
+ self.set_value("buildozer", "local_libs", ",".join(local_libs))
+
+ @property
+ def recipe_dir(self):
+ return self._recipe_dir
+
+ @recipe_dir.setter
+ def recipe_dir(self, recipe_dir: Path):
+ self._recipe_dir = recipe_dir.resolve() if recipe_dir else None
+ if self._recipe_dir:
+ self.set_value("buildozer", "recipe_dir", str(self._recipe_dir))
+
+ def recipes_exist(self):
+ if not self._recipe_dir:
+ return False
+
+ pyside_recipe_dir = Path(self.recipe_dir) / "PySide6"
+ shiboken_recipe_dir = Path(self.recipe_dir) / "shiboken6"
+
+ return pyside_recipe_dir.is_dir() and shiboken_recipe_dir.is_dir()
+
+ @property
+ def jars_dir(self) -> Path:
+ return self._jars_dir
+
+ @jars_dir.setter
+ def jars_dir(self, jars_dir: Path):
+ self._jars_dir = jars_dir.resolve() if jars_dir else None
+ if self._jars_dir:
+ self.set_value("buildozer", "jars_dir", str(self._jars_dir))
+
+ @property
+ def wheel_pyside(self) -> Path:
+ return self._wheel_pyside
+
+ @wheel_pyside.setter
+ def wheel_pyside(self, wheel_pyside: Path):
+ self._wheel_pyside = wheel_pyside.resolve() if wheel_pyside else None
+ if self._wheel_pyside:
+ self.set_value("qt", "wheel_pyside", str(self._wheel_pyside))
+
+ @property
+ def wheel_shiboken(self) -> Path:
+ return self._wheel_shiboken
+
+ @wheel_shiboken.setter
+ def wheel_shiboken(self, wheel_shiboken: Path):
+ self._wheel_shiboken = wheel_shiboken.resolve() if wheel_shiboken else None
+ if self._wheel_shiboken:
+ self.set_value("qt", "wheel_shiboken", str(self._wheel_shiboken))
+
+ def _find_and_set_pysidemodules(self):
+ self.modules = find_pyside_modules(project_dir=self.project_dir,
+ extra_ignore_dirs=self.extra_ignore_dirs,
+ project_data=self.project_data)
+ logging.info("The following PySide modules were found from the python files of "
+ f"the project {self.modules}")
+
+ def find_and_set_jars_dir(self):
+ """Extract out and copy .jar files to {generated_files_path}
+ """
+ if not self.dry_run:
+ logging.info("[DEPLOY] Extract and copy jar files from PySide6 wheel to "
+ f"{self.generated_files_path}")
+ self.jars_dir = extract_and_copy_jar(wheel_path=self.wheel_pyside,
+ generated_files_path=self.generated_files_path)
+
+ def _find_and_set_arch(self):
+ """Find architecture from wheel name
+ """
+ self.arch = get_wheel_android_arch(wheel=self.wheel_pyside)
+ if not self.arch:
+ raise RuntimeError("[DEPLOY] PySide wheel corrupted. Wheel name should end with"
+ "platform name")
diff --git a/sources/pyside-tools/deploy_lib/android/buildozer.py b/sources/pyside-tools/deploy_lib/android/buildozer.py
index f66a4b01c..f17ffd116 100644
--- a/sources/pyside-tools/deploy_lib/android/buildozer.py
+++ b/sources/pyside-tools/deploy_lib/android/buildozer.py
@@ -1,6 +1,7 @@
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+import sys
import logging
import re
import tempfile
@@ -22,8 +23,7 @@ ALL_PYSIDE_MODULES = [module[2:] for module in PySide6.__all__]
class BuildozerConfig(BaseConfig):
- def __init__(self, buildozer_spec_file: Path, pysidedeploy_config: Config,
- generated_files_path: Path):
+ def __init__(self, buildozer_spec_file: Path, pysidedeploy_config: Config):
super().__init__(buildozer_spec_file, comment_prefixes="#")
self.set_value("app", "title", pysidedeploy_config.title)
self.set_value("app", "package.name", pysidedeploy_config.title)
@@ -97,14 +97,15 @@ class BuildozerConfig(BaseConfig):
version = Wheel(pysidedeploy_config.wheel_pyside).version
create_recipe(version=version, component=f"PySide{MAJOR_VERSION}",
wheel_path=pysidedeploy_config.wheel_pyside,
- generated_files_path=generated_files_path,
+ generated_files_path=pysidedeploy_config.generated_files_path,
qt_modules=pysidedeploy_config.modules,
local_libs=pysidedeploy_config.local_libs,
plugins=pysidedeploy_config.qt_plugins)
create_recipe(version=version, component=f"shiboken{MAJOR_VERSION}",
wheel_path=pysidedeploy_config.wheel_shiboken,
- generated_files_path=generated_files_path)
- pysidedeploy_config.recipe_dir = (generated_files_path / "recipes").resolve()
+ generated_files_path=pysidedeploy_config.generated_files_path)
+ pysidedeploy_config.recipe_dir = ((pysidedeploy_config.generated_files_path
+ / "recipes").resolve())
self.set_value('app', "p4a.local_recipes", str(pysidedeploy_config.recipe_dir))
# add permissions
@@ -332,7 +333,7 @@ class Buildozer:
dry_run = False
@staticmethod
- def initialize(pysidedeploy_config: Config, generated_files_path: Path):
+ def initialize(pysidedeploy_config: Config):
project_dir = Path(pysidedeploy_config.project_dir)
buildozer_spec = project_dir / "buildozer.spec"
if buildozer_spec.exists():
@@ -341,14 +342,14 @@ class Buildozer:
return
# creates buildozer.spec config file
- command = ["buildozer", "init"]
+ command = [sys.executable, "-m", "buildozer", "init"]
run_command(command=command, dry_run=Buildozer.dry_run)
if not Buildozer.dry_run:
if not buildozer_spec.exists():
raise RuntimeError(f"buildozer.spec not found in {Path.cwd()}")
- BuildozerConfig(buildozer_spec, pysidedeploy_config, generated_files_path)
+ BuildozerConfig(buildozer_spec, pysidedeploy_config)
@staticmethod
def create_executable(mode: str):
- command = ["buildozer", "android", mode]
+ command = [sys.executable, "-m", "buildozer", "android", mode]
run_command(command=command, dry_run=Buildozer.dry_run)
diff --git a/sources/pyside-tools/deploy_lib/config.py b/sources/pyside-tools/deploy_lib/config.py
index f6898ad72..94a287eaf 100644
--- a/sources/pyside-tools/deploy_lib/config.py
+++ b/sources/pyside-tools/deploy_lib/config.py
@@ -6,6 +6,7 @@ import logging
import warnings
from configparser import ConfigParser
from pathlib import Path
+from typing import List
from project import ProjectData
@@ -14,9 +15,6 @@ from .commands import run_qmlimportscanner
# Some QML plugins like QtCore are excluded from this list as they don't contribute much to
# executable size. Excluding them saves the extra processing of checking for them in files
EXCLUDED_QML_PLUGINS = {"QtQuick", "QtQuick3D", "QtCharts", "QtWebEngine", "QtTest", "QtSensors"}
-# TODO: Move this to android module. Fix circular import.
-ANDROID_NDK_VERSION = "25c"
-ANDROID_DEPLOY_CACHE = Path.home() / ".pyside6_android_deploy"
class BaseConfig:
@@ -63,14 +61,14 @@ class Config(BaseConfig):
"""
def __init__(self, config_file: Path, source_file: Path, python_exe: Path, dry_run: bool,
- android_data, is_android: bool, existing_config_file: bool = False):
+ existing_config_file: bool = False):
super().__init__(config_file=config_file, existing_config_file=existing_config_file)
self._dry_run = dry_run
# set source_file
self.source_file = Path(
self.set_or_fetch(config_property_val=source_file, config_property_key="input_file")
- )
+ ).resolve()
# set python path
self.python_path = Path(
@@ -115,83 +113,7 @@ class Config(BaseConfig):
else:
self._find_and_set_excluded_qml_plugins()
- # Android
- if is_android:
- if android_data.wheel_pyside:
- self.wheel_pyside = android_data.wheel_pyside
- else:
- wheel_pyside_temp = self.get_value("qt", "wheel_pyside")
- if not wheel_pyside_temp:
- raise RuntimeError("[DEPLOY] Unable to find PySide6 Android wheel")
- self.wheel_pyside = Path(wheel_pyside_temp).resolve()
-
- if android_data.wheel_shiboken:
- self.wheel_shiboken = android_data.wheel_shiboken
- else:
- wheel_shiboken_temp = self.get_value("qt", "wheel_shiboken")
- if not wheel_shiboken_temp:
- 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:
- ndk_path_temp = (ANDROID_DEPLOY_CACHE / "android-ndk"
- / f"android-ndk-r{ANDROID_NDK_VERSION}")
- 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:
- sdk_path_temp = self.get_value("buildozer", "sdk_path")
- if sdk_path_temp:
- self.sdk_path = Path(sdk_path_temp)
- else:
- 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:
- print(f"Using Android SDK: {str(self.sdk_path)}")
-
- recipe_dir_temp = self.get_value("buildozer", "recipe_dir")
- self.recipe_dir = Path(recipe_dir_temp) if recipe_dir_temp else None
-
- jars_dir_temp = self.get_value("buildozer", "jars_dir")
- self.jars_dir = Path(jars_dir_temp) if jars_dir_temp else None
-
- self._modules = []
- if self.get_value("buildozer", "modules"):
- self.modules = self.get_value("buildozer", "modules").split(",")
-
- self.arch = self.get_value("buildozer", "arch")
-
- self._local_libs = []
- if self.get_value("buildozer", "local_libs"):
- self.local_libs = self.get_value("buildozer", "local_libs").split(",")
-
- self._qt_plugins = []
- if self.get_value("qt", "plugins"):
- self._qt_plugins = self.get_value("qt", "plugins").split(",")
-
- self._mode = self.get_value("buildozer", "mode")
+ self._generated_files_path = self.project_dir / "deployment"
def set_or_fetch(self, config_property_val, config_property_key, config_property_group="app"):
"""
@@ -215,6 +137,10 @@ class Config(BaseConfig):
return self._dry_run
@property
+ def generated_files_path(self):
+ return self._generated_files_path
+
+ @property
def qml_files(self):
return self._qml_files
@@ -272,95 +198,6 @@ class Config(BaseConfig):
self._excluded_qml_plugins = excluded_qml_plugins
@property
- def recipe_dir(self):
- return self._recipe_dir
-
- @recipe_dir.setter
- def recipe_dir(self, recipe_dir: Path):
- self._recipe_dir = recipe_dir.resolve() if recipe_dir else None
- if self._recipe_dir:
- self.set_value("buildozer", "recipe_dir", str(self._recipe_dir))
-
- def recipes_exist(self):
- if not self._recipe_dir:
- return False
-
- pyside_recipe_dir = Path(self.recipe_dir) / "PySide6"
- shiboken_recipe_dir = Path(self.recipe_dir) / "shiboken6"
-
- return pyside_recipe_dir.is_dir() and shiboken_recipe_dir.is_dir()
-
- @property
- def jars_dir(self) -> Path:
- return self._jars_dir
-
- @jars_dir.setter
- def jars_dir(self, jars_dir: Path):
- self._jars_dir = jars_dir.resolve() if jars_dir else None
- if self._jars_dir:
- self.set_value("buildozer", "jars_dir", str(self._jars_dir))
-
- @property
- def modules(self):
- return self._modules
-
- @modules.setter
- def modules(self, modules):
- self._modules = modules
- self.set_value("buildozer", "modules", ",".join(modules))
-
- @property
- def local_libs(self):
- return self._local_libs
-
- @local_libs.setter
- def local_libs(self, local_libs):
- self._local_libs = local_libs
- self.set_value("buildozer", "local_libs", ",".join(local_libs))
-
- @property
- def qt_plugins(self):
- return self._qt_plugins
-
- @qt_plugins.setter
- def qt_plugins(self, qt_plugins):
- self._qt_plugins = qt_plugins
- self.set_value("qt", "plugins", ",".join(qt_plugins))
-
- @property
- def ndk_path(self):
- return self._ndk_path
-
- @ndk_path.setter
- def ndk_path(self, ndk_path: Path):
- self._ndk_path = ndk_path.resolve() if ndk_path else None
- if self._ndk_path:
- self.set_value("buildozer", "ndk_path", str(self._ndk_path))
-
- @property
- def sdk_path(self) -> Path:
- return self._sdk_path
-
- @sdk_path.setter
- def sdk_path(self, sdk_path: Path):
- self._sdk_path = sdk_path.resolve() if sdk_path else None
- if self._sdk_path:
- self.set_value("buildozer", "sdk_path", str(self._sdk_path))
-
- @property
- def arch(self):
- return self._arch
-
- @arch.setter
- def arch(self, arch):
- self._arch = arch
- self.set_value("buildozer", "arch", arch)
-
- @property
- def mode(self):
- return self._mode
-
- @property
def exe_dir(self):
return self._exe_dir
@@ -368,26 +205,6 @@ class Config(BaseConfig):
def exe_dir(self, exe_dir: Path):
self._exe_dir = exe_dir
- @property
- def wheel_pyside(self) -> Path:
- return self._wheel_pyside
-
- @wheel_pyside.setter
- def wheel_pyside(self, wheel_pyside: Path):
- self._wheel_pyside = wheel_pyside.resolve() if wheel_pyside else None
- if self._wheel_pyside:
- self.set_value("qt", "wheel_pyside", str(self._wheel_pyside))
-
- @property
- def wheel_shiboken(self) -> Path:
- return self._wheel_shiboken
-
- @wheel_shiboken.setter
- def wheel_shiboken(self, wheel_shiboken: Path):
- self._wheel_shiboken = wheel_shiboken.resolve() if wheel_shiboken else None
- if self._wheel_shiboken:
- self.set_value("qt", "wheel_shiboken", str(self._wheel_shiboken))
-
def _find_and_set_qml_files(self):
"""Fetches all the qml_files in the folder and sets them if the
field qml_files is empty in the config_dir"""
diff --git a/sources/pyside-tools/deploy_lib/deploy_util.py b/sources/pyside-tools/deploy_lib/deploy_util.py
index a73ccb0eb..368ad682e 100644
--- a/sources/pyside-tools/deploy_lib/deploy_util.py
+++ b/sources/pyside-tools/deploy_lib/deploy_util.py
@@ -19,12 +19,12 @@ def config_option_exists():
return False
-def cleanup(generated_files_path: Path, config: Config, is_android: bool = False):
+def cleanup(config: Config, is_android: bool = False):
"""
Cleanup the generated build folders/files
"""
- if generated_files_path.exists():
- shutil.rmtree(generated_files_path)
+ if config.generated_files_path.exists():
+ shutil.rmtree(config.generated_files_path)
logging.info("[DEPLOY] Deployment directory purged")
if is_android:
@@ -39,37 +39,27 @@ def cleanup(generated_files_path: Path, config: Config, is_android: bool = False
logging.info(f"[DEPLOY] {str(buildozer_build)} removed")
-def get_config(python_exe: Path, dry_run: bool = False, config_file: Path = None, main_file:
- Path = None, android_data=None, is_android: bool = False):
+def create_config_file(dry_run: bool = False, config_file: Path = None, main_file: Path = None):
"""
Sets up a new pysidedeploy.spec or use an existing config file
"""
- config_file_exists = config_file and Path(config_file).exists()
-
- if main_file and not config_file_exists:
+ if main_file:
if main_file.parent != Path.cwd():
config_file = main_file.parent / "pysidedeploy.spec"
else:
config_file = Path.cwd() / "pysidedeploy.spec"
- if config_file_exists:
- logging.info(f"[DEPLOY] Using existing config file {config_file}")
- else:
- logging.info(f"[DEPLOY] Creating config file {config_file}")
- if not dry_run:
- shutil.copy(Path(__file__).parent / "default.spec", config_file)
+ logging.info(f"[DEPLOY] Creating config file {config_file}")
+ if not dry_run:
+ shutil.copy(Path(__file__).parent / "default.spec", config_file)
# the config parser needs a reference to parse. So, in the case of --dry-run
# use the default.spec file.
- if dry_run and not config_file_exists:
+ if dry_run:
config_file = Path(__file__).parent / "default.spec"
- config = Config(config_file=config_file, source_file=main_file, python_exe=python_exe,
- dry_run=dry_run, android_data=android_data, is_android=is_android,
- existing_config_file=config_file_exists)
-
- return config
+ return config_file
def setup_python(dry_run: bool, force: bool, init: bool):
@@ -109,12 +99,12 @@ def install_python_dependencies(config: Config, python: PythonExecutable, init:
python.install(packages=["patchelf"])
-def finalize(generated_files_path: Path, config: Config):
+def finalize(config: Config):
"""
Copy the executable into the final location
For Android deployment, this is done through buildozer
"""
- generated_exec_path = generated_files_path / (config.source_file.stem + EXE_FORMAT)
+ generated_exec_path = config.generated_files_path / (config.source_file.stem + EXE_FORMAT)
if generated_exec_path.exists() and config.exe_dir:
shutil.copy(generated_exec_path, config.exe_dir)
print("[DEPLOY] Executed file created in "
diff --git a/sources/pyside-tools/deploy_lib/python_helper.py b/sources/pyside-tools/deploy_lib/python_helper.py
index f403b2d47..1e5f77b78 100644
--- a/sources/pyside-tools/deploy_lib/python_helper.py
+++ b/sources/pyside-tools/deploy_lib/python_helper.py
@@ -12,7 +12,7 @@ from importlib import util
from importlib.metadata import version
from pathlib import Path
-from . import Config, Nuitka, run_command
+from . import Nuitka, run_command
IMPORT_WARNING_PYSIDE = (f"[DEPLOY] Found 'import PySide6' in file {0}"
". Use 'from PySide6 import <module>' or pass the module"
@@ -193,7 +193,7 @@ class PythonExecutable:
def is_installed(self, package):
return bool(util.find_spec(package))
- def create_executable(self, source_file: Path, extra_args: str, config: Config):
+ def create_executable(self, source_file: Path, extra_args: str, config):
if config.qml_files:
logging.info(f"[DEPLOY] Included QML files: {config.qml_files}")