.. _ref-creating-a-project:

.. program:: pyqtdeploy

Creating a :program:`pyqtdeploy` Project
========================================

The next stage of deploying a PyQt application is to create a
:program:`pyqtdeploy` project for it by running::

    pyqtdeploy pyqt-demo.pdy

This will create a new project, or open an exiting one if the file
``pyqt-demo.pdy`` already exists.  A project is simply a file with a ``.pdy``
extension.

A GUI will be displayed which consists of a ``File`` menu and a set of tabbed
pages that handle different aspects of the application's specification and
building.

The ``File`` menu contains the usual set of options to create a new project,
open an existing project, save a project and rename a project.


Defining the Application Source
-------------------------------

Python applications are usually structured in one of the following ways:

- a single standalone executable script that is installed in a ``bin``
  directory somewhere

- a package installed in ``site-packages`` with a separate executable script
  installed in a ``bin`` directory

- a package installed in ``site-packages`` with a separate executable script
  that is automatically generated by :mod:`setuptools`.  The script calls an
  *entry point* in the package.  An *entry point* is the name of a module in
  the package and the name of a callable within the module separated by a
  ``:``.

:program:`pyqt-demo` is a single standalone script (but with some additional
data which is the source code of the script).  :program:`pyqtdeploy` itself
uses the :mod:`setuptools` based structure.

The tab for defining the application source is shown below.

.. image:: /images/application_source_tab.png
    :align: center

**Name**
    is used to specify the name of the final application executable.  If it is
    not specified then it is derived from the name of the main script file.  If
    the application does not have a main script file then the name is derived
    from the name of the application package.

**Main script file**
    is used to specify the name of the executable Python script used to invoke
    the application.  It should not be specified if an entry point is
    specified.

    .. note::
        Whenever a file or directory is specified, :program:`pyqtdeploy` always
        saves its name relative to the directory containing the project file if
        possible.  In this particular example the ``pyqt-demo.py`` script is in
        the same directory as the ``pyqt-demo.pdy`` project file.  Also,
        whenever a file or directory name is entered, :program:`pyqtdeploy`
        allows the embedding of environment variables which will be expanded
        when necessary.  The :envvar:`PDY_PY_MAJOR`, :envvar:`PDY_PY_MINOR` and
        :envvar:`PDY_PY_MICRO` pseudo-environment variables can also be used
        which will be expanded to the relevant parts of the target Python
        version.

**Entry Point**
    is used to specify the entry point of a :mod:`setuptools`-based
    application.  It should not be specified if a main script file is
    specified.

**sys.path**
    is used to specify additional directories, ZIP files and eggs that will be
    added to :data:`sys.path`.  By default :program:`pyqtdeploy` generates an
    application that does not support the importing of packages or extension
    modules that are not embedded in the application.  However there are
    circumstances where this ability is desired:

    - you need to use an extension module that does not support being
      statically compiled

    - you allow users to write Python code that is imported by the application
      to configure or extend its functionality.

    The path is specified as a space separated list of directories.  Single or
    double quotes may be used to embed spaces in directory names.  Environment
    variables (specified using the standard UNIX notation) are expanded when
    the application is run.  Any relative directory names are assumed to be
    relative to the directory containing the application executable.  UNIX path
    separators should be used - the application will automatically do the
    appropriate conversions when running on Windows.

    :program:`pyqtdeploy` also supports the dynamic loading of extension
    modules that are installed adjacent to the application executable (i.e. in
    the same directory as the application executable).  This is useful for
    packages that are implemented as a combination of pure Python modules and
    extension modules where the extension modules do not support being
    statically compiled.  The pure Python modules would be added just like any
    other Python package (see :ref:`ref-other-packages`).  The extension module
    must be named according to its normal position in the package structure.

    For example, suppose we have a package called ``foo`` which contains pure
    Python modules ``__init__.py`` and ``bar.py`` and a dynamically loaded
    extension module ``baz.so``.  (The extension module would be called
    ``baz.pyd`` on Windows.)  When used with the deployed application the
    module must be installed as ``foo.baz.so`` (or ``foo.baz.pyd``) in the same
    directory as the application executable.

    On macOS an extension module will also be searched for in the ``PlugIns``
    and ``Frameworks`` sub-directories of the directory containing the
    application executable.

    Adjacent extension modules do not require :data:`sys.path` to be set.

    .. note::
        If you wish to allow the importing of external extension modules then
        you will also need to ensure that Python has been built with this
        enabled.

