diff options
Diffstat (limited to 'sources/pyside-tools/deploy_lib')
| -rw-r--r-- | sources/pyside-tools/deploy_lib/__init__.py | 2 | ||||
| -rw-r--r-- | sources/pyside-tools/deploy_lib/commands.py | 46 | ||||
| -rw-r--r-- | sources/pyside-tools/deploy_lib/config.py | 34 | ||||
| -rw-r--r-- | sources/pyside-tools/deploy_lib/default.spec | 6 | ||||
| -rw-r--r-- | sources/pyside-tools/deploy_lib/nuitka_helper.py | 18 | ||||
| -rw-r--r-- | sources/pyside-tools/deploy_lib/python_helper.py | 3 |
6 files changed, 89 insertions, 20 deletions
diff --git a/sources/pyside-tools/deploy_lib/__init__.py b/sources/pyside-tools/deploy_lib/__init__.py index b94bc665b..2ba281d78 100644 --- a/sources/pyside-tools/deploy_lib/__init__.py +++ b/sources/pyside-tools/deploy_lib/__init__.py @@ -1,6 +1,8 @@ # Copyright (C) 2022 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 +MAJOR_VERSION = 6 + from .commands import run_command from .nuitka_helper import Nuitka from .config import Config diff --git a/sources/pyside-tools/deploy_lib/commands.py b/sources/pyside-tools/deploy_lib/commands.py index 2733dd4c1..53ad633ea 100644 --- a/sources/pyside-tools/deploy_lib/commands.py +++ b/sources/pyside-tools/deploy_lib/commands.py @@ -4,29 +4,61 @@ import subprocess import sys import logging +from typing import List + +import json +from pathlib import Path """ All utility functions for deployment """ -def run_command(command, dry_run: bool): +def run_command(command, dry_run: bool, fetch_output: bool = False): command_str = " ".join([str(cmd) for cmd in command]) + output = None + is_windows = (sys.platform == "win32") try: if not dry_run: - subprocess.check_call(command, shell=(sys.platform == "win32")) + if fetch_output: + output = subprocess.check_output(command, shell=is_windows) + else: + subprocess.check_call(command, shell=is_windows) else: print(command_str + "\n") except FileNotFoundError as error: - logging.exception(f"[DEPLOY]: {error.filename} not found") + logging.exception(f"[DEPLOY] {error.filename} not found") raise except subprocess.CalledProcessError as error: logging.exception( - f"[DEPLOY]: Command {command_str} failed with error {error} and return_code" - f"{error.returncode}" + f"[DEPLOY] Command {command_str} failed with error {error} and return_code" + f"{error.returncode}" ) raise except Exception as error: - logging.exception(f"[DEPLOY]: Command {command_str} failed with error {error}") + logging.exception(f"[DEPLOY] Command {command_str} failed with error {error}") raise - return command_str + return command_str, output + + +def run_qmlimportscanner(qml_files: List[Path], dry_run: bool): + """ + Runs pyside6-qmlimportscanner to find all the imported qml modules + """ + if not qml_files: + return [] + + qml_modules = [] + cmd = ["pyside6-qmlimportscanner", "-qmlFiles"] + cmd.extend([str(qml_file) for qml_file in qml_files]) + + if dry_run: + run_command(command=cmd, dry_run=True) + + # we need to run qmlimportscanner during dry_run as well to complete the + # command being run by nuitka + _, json_string = run_command(command=cmd, dry_run=False, fetch_output=True) + json_string = json_string.decode("utf-8") + json_array = json.loads(json_string) + qml_modules = [item['name'] for item in json_array if item['type'] == "module"] + return qml_modules diff --git a/sources/pyside-tools/deploy_lib/config.py b/sources/pyside-tools/deploy_lib/config.py index d02558cca..ba165d20b 100644 --- a/sources/pyside-tools/deploy_lib/config.py +++ b/sources/pyside-tools/deploy_lib/config.py @@ -8,6 +8,11 @@ import shutil import logging from project import ProjectData +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"} class Config: @@ -60,8 +65,14 @@ class Config: else: self._find_and_set_qml_files() + self.excluded_qml_plugins = [] + if self.get_value("qt", "excluded_qml_plugins"): + self.excluded_qml_plugins = self.get_value("qt", "excluded_qml_plugins").split(",") + else: + self._find_and_set_excluded_qml_plugins() + def update_config(self): - logging.info("[DEPLOY] Creating {config_file}") + logging.info(f"[DEPLOY] Creating {self.config_file}") with open(self.config_file, "w+") as config_file: self.parser.write(config_file, space_around_delimiters=True) @@ -97,7 +108,7 @@ class Config: return self.get_value(config_property_group, config_property_key) else: logging.exception( - f"[DEPLOY]: No {config_property_key} specified in config file or as cli option" + f"[DEPLOY] No {config_property_key} specified in config file or as cli option" ) raise @@ -133,6 +144,14 @@ class Config: def python_path(self, python_path): self._python_path = python_path + @property + def excluded_qml_plugins(self): + return self._excluded_qml_plugins + + @excluded_qml_plugins.setter + def excluded_qml_plugins(self, excluded_qml_plugins): + self._excluded_qml_plugins = excluded_qml_plugins + 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""" @@ -224,3 +243,14 @@ class Config: self.set_value("app", "project_file", str(files[0].relative_to(self.project_dir))) logging.info(f"[DEPLOY] Project file {files[0]} found and set in config file") + def _find_and_set_excluded_qml_plugins(self): + if self.qml_files: + included_qml_modules = set(run_qmlimportscanner(qml_files=self.qml_files, + dry_run=self.dry_run)) + self.excluded_qml_plugins = EXCLUDED_QML_PLUGINS.difference(included_qml_modules) + + # needed for dry_run testing + self.excluded_qml_plugins = sorted(self.excluded_qml_plugins) + + if self.excluded_qml_plugins: + self.set_value("qt", "excluded_qml_plugins", ",".join(self.excluded_qml_plugins)) diff --git a/sources/pyside-tools/deploy_lib/default.spec b/sources/pyside-tools/deploy_lib/default.spec index 4558ae161..909b44d73 100644 --- a/sources/pyside-tools/deploy_lib/default.spec +++ b/sources/pyside-tools/deploy_lib/default.spec @@ -16,7 +16,6 @@ exec_directory = # Path to .pyproject project file project_file = - [python] # Python path @@ -33,8 +32,11 @@ packages = nuitka,ordered_set,zstandard # normally all the QML files are added automatically qml_files = +# excluded qml plugin binaries +excluded_qml_plugins = + [nuitka] # (str) specify any extra nuitka arguments # eg: extra_args = --show-modules --follow-stdlib -extra_args = --quiet +extra_args = --quiet --noinclude-qt-translations=True diff --git a/sources/pyside-tools/deploy_lib/nuitka_helper.py b/sources/pyside-tools/deploy_lib/nuitka_helper.py index 1f4e434c5..83144c7fe 100644 --- a/sources/pyside-tools/deploy_lib/nuitka_helper.py +++ b/sources/pyside-tools/deploy_lib/nuitka_helper.py @@ -6,7 +6,7 @@ import sys from pathlib import Path from typing import List -from . import run_command +from . import run_command, MAJOR_VERSION class Nuitka: @@ -17,20 +17,22 @@ class Nuitka: def __init__(self, nuitka): self.nuitka = nuitka - def create_executable( - self, source_file: Path, extra_args: str, qml_files: List[Path], dry_run: bool - ): + def create_executable(self, source_file: Path, extra_args: str, qml_files: List[Path], + excluded_qml_plugins, dry_run: bool): extra_args = extra_args.split() qml_args = [] if qml_files: - # this includes "all" the plugins - # FIXME: adding the "qml" plugin is equivalent to "all" because of dependencies - # Ideally it should only add the specific qml plugins. eg: quick window, quick controls qml_args.append("--include-qt-plugins=all") qml_args.extend( [f"--include-data-files={qml_file}=./{qml_file.name}" for qml_file in qml_files] ) + if excluded_qml_plugins: + prefix = "lib" if sys.platform != "win32" else "" + for plugin in excluded_qml_plugins: + dll_name = plugin.replace("Qt", f"Qt{MAJOR_VERSION}") + qml_args.append(f"--noinclude-dlls={prefix}{dll_name}*") + output_dir = source_file.parent / "deployment" if not dry_run: output_dir.mkdir(parents=True, exist_ok=True) @@ -48,5 +50,5 @@ class Nuitka: linux_icon = str(Path(__file__).parent / "pyside_icon.jpg") command.append(f"--linux-onefile-icon={linux_icon}") - command_str = run_command(command=command, dry_run=dry_run) + command_str, _ = run_command(command=command, dry_run=dry_run) return command_str diff --git a/sources/pyside-tools/deploy_lib/python_helper.py b/sources/pyside-tools/deploy_lib/python_helper.py index e92ce8e0c..0c1978a9d 100644 --- a/sources/pyside-tools/deploy_lib/python_helper.py +++ b/sources/pyside-tools/deploy_lib/python_helper.py @@ -60,7 +60,7 @@ class PythonExecutable: dry_run=self.dry_run, ) else: - logging.info(f"[DEPLOY]: Upgrading package: {package}") + logging.info(f"[DEPLOY] Upgrading package: {package}") run_command( command=[self.exe, "-m", "pip", "install", "--upgrade", package], dry_run=self.dry_run, @@ -77,6 +77,7 @@ class PythonExecutable: source_file=source_file, extra_args=extra_args, qml_files=config.qml_files, + excluded_qml_plugins=config.excluded_qml_plugins, dry_run=self.dry_run, ) |
