aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/doc/deployment
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/doc/deployment')
-rw-r--r--sources/pyside6/doc/deployment/deployment-briefcase.rst211
-rw-r--r--sources/pyside6/doc/deployment/deployment-cxfreeze.rst131
-rw-r--r--sources/pyside6/doc/deployment/deployment-fbs.rst97
-rw-r--r--sources/pyside6/doc/deployment/deployment-nuitka.rst132
-rw-r--r--sources/pyside6/doc/deployment/deployment-py2exe.rst16
-rw-r--r--sources/pyside6/doc/deployment/deployment-pyinstaller.rst164
-rw-r--r--sources/pyside6/doc/deployment/deployment-pyside6-android-deploy.rst211
-rw-r--r--sources/pyside6/doc/deployment/deployment-pyside6-deploy.rst217
-rw-r--r--sources/pyside6/doc/deployment/index.rst155
9 files changed, 1334 insertions, 0 deletions
diff --git a/sources/pyside6/doc/deployment/deployment-briefcase.rst b/sources/pyside6/doc/deployment/deployment-briefcase.rst
new file mode 100644
index 000000000..e85e618a7
--- /dev/null
+++ b/sources/pyside6/doc/deployment/deployment-briefcase.rst
@@ -0,0 +1,211 @@
+|project| & Briefcase
+#######################
+
+`Briefcase <https://briefcase.readthedocs.io>`_ is a packaging tool that lets
+you create a standalone package for a Python application. It supports the
+following installer formats:
+
+* ``.app`` application bundle for macOS
+* MSI installer for Windows
+* AppImage for Linux
+
+For more details, see the `official documentation
+<https://briefcase.readthedocs.io/en/latest/index.html>`_.
+
+Status of Qt 6 Support
+======================
+
+As of March 2021, Qt 6 is not supported yet.
+
+Preparation
+===========
+
+Install ``Briefcase`` using the following **pip** command::
+
+ pip install briefcase
+
+You also need : docker on linux, `WixToolset`_ on windows,
+
+If you're using a virtual environment, remember to activate it before installing ``Briefcase``.
+
+After installation, the ``briefcase`` binary is located in your virtual environment's ``bin/``
+directory, or where your Python executable is located.
+
+You can either create a brand new project using the briefcase assistant or setup your own.
+
+.. _`WixToolset`: https://wixtoolset.org/
+
+Use Briefcase Assistant
+=======================
+
+Run the following command and answer the questions to get started::
+
+ briefcase new
+
+Ensure that |pymodname| is chosen as the **GUI toolkit choice**.
+Your |pymodname| application is now configured. You can jump to `Build the package`_.
+
+
+Set up your project
+===================
+
+Create a pyproject.toml
+-----------------------
+
+At the root level of your project, create a ``pyproject.toml`` file::
+
+ [tool.briefcase]
+ project_name = "MyPySideApp"
+ bundle = "com.example"
+ version = "0.0.1"
+ url = "https://somwhere/on/the/net"
+ license = "GNU General Public License v3 (GPLv3)"
+ author = 'MyName Firstname'
+ author_email = "cool@mailexample.com"
+
+ [tool.briefcase.app.mypysideapp]
+ formal_name = "A Cool App"
+ description = "The coolest app ever"
+ icon = "src/mypysideapp/resources/appicon" # Briecase will choose the right extension depending the os (png,ico,...)
+ sources = ['src/mypysideapp']
+ requires = ['pyside6==6.0.0',
+ 'pony>=0.7.11,<0.8',
+ 'dickens==1.0.1',
+ 'Pillow==7.1.2',
+ 'mako==1.1.2',
+ 'beautifulsoup4']
+
+
+ [tool.briefcase.app.mypysideapp.macOS]
+ requires = []
+
+ [tool.briefcase.app.mypysideapp.linux]
+ requires = []
+ system_requires = []
+
+ [tool.briefcase.app.mypysideapp.windows]
+ requires = []
+
+
+Write some code
+---------------
+
+Let's say your project tree is like this::
+
+ pyproject.toml
+ setup.cfg
+ pytest.ini
+ src/
+
+ mypysideapp/
+ resources/
+ appicon.png
+ appicon.ico
+ __init__.py
+ __main__.py
+ app.py
+
+
+Content of ``__main__.py``::
+
+ import sys
+ from PySide6.QtWidgets import QApplication
+ from mypysideapp.app import MyWidget
+
+ if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ widget = MyWidget()
+ widget.resize(800, 600)
+ widget.show()
+
+ sys.exit(app.exec())
+
+
+Content of ``app.py``::
+
+ import random
+ from PySide6.QtWidgets import (QLabel, QPushButton,
+ QVBoxLayout, QWidget)
+ from PySide6.QtCore import Slot, Qt
+
+ class MyWidget(QWidget):
+ def __init__(self):
+ QWidget.__init__(self)
+
+ self.hello = ["Hallo Welt", "你好,世界", "Hei maailma",
+ "Hola Mundo", "Привет мир"]
+
+ self.button = QPushButton("Click me!")
+ self.text = QLabel("Hello World")
+ self.text.setAlignment(Qt.AlignCenter)
+
+ self.layout = QVBoxLayout()
+ self.layout.addWidget(self.text)
+ self.layout.addWidget(self.button)
+ self.setLayout(self.layout)
+
+ # Connecting the signal
+ self.button.clicked.connect(self.magic)
+
+ @Slot()
+ def magic(self):
+ self.text.setText(random.choice(self.hello))
+
+
+Build the package
+=================
+
+Initialize the package
+----------------------
+
+Just run::
+
+ briefcase create
+
+Run the following command to initialize the building the packages for Windows, Linux, and macOS.
+It creates a subdirectory each for the different platforms.
+This step takes longer as it adds the packages listed in ``requires`` sections in the
+``pyproject.toml`` file.
+
+Build the application
+---------------------
+::
+
+ briefcase build
+
+You'll get::
+
+ macOS/A Cool App/A Cool App.app
+ or
+ linux/A Cool App-x86_64-0.0.1.AppImage
+ or
+ windows\A Cool App
+
+
+Run the application
+-------------------
+::
+
+ briefcase run
+
+.. note:: You can run your project in ``dev`` mode (your source code not packaged) with
+ ``briefcase dev``
+
+
+Build the installer (only Windows and macOS)
+--------------------------------------------
+
+macOS::
+
+ briefcase package --no-sign
+
+It's possible to sign, see the
+`documentation <https://briefcase.readthedocs.io/en/latest/how-to/code-signing/index.html>`_.
+You get ``macOS/A Cool App-0.0.1.dmg``
+
+Windows::
+
+ briefcase package
+
+You get ``windows\A_Cool_App-0.0.1.msi``
diff --git a/sources/pyside6/doc/deployment/deployment-cxfreeze.rst b/sources/pyside6/doc/deployment/deployment-cxfreeze.rst
new file mode 100644
index 000000000..46cbb142e
--- /dev/null
+++ b/sources/pyside6/doc/deployment/deployment-cxfreeze.rst
@@ -0,0 +1,131 @@
+=====================
+|project| & cx_Freeze
+=====================
+
+`cx_Freeze <https://marcelotduarte.github.io/cx_Freeze//>`_ lets you
+freeze your Python application into executables. The supported
+platforms are Linux, macOS, Windows, FreeBSD, among others.
+
+You can read the `official documentation <https://cx-freeze.readthedocs.io/en/latest/index.html>`_
+to clarify any further question, and remember to contribute to
+the project by `filing issues
+<https://github.com/marcelotduarte/cx_Freeze/issues>`_
+if you find any, or contributing to `their development <https://github.com/marcelotduarte/cx_Freeze>`_.
+
+Preparation
+===========
+
+Installing ``cx_Freeze`` can be done using **pip**::
+
+ pip install cx_freeze
+
+If you are using a virtual environment, remember to activate it before
+installing ``cx_Freeze`` into it.
+
+After the installation, you will have the ``cxfreeze`` binary to deploy
+your application.
+
+Freezing an application
+=======================
+
+There are three options to work with ``cx_Freeze``:
+
+1. Using the ``cxfreeze`` script.
+2. Creating ``setup.py`` script to build the project.
+3. Using the module classes directly (for advanced purposes).
+
+The following sections cover the first two use cases.
+
+Creating an example
+-------------------
+
+Now, consider the following simple script, named ``hello.py``::
+
+ import sys
+ import random
+ from PySide6.QtWidgets import (QApplication, QLabel, QPushButton,
+ QVBoxLayout, QWidget)
+ from PySide6.QtCore import Slot, Qt
+
+ class MyWidget(QWidget):
+ def __init__(self):
+ QWidget.__init__(self)
+
+ self.hello = ["Hallo Welt", "你好,世界", "Hei maailma",
+ "Hola Mundo", "Привет мир"]
+
+ self.button = QPushButton("Click me!")
+ self.text = QLabel("Hello World")
+ self.text.setAlignment(Qt.AlignCenter)
+
+ self.layout = QVBoxLayout()
+ self.layout.addWidget(self.text)
+ self.layout.addWidget(self.button)
+ self.setLayout(self.layout)
+
+ # Connecting the signal
+ self.button.clicked.connect(self.magic)
+
+ @Slot()
+ def magic(self):
+ self.text.setText(random.choice(self.hello))
+
+ if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ widget = MyWidget()
+ widget.resize(800, 600)
+ widget.show()
+
+ sys.exit(app.exec())
+
+
+Using ``cxfreeze`` executable
+-----------------------------
+
+Now that we have an application, try freezing it with the following
+command::
+
+ cxfreeze hello.py
+
+This command creates a ``dist/`` directory containing the executable.
+and a ``lib/`` directory containing all the shared libraries.
+
+To launch the application, go to the ``dist/`` directory and execute
+the file::
+
+ cd dist/
+ ./main
+
+
+Using a ``setuptools`` script
+-----------------------------
+
+For this process, you need an additional script called ``setup.py``::
+
+ import sys
+ from cx_Freeze import setup, Executable
+
+ setup(name = "MyApp",
+ version = "0.1",
+ description = "My GUI App",
+ executables = [Executable("hello.py")])
+
+Now, build the project using it::
+
+ python setup.py build
+
+This step creates a ``build/`` directory with the following structure::
+
+ build
+ └── exe.linux-x86_64-3.7
+ └── lib
+ └── main
+
+The first directory inside ``build/`` depends on the platform
+you are using, in this case a ``x86_64`` Linux using Python 3.7.
+The structure is the same as previously described, and you can simply
+enter the directory and execute the file::
+
+ cd build/exe.linux-x86_64-3.7
+ ./main
diff --git a/sources/pyside6/doc/deployment/deployment-fbs.rst b/sources/pyside6/doc/deployment/deployment-fbs.rst
new file mode 100644
index 000000000..459a225bf
--- /dev/null
+++ b/sources/pyside6/doc/deployment/deployment-fbs.rst
@@ -0,0 +1,97 @@
+|project| & fbs
+####################
+
+`fbs`_ provides a powerful environment for packaging, creating installers, and signing your
+application. It also lets you manage updates to your application. Since `fbs`_ is based on
+PyInstaller, it supports Linux, macOS, and Windows.
+
+For more details, see the `fbs tutorial`_ and the `fbs manual`_.
+
+.. _fbs: https://build-system.fman.io/
+.. _fbs tutorial: https://github.com/mherrmann/fbs-tutorial
+.. _fbs manual: https://build-system.fman.io/manual/
+
+Preparation
+===========
+
+Installing `fbs`_ (>= 0.7.6) is done via **pip**::
+
+ pip install fbs
+
+If you're using a virtual environment, remember to activate it before installing `fbs`_.
+
+After the installation, you can use the `fbs`_ executable.
+
+Starting a new project
+======================
+
+`fbs`_ provides useful features for you to create a base project structure with the following
+command::
+
+ fbs startproject
+
+This command prompts you to answer a few questions to configure the details of your project, like:
+
+* Application name
+* Author name
+* Qt bindings (PySide6)
+* Bundle indentified (for macOS)
+
+Afterwards, you have a ``src/`` directory that contains the following structure::
+
+ └── src
+ ├── build
+ │ └── settings
+ └── main
+ ├── icons
+ │ ├── base
+ │ ├── linux
+ │ └── mac
+ └── python
+
+Inside the ``settings`` directory, there are a few JSON files that can be edited to include more
+information about your project.
+
+The ``main`` file is in the ``python`` directory, and its default content is::
+
+ from fbs_runtime.application_context import ApplicationContext
+ from PySide6.QtWidgets import QMainWindow
+
+ import sys
+
+ if __name__ == '__main__':
+ appctxt = ApplicationContext() # 1. Instantiate ApplicationContext
+ window = QMainWindow()
+ window.resize(250, 150)
+ window.show()
+ exit_code = appctxt.app.exec() # 2. Invoke appctxt.app.exec()
+ sys.exit(exit_code)
+
+This example shows an empty ``QMainWindow``. You can run it using the following command::
+
+ fbs run
+
+Freezing the application
+========================
+
+Once you've verified that the application is working properly, you can continue with the freezing
+process using the following command::
+
+ fbs freeze
+
+After the process completes, you see a message stating the location of your executable. For
+example::
+
+ Done. You can now run `target/MyApp/MyApp`. If that doesn't work, see
+ https://build-system.fman.io/troubleshooting
+
+
+Now, you can try to run the application. The result is the same window as the one you saw with the
+``fbs run`` command::
+
+ cd target/MyApp/
+ ./MyApp
+
+.. note:: This is the case for Linux. For other platforms like macOS, you need to enter the
+ directory: ``target/MyApp.app/Contents/macOS``. For Windows, you need to find the ``MyApp.exe``
+ executable.
diff --git a/sources/pyside6/doc/deployment/deployment-nuitka.rst b/sources/pyside6/doc/deployment/deployment-nuitka.rst
new file mode 100644
index 000000000..8b0afa56c
--- /dev/null
+++ b/sources/pyside6/doc/deployment/deployment-nuitka.rst
@@ -0,0 +1,132 @@
+|project| & Nuitka
+##################
+
+`Nuitka <https://nuitka.net/>`_ lets you compile your python application into a
+stand-alone executable. Besides being a Python compiler which provides a fair
+acceleration, it has the side-effect of acting as an installer as well.
+Nuitka supports Linux, macOS and Windows.
+
+For more details, see the `official documentation <https://nuitka.net/pages/overview.html>`_.
+
+Preparation
+===========
+
+Install ``Nuitka`` via **pip** with the following command::
+
+ pip install nuitka
+
+After installation, the ``nuitka3`` binary is located in your virtual environment's ``bin/``
+directory, or where your Python executable is located.
+Alternatively, you can also run::
+
+ python3 -m nuitka
+
+to achieve the same effect.
+
+Freeze an application
+=====================
+
+``Nuitka`` has many options that you can use. To list them all, run ``nuitka3 -h``.
+
+To simply compile a project, you can run::
+
+ nuitka3 <programname>
+
+There are two main features:
+
+* the option to place it in a directory containing the libraries
+ (``--standalone``)
+* the option to package the whole project (including shared libraries) into one executable file
+ (``--onefile``)
+
+If you use these options, you need to specify ``--plugin-enable=pyside6``.
+
+Run an example
+--------------
+
+Now, consider the following script, named ``hello.py``::
+
+ import sys
+ import random
+ from PySide6.QtWidgets import (QApplication, QLabel, QPushButton,
+ QVBoxLayout, QWidget)
+ from PySide6.QtCore import Slot, Qt
+
+ class MyWidget(QWidget):
+ def __init__(self):
+ QWidget.__init__(self)
+
+ self.hello = ["Hallo Welt", "你好,世界", "Hei maailma",
+ "Hola Mundo", "Привет мир"]
+
+ self.button = QPushButton("Click me!")
+ self.text = QLabel("Hello World")
+ self.text.setAlignment(Qt.AlignCenter)
+
+ self.layout = QVBoxLayout()
+ self.layout.addWidget(self.text)
+ self.layout.addWidget(self.button)
+ self.setLayout(self.layout)
+
+ # Connecting the signal
+ self.button.clicked.connect(self.magic)
+
+ @Slot()
+ def magic(self):
+ self.text.setText(random.choice(self.hello))
+
+ if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ widget = MyWidget()
+ widget.resize(800, 600)
+ widget.show()
+
+ sys.exit(app.exec())
+
+You don't have to copy this script. You find it as ``examples/installer_test/hello.py``.
+
+The command line to proceed looks like this::
+
+ nuitka3 examples/installer_test/hello.py
+
+This process creates an executable ``hello.bin`` and a directory hello.build that you
+don't need. You can execute the binary directly.
+
+In order to create a bundle which can be copied onto a machine without any pre-existing
+installation, run::
+
+ nuitka3 --standalone --plugin-enable=pyside6 examples/installer_test/hello.py
+
+This creates an application ``hello.dist/hello`` that contains everything needed to run.
+
+To run the application, go to ``hello.dist/`` and run the program::
+
+ cd hello.dist
+ ./hello
+
+Use the ``--onefile`` option if you prefer to have everything bundled into one executable, without
+the shared libraries next to it. First you need to install::
+
+ pip install zstandard
+
+for data compression. Then you can run::
+
+ nuitka3 --onefile --plugin-enable=pyside6 examples/installer_test/hello.py
+
+This process takes a bit longer, but in the end you have one executable ``hello.bin``::
+
+ ./hello.bin
+
+
+Some Caveats
+============
+
+
+Nuitka issue on macOS
+---------------------
+
+Nuitka currently has a problem with the macOS bundle files on current macOS versions.
+That has the effect that ``--standalone`` and ``--onefile`` create a crashing application.
+Older versions which don't have the recent macOS API changes from 2020 will work.
+We are currently trying to fix that problem.
diff --git a/sources/pyside6/doc/deployment/deployment-py2exe.rst b/sources/pyside6/doc/deployment/deployment-py2exe.rst
new file mode 100644
index 000000000..6ca09a826
--- /dev/null
+++ b/sources/pyside6/doc/deployment/deployment-py2exe.rst
@@ -0,0 +1,16 @@
+|project| & py2exe
+##################
+
+Deploying an application using py2exe requires writing a small ``setup.py`` file.
+It is explained in the `Tutorial <http://www.py2exe.org/index.cgi/Tutorial>`_.
+
+py2exe is not generally aware of Qt. It merely copies the dependent libraries
+of the application to the ``dist`` directory, so, the plugins, QML imports
+and translations of Qt are missing.
+
+The latter need to be copied manually after running py2exe.
+This can be achieved by running the ``windeployqt`` tool
+from the Qt SDK on the Qt libraries present in the ``dist`` directory,
+for example::
+
+ windeployqt dist\\Qt6Widgets.dll
diff --git a/sources/pyside6/doc/deployment/deployment-pyinstaller.rst b/sources/pyside6/doc/deployment/deployment-pyinstaller.rst
new file mode 100644
index 000000000..feb257162
--- /dev/null
+++ b/sources/pyside6/doc/deployment/deployment-pyinstaller.rst
@@ -0,0 +1,164 @@
+|project| & PyInstaller
+#######################
+
+`PyInstaller <https://www.pyinstaller.org/>`_ lets you freeze your python application into a
+stand-alone executable. This installer supports Linux, macOS, Windows, and more; and is also
+compatible with 3rd-party Python modules, such as |pymodname|.
+
+For more details, see the `official documentation <https://www.pyinstaller.org>`_.
+
+Status of Qt 6 Support
+======================
+
+As of March 2021, Qt 6 is not supported yet. PyInstaller is unable to properly
+deploy Qt; the Qt plugins are not copied. With that, using ``--onefile`` is not
+possible.
+
+It is possible to use PyInstaller for the non ``--onefile`` case though by
+manually copying the Qt plugins, QML imports and translations into
+the dist directory after running PyInstaller.
+
+On Windows, this can be achieved by running the ``windeployqt`` tool
+from the Qt SDK on the Qt libraries present in the ``dist`` directory, for
+example:
+
+ windeployqt dist\\app\\Qt6Widgets.dll
+
+
+Preparation
+===========
+
+Install the ``PyInstaller`` via **pip** with the following command::
+
+ pip install pyinstaller
+
+If you're using a virtual environment, remember to activate it before installing ``PyInstaller``.
+
+After installation, the ``pyinstaller`` binary is located in your virtual environment's ``bin/``
+directory, or where your Python executable is located. If that directory isn't in your ``PATH``,
+include the whole path when you run ``pyinstaller``.
+
+.. warning:: If you already have a PySide6 or Shiboken6 version installed in your
+ system path, PyInstaller uses them instead of your virtual environment version.
+
+Freeze an application
+=======================
+
+``PyInstaller`` has many options that you can use. To list them all, run ``pyinstaller -h``.
+
+There are two main features:
+
+ * the option to package the whole project (including shared libraries) into one executable file
+ (``--onefile``)
+ * the option to place it in a directory containing the libraries
+
+Additionally, on Windows when the command is running, you can open a console with the ``-c`` option
+(or ``--console`` or ``--nowindowed`` equivalent).
+
+Otherwise, you can specify to not open such a console window on macOS and Windows with the ``-w``
+option (or ``--windowed`` or ``--noconsole`` equivalent).
+
+Create an example
+-----------------
+
+Now, consider the following script, named ``hello.py``::
+
+ import sys
+ import random
+ from PySide6.QtWidgets import (QApplication, QLabel, QPushButton,
+ QVBoxLayout, QWidget)
+ from PySide6.QtCore import Slot, Qt
+
+ class MyWidget(QWidget):
+ def __init__(self):
+ QWidget.__init__(self)
+
+ self.hello = ["Hallo Welt", "你好,世界", "Hei maailma",
+ "Hola Mundo", "Привет мир"]
+
+ self.button = QPushButton("Click me!")
+ self.text = QLabel("Hello World")
+ self.text.setAlignment(Qt.AlignCenter)
+
+ self.layout = QVBoxLayout()
+ self.layout.addWidget(self.text)
+ self.layout.addWidget(self.button)
+ self.setLayout(self.layout)
+
+ # Connecting the signal
+ self.button.clicked.connect(self.magic)
+
+ @Slot()
+ def magic(self):
+ self.text.setText(random.choice(self.hello))
+
+ if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ widget = MyWidget()
+ widget.resize(800, 600)
+ widget.show()
+
+ sys.exit(app.exec())
+
+
+Since it has a UI, you use the ``--windowed`` option.
+
+The command line to proceed looks like this::
+
+ pyinstaller --name="MyApplication" --windowed hello.py
+
+This process creates two directories: ``dist/`` and ``build/``. The application executable and the
+required shared libraries are placed in ``dist/MyApplication``.
+
+To run the application, go to ``dist/MyApplication`` and run the program::
+
+ cd dist/MyApplication/
+ ./MyApplication
+
+.. note:: The directory inside ``dist/`` and the executable have the same name.
+
+Use the ``--onefile`` option if you prefer to have everything bundled into one executable, without
+the shared libraries next to it::
+
+ pyinstaller --name="MyApplication" --windowed --onefile hello.py
+
+This process takes a bit longer, but in the end you have one executable in the
+``dist/`` directory::
+
+ cd dist/
+ ./MyApplication
+
+
+Some Caveats
+============
+
+
+PyInstaller Issue
+-----------------
+
+As mentioned before, if available, ``PyInstaller`` picks a system installation of |pymodname| or
+Shiboken6 instead of your ``virtualenv`` version without notice. This is negligible if those
+two versions are the same.
+
+If you're working with different versions, this can result in frustrating debugging sessions
+when you think you are testing the latest version, but ``PyInstaller`` is working with an older
+version.
+
+
+Safety Instructions
+-------------------
+
+- When using ``PyInstaller`` with ``virtualenv``, make sure that there is no system
+ installation of PySide6 or shiboken6.
+
+- Before compiling, use ``pip -uninstall pyside6 pyside6_essentials pyside6_addons shiboken6 -y``
+ multiple times, until none of the programs are found anymore.
+
+- Pip is usually a good tool. But to be 100 % sure, you should directly remove
+ the PySide6 and shiboken6 folders from ``site-packages``.
+
+- Be sure to use the right version of pip. The safest way to really run the right
+ pip, is to use the Python that you mean: Instead of the pip command, better use::
+
+ <path/to/your/>python -m pip
diff --git a/sources/pyside6/doc/deployment/deployment-pyside6-android-deploy.rst b/sources/pyside6/doc/deployment/deployment-pyside6-android-deploy.rst
new file mode 100644
index 000000000..53944f6ea
--- /dev/null
+++ b/sources/pyside6/doc/deployment/deployment-pyside6-android-deploy.rst
@@ -0,0 +1,211 @@
+.. _pyside6-android-deploy:
+
+pyside6-android-deploy: the Android deployment tool for Qt for Python
+#####################################################################
+
+``pyside6-android-deploy`` is an easy-to-use tool for deploying PySide6 applications to different
+Android architectures, namely *arm64-v8a, x86_64, x86 and armeabi-v7a*. This tool works similarly to
+the ``pyside6-deploy`` tool and uses the same configuration file ``pysidedeploy.spec`` as
+``pyside6-deploy`` to configure the deployment process. Using the deployment configuration
+options either from the command line or from ``pysidedeploy.spec``, ``pyside6-android-deploy``
+configures the deployment to be initiated and invokes `buildozer`_, a tool used for packaging Python
+applications to Android.
+
+The final output is a `.apk` or a `.aab` file created within the project's source directory. The
+`mode` option specified under the :ref:`buildozer <buildozer_key>` key in ``pysidedeploy.spec``
+determines whether a `.apk` or a `.aab` is created.
+
+.. warning:: Currently, users are required to cross-compile Qt for Python to generate the wheels
+ required for a specific Android target architecture. This requirement will disappear when
+ there are official Qt for Python Android wheels (*in progress*). Because of this
+ requirement ``pyside6-android-deploy`` will be considered in **Technical Preview**.
+ Instructions on cross-compiling Qt for Python for Android can be found
+ :ref:`here <cross_compile_android>`.
+
+.. note:: ``pyside6-android-deploy`` only works on a Linux host at the moment. This constraint
+ is also because Qt for Python cross-compilation for Android currently only works on Linux
+ systems.
+
+How to use it?
+==============
+
+Like ``pyside6-deploy``, there are :ref:`two different ways <how_pysidedeploy>` with which
+you can deploy your PySide6 application using ``pyside6-android-deploy``. The only difference is
+that for ``pyside6-android-deploy`` to work, the main Python entry point file should be named
+``main.py``.
+
+.. _pysideandroiddeploy:
+
+pysidedeploy.spec
+=================
+
+Like ``pyside6-deploy``, you can use the ``pysidedeploy.spec`` file to control the various
+parameters of the deployment process. The file has multiple sections, with each section containing
+multiple keys (parameters being controlled) assigned to a value. The advantages of such a file are
+mentioned :ref:`here <pysidedeployspec_advantages>`. The benefit of using the same
+``pysidedeploy.spec`` for both ``pyside6-deploy`` and ``pyside6-android-deploy`` is that you can
+have one single file to control deployment to all platforms.
+
+The relevant parameters for ``pyside6-android-deploy`` are:
+
+**app**
+ * ``title``: The name of the application.
+ * ``project_dir``: Project directory. The general assumption made is that the project directory
+ is the parent directory of the main Python entry point file.
+ * ``input_file``: Path to the main Python entry point file. For ``pyside6-android-deploy`` this
+ file should be named `main.py`.
+ * ``project_file``: If it exists, this points to the path to the `Qt Creator Python Project File
+ .pyproject <https://doc.qt.io/qtforpython-6/faq/typesoffiles.html
+ #qt-creator-python-project-file-pyproject>`_ file. Such a file in the project directory ensures
+ that deployment does not consider unnecessary files when bundling the executable.
+ * ``exec_directory``: The directory where the final executable is generated.
+
+**python**
+ * ``python_path``: Path to the Python executable. It is recommended to run
+ ``pyside6-android-deploy`` from a virtual environment as certain Python packages will be
+ installed onto the Python environment. However, note to keep the created virtual environment
+ outside the project directory so that ``pyside6-android-deploy`` does not try to package it
+ as well.
+ * ``android_packages``: The Python packages installed into the Python environment for deployment
+ to work. By default, the Python packages `buildozer`_ and `cpython`_ are installed.
+
+.. _qt_key:
+
+**qt**
+ * ``modules``: Comma-separated list of all the Qt modules used by the application. Just like the
+ other configuration options in ``pysidedeploy.spec``, this option is also computed automatically
+ by ``pyside6-android-deploy``. However, if you want to explicitly include certain Qt modules,
+ the module names can be appended to this list without the `Qt` prefix.
+ e.g. Network instead of QtNetwork
+ * ``plugins``: This field is *not relevant* for ``pyside6-android-deploy`` and is only specific to
+ ``pyside6-deploy``. The plugins relevant for ``pyside6-android-deploy`` are specified through
+ the ``plugins`` option under the :ref:`android <android_key>` key.
+
+.. _android_key:
+
+**android**
+ * ``wheel_pyside``: Specifies the path to the PySide6 Android wheel for a specific target
+ architecture.
+ * ``wheel_pyside``: Specifies the path to the Shiboken6 Android wheel for a specific target
+ architecture.
+ * ``plugins``: Comma-separated list of all the Qt plugins used by the application. Just like the
+ other configuration options in ``pysidedeploy.spec``, this option is also computed automatically
+ by ``pyside6-android-deploy``. However, if you want to to explicitly include certain Qt plugins,
+ the plugin names can be appended to this list. To see all the plugins bundled with PySide6, see
+ the `plugins` folder in the ``site-packages`` on your Python where PySide6 is installed. The
+ plugin name corresponds to their folder name. This field can be confused with the ``plugins``
+ option under :ref:`qt <qt_key>` key. In the future, they will be merged into one single option.
+
+.. _buildozer_key:
+
+**buildozer**
+ * ``mode``: Specifies one of the two modes - `release` and `debug`, to run `buildozer`_. The
+ `release` mode creates an *aab* while the `debug` mode creates an apk. The default mode is
+ `debug`.
+ * ``recipe_dir``: Specifies the path to the directory containing `python-for-android`_ recipes.
+ This option is automatically computed by ``pyside6-android-deploy`` during deployment. Without
+ the :ref:`--keep-deployment-files <keep_deployment_files>` option of ``pyside6-android-deploy``,
+ the `recipe_dir` will point to a temporary directory that is deleted after the final Android
+ application package is created.
+ * ``jars_dir``: Specifies the path to the Qt Android `.jar` files that are relevant for
+ creating the Android application package. This option is automatically computed by
+ ``pyside6-android-deploy`` during deployment. Just like ``recipe_dir``, this field is also
+ *not relevant* unless used with the :ref:`--keep-deployment-files <keep_deployment_files>`
+ option of ``pyside6-android-deploy``.
+ * ``ndk_path``: Specifies the path to the Android NDK used for packaging the application.
+ * ``sdk_path``: Specifies the path to the Android SDK used for packaging the application.
+ * ``local_libs``: Specifies non-Qt plugins or other libraries compatible with the Android target
+ to be loaded by the Android runtime on startup.
+ * ``sdk_path``: Specifies the path to the Android SDK used for packaging the application.
+ * ``arch``: Specifies the target architecture's instruction set. This option take one of the four
+ values - *aarch64, armv7a, i686, x86_64*.
+
+Command Line Options
+====================
+
+Here are all the command line options of ``pyside6-android-deploy``:
+
+* **-c/--config-file**: This option is used to specify the path to ``pysidedeploy.spec`` explicitly.
+
+* **--init**: Used to only create the ``pysidedeploy.spec`` file.
+ Usage::
+
+ pyside6-android-deploy --init
+
+* **-v/--verbose**: Runs ``pyside6-android-deploy`` in verbose mode.
+
+* **--dry-run**: Displays the commands being run to produce the Android application package.
+
+.. _keep_deployment_files:
+
+* **--keep-deployment-files**: When this option is added, it retains the build folders created by
+ `buildozer`_ during the deployment process. This includes the folder storing the
+ `python-for-android`_ recipes, relevant `.jar` files and even the Android Gradle project for the
+ application.
+
+* **-f/--force**: When this option is used, it assumes ``yes`` to all prompts and runs
+ ``pyside6-android-deploy`` non-interactively. ``pyside6-android-deploy`` prompts the user to
+ create a Python virtual environment, if not already in one. With this option, the current Python
+ environment is used irrespective of whether the current Python environment is a virtual
+ environment or not.
+
+* **--name**: Application name.
+
+* **--wheel-pyside**: Path to the PySide6 Android wheel for a specific target architecture.
+
+* **--wheel-shiboken**: Path to the Shiboken6 Android wheel for a specific target architecture.
+
+* **--ndk-path**: Path to the Android NDK used for packaging the application.
+
+* **--sdk-path**: Path to the Android SDK used for packaging the application.
+
+* **--extra-ignore-dirs**: Comma-separated directory names inside the project directory. These
+ directories will be skipped when searching for Python files relevant to the project.
+
+* **--extra-modules**: Comma-separated list of Qt modules to be added to the application,
+ in case they are not found automatically. The module name can either be specified
+ by omitting the prefix of Qt or including it eg: both Network and QtNetwork works.
+
+.. _cross_compile_android:
+
+Cross-compile Qt for Python wheels for Android
+==============================================
+
+The cross-compilation of Qt for Python wheel for a specific Android target architecture needs to be
+done only once per Qt version, irrespective of the number of applications you are deploying.
+Currently, cross-compiling Qt for Python wheels only works with a Linux host. Follow these steps
+to cross-compile Qt for Python Android wheels.
+
+#. `Download <qt_download>`_ and install Qt version for which you would like to create Qt for Python
+ wheels.
+
+#. Cloning the Qt for Python repository::
+
+ git clone https://code.qt.io/pyside/pyside-setup
+
+#. Check out the version that you want to build, for example 6.7. The version checked out has
+ to correspond to the Qt version downloaded in Step 1::
+
+ cd pyside-setup && git checkout 6.7
+
+#. Installing the dependencies::
+
+ pip install -r requirements.txt
+ pip install -r tools/cross_compile_android/requirements.txt
+
+#. Run the cross-compilation Python script.::
+
+ python tools/cross_compile_android/main.py --plat-name=aarch64 --qt-install-path=/opt/Qt/6.7.0
+ --auto-accept-license --skip-update
+
+ *--qt-install-path* refers to the path where Qt 6.7.0 is installed. *--auto-accept-license* and
+ *--skip-update* are required for downloading and installing Android NDK and SDK if not already
+ specified through command line options or if they don't already exist in the
+ ``pyside6-android-deploy`` cache. Use --help to see all the other available options::
+
+ python tools/cross_compile_android/main.py --help
+
+.. _`buildozer`: https://buildozer.readthedocs.io/en/latest/
+.. _`python-for-android`: https://python-for-android.readthedocs.io/en/latest/
+.. _`qt_download`: https://www.qt.io/download
+.. _`cpython`: https://pypi.org/project/Cython/
diff --git a/sources/pyside6/doc/deployment/deployment-pyside6-deploy.rst b/sources/pyside6/doc/deployment/deployment-pyside6-deploy.rst
new file mode 100644
index 000000000..980fe2dd1
--- /dev/null
+++ b/sources/pyside6/doc/deployment/deployment-pyside6-deploy.rst
@@ -0,0 +1,217 @@
+.. _pyside6-deploy:
+
+pyside6-deploy: the deployment tool for Qt for Python
+#####################################################
+
+``pyside6-deploy`` is an easy to use tool for deploying PySide6 applications to different
+platforms. It is a wrapper around `Nuitka <https://nuitka.net/>`_, a Python compiler that
+compiles your Python code to C code, and links with libpython to produce the final executable.
+
+The final executable produced has a ``.exe`` suffix on Windows, ``.bin`` on Linux and ``.app`` on
+macOS.
+
+.. note:: Although using a virtual environment for Python is recommended for ``pyside6-deploy``, do
+ not add the virtual environment to the application directory you are trying to deploy.
+ ``pyside6-deploy`` will try to package this venv folder and will eventually fail.
+
+.. _how_pysidedeploy:
+
+How to use it?
+==============
+
+There are 2 different ways with which you can deploy your PySide6 application using
+``pyside6-deploy``:
+
+Approach 1: Using the main python entry point file
+--------------------------------------------------
+
+In this approach, you point ``pyside6-deploy`` to the file containing the main Python entry point
+file of the project i.e. the file containing ``if __name__ == "__main__":``.
+The command looks like this::
+
+ pyside6-deploy /path/to/main_file.py
+
+On running the command, ``pyside6-deploy`` installs all the dependencies required for deployment
+into the Python environment.
+
+If your main Python entry point file is named ``main.py``, then you don't have to point it to the
+filename. You can run ``pyside6-deploy`` without any options, and it will work.
+
+.. note:: If your project contains a ``pysidedeploy.spec`` file, which is generated on the first
+ run of ``pyside6-deploy`` on the project directory, then for any subsequent runs of
+ ``pyside6-deploy`` you can run ``pyside6-deploy`` without specifying the main Python entry
+ point file. It would take the path to the main file from the ``pysidedeploy.spec`` file.
+ To know more about what deployment parameters are controlled by ``pysidedeploy.spec`` file,
+ read `pysidedeploy`_.
+
+.. _approach_two:
+
+Approach 2: Using pysidedeploy.spec config file
+------------------------------------------------
+
+When you run ``pyside6-deploy`` for the first time, it creates a file called ``pysidedeploy.spec``
+in the project directory. This file controls various :ref:`parameters <pysidedeploy>` that influence
+the deployment process. Any subsequent runs of ``pyside6-deploy`` on the project directory, would
+not require additional parameters like the main Python entry point file. You can also point
+``pyside6-deploy`` to the path of the ``pysidedeploy.spec`` file (in case it is not in the same
+directory), to take the parameters from that file. This can be done with the following command::
+
+ pyside6-deploy -c /path/to/pysidedeploy.spec
+
+.. _pysidedeploy:
+
+pysidedeploy.spec
+=================
+
+As mentioned in the `Approach 2 <approach_two>`_ above, you can use this file to control the various
+parameters of the deployment process. The file has multiple sections, with each section containing
+multiple keys (parameters being controlled) assigned to a value. The advantages of such a file are
+two folds:
+
+.. _pysidedeployspec_advantages:
+
+#. Using the command line, you can control the deployment parameters without specifying them each
+ time. It is saved permanently in a file, and any subsequent runs much later in time
+ would enable the user to be aware of their last deployment parameters.
+
+#. Since these parameters are saved into a file, they can be checked into version control. This
+ gives the user more control of the deployment process. For example, when you decide to exclude
+ more QML plugins, or want to include more Nuitka options into your executable.
+
+This file is also used by the ``pyside6-android-deploy`` tool as a configuration file. The advantage
+here is that you can have one single file to control deployment to all platforms.
+
+The relevant parameters for ``pyside6-deploy`` are:
+
+**app**
+ * ``title``: The name of the application
+ * ``project_dir``: Project directory. The general assumption made is that the project directory
+ is the parent directory of the main Python entry point file
+ * ``input_file``: Path to the main Python entry point file
+ * ``project_file``: If it exists, this points to the path to the `Qt Creator Python Project File
+ .pyproject <https://doc.qt.io/qtforpython-6/faq/typesoffiles.html
+ #qt-creator-python-project-file-pyproject>`_ file. Such a file makes sure that the deployment
+ process never considers unnecessary files when bundling the executable.
+ * ``exec_directory``: The directory where the final executable is generated.
+ * ``icon``: The icon used for the application. For Windows, the icon image should be of ``.ico``
+ format, for macOS it should be of ``.icns`` format, and for linux all standard image formats
+ are accepted.
+
+**python**
+ * ``python_path``: Path to the Python executable. It is recommended to run the deployment
+ process inside a virtual environment as certain python packages will be installed onto the
+ Python environment.
+ * ``packages``: The Python packages installed into the Python environment for deployment to
+ work. By default, the Python packages `nuitka <https://pypi.org/project/Nuitka/>`__,
+ `ordered_set <https://pypi.org/project/ordered-set/>`_ and `zstandard
+ <https://pypi.org/project/zstandard/>`_ are installed. If the deployment platform is
+ Linux-based, then `patchelf <https://pypi.org/project/patchelf/>`_ is also installed
+
+**qt**
+ * ``qml_files``: Comma-separated paths to all the QML files bundled with the executable
+ * ``excluded_qml_plugins``: The problem with using Nuitka for QML deployment is that all the QML
+ plugins are also bundled with the executable. When the plugins are bundled, the binaries of
+ the plugin's Qt module are also packaged. For example, size heavy module like QtWebEngine
+ also gets added to your executable, even when you do not use it in your code. The
+ ``excluded_qml_plugins`` parameter helps you to explicitly specify which all QML plugins are
+ excluded. ``pyside6-deploy`` automatically checks the QML files against the various QML
+ plugins and excludes the following Qt modules if they don't exist::
+
+ QtQuick, QtQuick3D, QtCharts, QtWebEngine, QtTest, QtSensors
+
+ The reason why only the presence of the above 6 Qt modules is searched for is because they
+ have the most size heavy binaries among all the Qt modules. With this, you can drastically
+ reduce the size of your executables.
+ * ``modules``: Comma-separated list of all the Qt modules used by the application. Just like the
+ other configuration options in `pysidedeploy.spec`, this option is also computed automatically
+ by ``pyside6-deploy``. However, if the user wants to explicitly include certain Qt modules, the
+ module names can be appended to this list without the `Qt` prefix.
+ e.g. Network instead of QtNetwork
+ * ``plugins``: Comma-separated list of all the Qt plugins used by the application. Just like the
+ other configuration options in `pysidedeploy.spec`, this option is also computed automatically
+ by ``pyside6-deploy``. However, if the user wants to explicitly include certain Qt plugins,
+ the plugin names can be appended to this list. To see all the plugins bundled with PySide6,
+ see the `plugins` folder in the `site-packages` on your Python where PySide6 is installed. The
+ plugin name correspond to their folder name.
+
+**nuitka**
+ * ``macos.permissions``: Only relevant for macOS. This option lists the permissions used by the
+ macOS application, as found in the ``Info.plist`` file of the macOS application bundle, using
+ the so-called UsageDescription strings. The permissions are normally automatically found by
+ ``pyside6-deploy``. However the user can also explicitly specify them using the format
+ `<UsageDescriptionKey>:<Short Description>`. For example, the Camera permission is specified
+ as::
+
+ NSCameraUsageDescription:CameraAccess
+
+ * ``extra_args``: Any extra Nuitka arguments specified. It is specified as space-separated
+ command line arguments i.e. just like how you would specify it when you use Nuitka through
+ the command line. By default, it contains the following arguments::
+
+ --quiet --noinclude-qt-translations=True
+
+Command Line Options
+====================
+
+The most important command line options are the path to the main Python entry point file and the
+``pysidedeploy.spec`` file. If neither of these files exists or their command line options are
+given, then ``pyside6-deploy`` assumes that your current working directory does not contain a
+PySide6 project.
+
+Here are all the command line options of ``pyside6-deploy``:
+
+* **main entry point file**: This option does not have a name or a flag and is not restricted by it.
+ This enables ``pyside6-deploy`` to be used like::
+
+ pyside6-deploy /path/to/main_file.py
+
+* **-c/--config-file**: This option is used to specify the path to ``pysidedeploy.spec`` explicitly
+
+* **--init**: Used to only create the ``pysidedeploy.spec`` file
+ Usage::
+
+ pyside6-deploy /path/to/main --init
+
+
+* **-v/--verbose**: Runs ``pyside6-deploy`` in verbose mode.
+
+* **--dry-run**: Displays the final Nuitka command being run.
+
+* **--keep-deployment-files**: When this option is added, it retains the build folders created by
+ Nuitka during the deployment process.
+
+* **-f/--force**: When this option is used, it forces through all the input prompts.
+ ``pyside6-deploy`` prompts the user to create a Python virtual environment, if not already in one.
+ With this option, the current Python environment is used irrespective of whether the current
+ Python environment is a virtual environment or not.
+
+* **--name**: Application name.
+
+* **--extra-ignore-dirs**: Comma-separated directory names inside the project directory. These
+ directories will be skipped when searching for Python files relevant to the project.
+
+* **--extra-modules**: Comma-separated list of Qt modules to be added to the application,
+ in case they are not found automatically. The module name can either be specified
+ by omitting the prefix of Qt or including it eg: both Network and QtNetwork works.
+
+Considerations
+===============
+
+For deployment to work efficiently by bundling only the necessary plugins, the following utilities
+are required to be installed on the system:
+
+.. list-table::
+ :header-rows: 1
+
+ * - OS
+ - Dependencies
+ - Installation
+ * - Windows
+ - dumpbin
+ - Shipped with MSVC. Run `vcvarsall.bat` to add it to PATH
+ * - Linux
+ - readelf
+ - Available by default
+ * - macOS
+ - dyld_info
+ - Available by default from macOS 12 and upwards
diff --git a/sources/pyside6/doc/deployment/index.rst b/sources/pyside6/doc/deployment/index.rst
new file mode 100644
index 000000000..36e677566
--- /dev/null
+++ b/sources/pyside6/doc/deployment/index.rst
@@ -0,0 +1,155 @@
+.. _deployment-guides:
+
+Deployment
+==========
+
+Deploying or freezing an application is an important part of a Python project,
+this means to bundle all required resources so that the application finds everything it needs to
+be able to run on a client's machine.
+However, because most large projects aren't based on a single Python file, distributing these
+applications can be a challenge.
+
+Here are a few distribution options that you can use:
+ 1. Send a normal ZIP file with the application's content.
+ 2. Build a proper `Python package (wheel) <https://packaging.python.org/>`_.
+ 3. Freeze the application into a single binary file or directory.
+ 4. Provide native installer (msi, dmg)
+
+If you are considering Option 3, then starting with 6.4, we ship a new tool called `pyside6-deploy`
+that deploys your PySide6 application to all desktop platforms - Windows, Linux, and macOS. To know
+more about how to use the tool see :ref:`pyside6-deploy`. For Android deployment, see
+:ref:`pyside6-android-deploy`. Additionally, you can also use other popular deployment tools shown
+below:
+
+* `fbs`_
+* `PyInstaller`_
+* `cx_Freeze`_
+* `py2exe`_
+* `py2app`_
+* `briefcase`_
+
+.. _fbs: https://build-system.fman.io/
+.. _PyInstaller: https://www.pyinstaller.org/
+.. _cx_Freeze: https://marcelotduarte.github.io/cx_Freeze/
+.. _py2exe: http://www.py2exe.org/
+.. _py2app: https://py2app.readthedocs.io/en/latest/
+.. _briefcase: https://briefcase.readthedocs.io
+
+Although you can deploy PySide6 application using these tools, it is recommended to use
+`pyside6-deploy` as it is easier to use and also to get the most optimized executable. Since
+|project| is a cross-platform framework, we focus on solutions for the three major platforms that
+Qt supports: Windows, Linux, and macOS.
+
+The following table summarizes the platform support for those packaging tools:
+
+.. raw:: html
+
+ <table class="docutils align-default">
+ <thead>
+ <tr>
+ <th class="head">Name</th>
+ <th class="head">License</th>
+ <th class="head">Qt 6</th>
+ <th class="head">Qt 5</th>
+ <th class="head">Linux</th>
+ <th class="head">macOS</th>
+ <th class="head">Windows</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><p>fbs</p></td>
+ <td><p>GPL</p></td>
+ <td></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ </tr>
+ <tr>
+ <td><p>PyInstaller</p></td>
+ <td><p>GPL</p></td>
+ <td><p style="color: green;">partial</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ </tr>
+ <tr>
+ <td><p>cx_Freeze</p></td>
+ <td><p>MIT</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ </tr>
+ <tr>
+ <td><p>py2exe</p></td>
+ <td><p>MIT</p></td>
+ <td><p style="color: green;">partial</p></td>
+ <td><p style="color: green;">partial</p></td>
+ <td><p style="color: red;">no</p></td>
+ <td><p style="color: red;">no</p></td>
+ <td><p style="color: green;">yes</p></td>
+ </tr>
+ <tr>
+ <td><p>py2app</p></td>
+ <td><p>MIT</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: red;">no</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: red;">no</p></td>
+ </tr>
+ <tr>
+ <td><p>briefcase</p></td>
+ <td><p>BSD3</p></td>
+ <td><p style="color: green;">partial</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ </tr>
+ <tr>
+ <td><p>Nuitka</p></td>
+ <td><p>MIT</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ <td><p style="color: green;">yes</p></td>
+ </tr>
+ </tbody>
+ </table>
+
+Notice that only *fbs*, *cx_Freeze*, *briefcase*, and *PyInstaller* meet our cross-platform requirement.
+
+Since these are command-line tools, you'll need special hooks or scripts to handle resources
+such as images, icons, and meta-information, before adding them to your package. Additionally,
+these tools don't offer a mechanism to update your application packages.
+
+To create update packages, use the `PyUpdater <https://www.pyupdater.org/>`_, which is a tool
+built around PyInstaller.
+
+The `fbs`_ tool offers a nice UI for the user to install the
+application step-by-step.
+
+.. note::
+
+ Deployment is supported only from Qt for Python 5.12.2 and later.
+
+Here's a set of tutorials on how to use these tools:
+
+.. toctree::
+ :name: mastertoc
+ :maxdepth: 2
+
+ deployment-pyside6-deploy.rst
+ deployment-pyside6-android-deploy.rst
+ deployment-fbs.rst
+ deployment-pyinstaller.rst
+ deployment-cxfreeze.rst
+ deployment-briefcase.rst
+ deployment-py2exe.rst
+ deployment-nuitka.rst