**Target Python version**
    is used to specify version of Python that you are targeting.

**Target PyQt version**
    is used to specify that the application is either a PyQt4 or a PyQt5
    application.  This is ignored if the application doesn't use PyQt.

**Use console (Windows)**
    is checked if the application should use a console.  Specifically it adds
    ``console`` to the value of ``CONFIG`` in the generated ``.pro`` file and
    only affects Windows applications.  Normally this is handled automatically
    and a console is used only if the application does not use any GUI related
    PyQt module.  However it may be usefull during testing of deployed GUI
    applications to ensure that tracebacks (e.g. about missing modules) are
    captured and displayed.

**Application bundle (macOS)**
    is checked if the application should be built as a bundle and only affects
    macOS targets.  It would normally be unchecked for command line (i.e.
    non-GUI) applications.

**Application Package Directory**
    contains the hierachy of files and directories that implement the
    application package and any associated data.  It is populated by clicking
    the **Scan...** button.  Each file or directory can then be checked if it
    is to be included in the package.  Note that if the main script file is a
    part of the application package then it's entry must be explicitly
    unchecked (i.e. excluded).

    The demo includes a copy of it's source file which is read (when using
    Python v3.7.0 or later) using the :py:mod:`importlib.resources` module.
    This is stored in the ``data`` directory.  This directory must be a Python
    package and so it contains an empty ``__init__.py`` file.  The source file
    is given a ``.dat`` extension so that it doesn't appear to be a Python
    source file to :program:`pyqtdeploy-build`.  If we didn't do this then the
    source file would be replaced by its frozen version.

**Scan...**
    is clicked to specify the name of the directory containing the Python
    package that implements the application.  (If the application consists of a
    single script then you would not use this.)  The hierachy will be scanned
    for all files and directories that don't match any of the specified
    exclusions and will be displayed in the **Application Package Directory**.

**Remove all**
    is clicked to remove all the scanned files and directories.

**Include all**
    is clicked to check all scanned files and directories so that they are
    included in the application package.

**Exclude all**
    is clicked to uncheck all scanned files and directories so that they are
    excluded from the application package.

**Exclusions**
    is used to specify the list of *glob*-style patterns that are applied to
    the scanned files and directories.  Those items that match are then
    completely ignored.  To edit the list just double-click on the entry to
    modify or delete.  To add a new entry just double-click the list after the
    last entry.


Additional :program:`qmake` Configuration
-----------------------------------------

The tab for defining additional :program:`qmake` configuration information is
shown below.

.. image:: /images/qmake_tab.png
    :align: center

Any text entered here is added to the end of the ``.pro`` file generated by
:program:`pyqtdeploy`.


Defining the PyQt Modules
-------------------------

The tab for defining any PyQt modules used by the application is shown below.
If the application is a PyQt4 application then the PyQt4 modules will be shown
instead.

.. image:: /images/pyqt_modules_tab.png
    :align: center

Simply check all the PyQt modules that are imported by the application.

:program:`pyqtdeploy` understands the dependencies between the different PyQt
modules and will automatically check any additional modules that are required.
It is recommended that modules explicitly imported by the application are
checked even if they are also implicity imported.

.. note::
    These modules must be compiled statically.  If you plan to use a separately
    deployed copy of PyQt that will be dynamically loaded by your application
    then do not specify any modules here.


Adding Standard Library Packages
--------------------------------

The tab for defining the Python standard library packages used by the
application is shown below.

