aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside-tools/deploy_lib/nuitka_helper.py
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside-tools/deploy_lib/nuitka_helper.py')
-rw-r--r--sources/pyside-tools/deploy_lib/nuitka_helper.py90
1 files changed, 80 insertions, 10 deletions
diff --git a/sources/pyside-tools/deploy_lib/nuitka_helper.py b/sources/pyside-tools/deploy_lib/nuitka_helper.py
index 83144c7fe..5d0e9032f 100644
--- a/sources/pyside-tools/deploy_lib/nuitka_helper.py
+++ b/sources/pyside-tools/deploy_lib/nuitka_helper.py
@@ -1,12 +1,17 @@
# 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
+# enables to use typehints for classes that has not been defined yet or imported
+# used for resolving circular imports
+from __future__ import annotations
+import logging
import os
import sys
from pathlib import Path
from typing import List
-from . import run_command, MAJOR_VERSION
+from . import MAJOR_VERSION, run_command
+from .config import DesktopConfig
class Nuitka:
@@ -16,16 +21,71 @@ class Nuitka:
def __init__(self, nuitka):
self.nuitka = nuitka
+ # plugins to ignore. The sensible plugins are include by default by Nuitka for PySide6
+ # application deployment
+ self.qt_plugins_to_ignore = ["imageformats", # being Nuitka `sensible`` plugins
+ "iconengines",
+ "mediaservice",
+ "printsupport",
+ "platforms",
+ "platformthemes",
+ "styles",
+ "wayland-shell-integration",
+ "wayland-decoration-client",
+ "wayland-graphics-integration-client",
+ "egldeviceintegrations",
+ "xcbglintegrations",
+ "tls", # end Nuitka `sensible` plugins
+ "generic" # plugins that error with Nuitka
+ ]
+
+ # .webp are considered to be dlls by Nuitka instead of data files causing
+ # the packaging to fail
+ # https://github.com/Nuitka/Nuitka/issues/2854
+ # TODO: Remove .webp when the issue is fixed
+ self.files_to_ignore = [".cpp.o", ".qsb", ".webp"]
+
+ @staticmethod
+ def icon_option():
+ if sys.platform == "linux":
+ return "--linux-icon"
+ elif sys.platform == "win32":
+ return "--windows-icon-from-ico"
+ else:
+ return "--macos-app-icon"
def create_executable(self, source_file: Path, extra_args: str, qml_files: List[Path],
- excluded_qml_plugins, dry_run: bool):
+ qt_plugins: List[str], excluded_qml_plugins: List[str], icon: str,
+ dry_run: bool, permissions: List[str],
+ mode: DesktopConfig.NuitkaMode):
+ qt_plugins = [plugin for plugin in qt_plugins if plugin not in self.qt_plugins_to_ignore]
extra_args = extra_args.split()
+
+ # macOS uses the --standalone option by default to create an app bundle
+ if sys.platform == "darwin":
+ # create an app bundle
+ extra_args.extend(["--standalone", "--macos-create-app-bundle"])
+ permission_pattern = "--macos-app-protected-resource={permission}"
+ for permission in permissions:
+ extra_args.append(permission_pattern.format(permission=permission))
+ else:
+ extra_args.append(f"--{mode.value}")
+
qml_args = []
if qml_files:
- qml_args.append("--include-qt-plugins=all")
+ # This will generate options for each file using:
+ # --include-data-files=ABSOLUTE_PATH_TO_FILE=RELATIVE_PATH_TO ROOT
+ # for each file. This will preserve the directory structure of QML resources.
qml_args.extend(
- [f"--include-data-files={qml_file}=./{qml_file.name}" for qml_file in qml_files]
+ [f"--include-data-files={qml_file.resolve()}="
+ f"./{qml_file.resolve().relative_to(source_file.parent)}"
+ for qml_file in qml_files]
)
+ # add qml plugin. The `qml`` plugin name is not present in the module json files shipped
+ # with Qt and hence not in `qt_plugins``. However, Nuitka uses the 'qml' plugin name to
+ # include the necessary qml plugins. There we have to add it explicitly for a qml
+ # application
+ qt_plugins.append("qml")
if excluded_qml_plugins:
prefix = "lib" if sys.platform != "win32" else ""
@@ -33,22 +93,32 @@ class Nuitka:
dll_name = plugin.replace("Qt", f"Qt{MAJOR_VERSION}")
qml_args.append(f"--noinclude-dlls={prefix}{dll_name}*")
+ # Exclude .qen json files from QtQuickEffectMaker
+ # These files are not relevant for PySide6 applications
+ qml_args.append("--noinclude-dlls=*/qml/QtQuickEffectMaker/*")
+
+ # Exclude files that cannot be processed by Nuitka
+ for file in self.files_to_ignore:
+ extra_args.append(f"--noinclude-dlls=*{file}")
+
output_dir = source_file.parent / "deployment"
if not dry_run:
output_dir.mkdir(parents=True, exist_ok=True)
- print("[DEPLOY] Running Nuitka")
+ logging.info("[DEPLOY] Running Nuitka")
command = self.nuitka + [
os.fspath(source_file),
"--follow-imports",
- "--onefile",
"--enable-plugin=pyside6",
f"--output-dir={output_dir}",
]
- command.extend(extra_args + qml_args)
- if sys.platform == "linux":
- linux_icon = str(Path(__file__).parent / "pyside_icon.jpg")
- command.append(f"--linux-onefile-icon={linux_icon}")
+ command.extend(extra_args + qml_args)
+ command.append(f"{self.__class__.icon_option()}={icon}")
+ if qt_plugins:
+ # sort qt_plugins so that the result is definitive when testing
+ qt_plugins.sort()
+ qt_plugins_str = ",".join(qt_plugins)
+ command.append(f"--include-qt-plugins={qt_plugins_str}")
command_str, _ = run_command(command=command, dry_run=dry_run)
return command_str