diff options
Diffstat (limited to 'sources/pyside6/doc/deployment')
-rw-r--r-- | sources/pyside6/doc/deployment/deployment-briefcase.rst | 211 | ||||
-rw-r--r-- | sources/pyside6/doc/deployment/deployment-cxfreeze.rst | 131 | ||||
-rw-r--r-- | sources/pyside6/doc/deployment/deployment-fbs.rst | 97 | ||||
-rw-r--r-- | sources/pyside6/doc/deployment/deployment-nuitka.rst | 132 | ||||
-rw-r--r-- | sources/pyside6/doc/deployment/deployment-py2exe.rst | 16 | ||||
-rw-r--r-- | sources/pyside6/doc/deployment/deployment-pyinstaller.rst | 164 | ||||
-rw-r--r-- | sources/pyside6/doc/deployment/deployment-pyside6-android-deploy.rst | 211 | ||||
-rw-r--r-- | sources/pyside6/doc/deployment/deployment-pyside6-deploy.rst | 217 | ||||
-rw-r--r-- | sources/pyside6/doc/deployment/index.rst | 155 |
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 |