.. image:: /images/stdlib_packages_tab.png
    :align: center

**Package**
    is used to specify each of the target Python version's standard library
    packages that is explicitly imported by the application.  Each package can
    be in one of three states:

    - *checked* meaning it is explicitly imported by the application
    - *partially checked* meaning it is implicitly imported by the application
      because another imported package depends on it, or the Python interpreter
      itself imports it
    - *unchecked* meaning it is not needed by the application.

    You should always check a package if the application explicitly imports it,
    even if it is already shown as partially checked.  When a package is
    checked (or unchecked) then any sub-packages are automatically checked (or
    unchecked).

    Here we have checked the :mod:`ssl` and :mod:`sysconfig` modules and the
    :mod:`socket`, :mod:`stat`, :mod:`string`, :mod:`struct` and
    :mod:`subprocess` modules (amongst others) have been partially checked
    automatically.

The remaining part of the tab relates to additional libraries that may need to
be linked with the application.  Typically they correspond to packages in the
standard library that wrap them.  A tab is provided for each target platform so
that a library can be handled in a platform-specific manner.  If a library is
required, because a package that uses it is required, then the entry for the
library will be enabled.  The corresponding ``DEFINES``, ``INCLUDEPATH`` and
``LIBS`` fields will also be editable allowing those values to be set
appropriately.  If all of those fields are left blank then the external library
is effectively disabled.  This can be useful if, for example, the original
Python package is written to use an external library if it is available but
will fall back to another implementation if not.

For example, if you have built a static copy of the library
then you may need to specify the location of the library's header files in the
``INCLUDEPATH`` field and add a ``-L`` flag to the ``LIBS`` field if the
library is not installed in locations that will be found automatically by the
compiler and linker.

:program:`pyqt-demo` imports the :mod:`ssl` module from the standard library
and so the corresponding entry is enabled.  On macOS :program:`pyqt-demo` links
against a static version of OpenSSL.  We use ``INCLUDEPATH`` to specify where
:program:`pyqtdeploy-sysroot` has installed the OpenSSL header files.  Because
the OpenSSL libraries are statically linked as part of the static build of Qt,
there is no need to specify a value for ``LIBS``.  You should click on the
other platform tabs to see how SSL is configured for those.

**Use standard Python shared library**
    is used to specify if the standard Python shared library is to be used
    instead of a specially compiled shared or static library.  When selected
    :program:`pyqtdeploy` assumes that all of the Python standard library that
    is implemented as C extension modules is implemented in the shared library.
    The default is to enable this for Windows.  See also
    :ref:`ref-win-dynload`.


.. _ref-other-packages:

Adding Other Packages
---------------------

The tab for defining additional packages used by the application is shown
below.

.. image:: /images/other_packages_tab.png
    :align: center

This tab is used to scan a number of directories containing additional Python
packages (i.e. other than those that are part of the Python standard library).
You then specify which individual modules are needed, either implicitly or
explicitly, by the application.

To edit the list of directories just double-click on the entry to modify or
delete.  To add a new entry just double-click the list after the last entry.

In many cases you will want to add the ``site-packages`` directory of your host
Python interpreter, i.e. the interpreter being used to develop the application,
where all the additional packages required by your application are already
installed.

:program:`pyqt-demo` does not use any additional Python packages.


.. _ref-other-extension-modules:

Adding Other Extension Modules
------------------------------

The tab for defining additional C extension modules used by the application is
shown below.

.. image:: /images/other_extension_modules_tab.png
    :align: center

This tab is used to specify any additional C extension modules (i.e. other than
those that are part of the Python standard library or PyQt) that will be
statically linked into the application.

These extension modules may already have been built, but this tab can also be
used to compile them from source.  You would only normally do this for simple
extension modules typically made up of a single source file.

**Name**
    is the full (dot separated) package name of the extension module.

**QT**
    are the values added to the :program:`qmake` ``QT`` variable.

**CONFIG**
    are the values added to the :program:`qmake` ``CONFIG`` variable.

**SOURCES**
    are the names of the source files that will be compiled to create the
    extension module.  The file name extension determines which
    :program:`qmake` variable the file is added to:

    - ``.asm`` files are added to ``MASMSOURCES``
    - ``.h`` files are added to ``HEADERS``
    - ``.java`` files are added to ``JAVASOURCES``
    - ``.l`` files are added to ``LEXSOURCES``
    - ``.pyx`` files are added to ``CYTHONSOURCES``
    - ``.y`` files are added to ``YACCSOURCES``.

    Files with any other extension are added to ``SOURCES``.

**DEFINES**
    are the values added to the :program:`qmake` ``DEFINES`` variable.

**INCLUDEPATH**
    are the values added to the :program:`qmake` ``INCLUDEPATH`` variable.

**LIBS**
    are the values added to the :program:`qmake` ``LIBS`` variable.  If the
    extension module has already been compiled then this is used to link it
    with the application.

:program:`pyqtdeploy` goes to some trouble to make it possible to create
project files that can be used without modification across all supported
targets.  To this end the values of these :program:`qmake` variables may be
*scoped* with any supported target architecture or platform name.

The scope is specified immediately before the value and separated from it by a
``#``.  A scope can take one of the following forms (where *target* is either a
target architecture or platform):

- *target* where the value applies for the specified target only

- *!target* where the values applies to all targets except the one specified

- *target|target|...* where the value applies to all of the targets specified.

The most common requirement is to distinguish between Windows and non-Windows
targets, therefore the most common scopes used will be ``win`` and ``!win``.

To edit the list just double-click on the entry to modify or delete.  To add a
new entry just double-click the list after the last entry.

:program:`pyqt-demo` does not use any additional C extension modules.


Defining File and Directory Locations
-------------------------------------

The tab for defining the locations of various files and directories needed by
:program:`pyqtdeploy` is shown below.

.. image:: /images/locations_tab.png
    :align: center

**Interpreter**
    is used to specify the **host** Python interpreter used to compile all of
    the Python modules used by the application.  This must be the same version
    as the **target** Python installation to ensure that the compiled bytecode
    can be executed by the deployed application.  (Of course if you are not
    cross-compiling the application then the host and target Python
    installations can be the same.)  On Windows any trailing version number
    will be automatically stripped.  This makes it easier to create project
    files that are portable across all platforms.  If it is not specified then
    :program:`pyqtdeploy` will use a platform-specific default.  On Windows it
    will inspect the registry to try and find the required version of Python,
    on other platforms it assumes that the required version is on
    :envvar:`PATH`.  It can be overridden by the
    :option:`--interpreter <pyqtdeploy-build --interpreter>` command line
    option of :program:`pyqtdeploy-build`.

**Source directory**
    is used to specify the name of the directory containing the Python source
    code.  It can be overridden by the
    :option:`--source-dir <pyqtdeploy-build --source-dir>` command line option
    of :program:`pyqtdeploy-build`.

**Include directory**
    is used to specify the name of the directory containing the target Python
    installation's ``Python.h`` file.  It can be overridden by the
    :option:`--include-dir <pyqtdeploy-build --include-dir>` command line
    option of :program:`pyqtdeploy-build`.

**Python library**
    is used to specify the name of the target Python interpreter library.  Note
    that in this example the library is specified as a UNIX archive, however
    :program:`pyqtdeploy` will interpret it correctly on Windows.  It can be
    overridden by the
    :option:`--python-library <pyqtdeploy-build --python-library>` command line
    option of :program:`pyqtdeploy-build`.

**Standard library directory**
    is used to specify the name of the directory containing the target Python
    interpreter's standard library.  It can be overridden by the
    :option:`--standard-library-dir <pyqtdeploy-build --standard-library-dir>`
    command line option of :program:`pyqtdeploy-build`.

**Set defaults**
    is used to restore all the other fields to their default values.  Those
    values correspond to the values used by :program:`pyqtdeploy-sysroot`.
