aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.pyside6.md7
-rw-r--r--README.pyside6_addons.md62
-rw-r--r--README.pyside6_essentials.md56
-rw-r--r--build_scripts/main.py18
-rw-r--r--build_scripts/wheel_files.py893
-rw-r--r--coin_build_instructions.py10
-rw-r--r--coin_test_instructions.py11
-rw-r--r--create_wheels.py417
-rw-r--r--requirements.txt2
-rw-r--r--testing/wheel_tester.py19
-rw-r--r--wheel_artifacts/pyproject.toml3
-rw-r--r--wheel_artifacts/setup.cfg.base52
-rw-r--r--wheel_artifacts/setup.py.base29
13 files changed, 1568 insertions, 11 deletions
diff --git a/README.pyside6.md b/README.pyside6.md
index 007903291..0ece3ba72 100644
--- a/README.pyside6.md
+++ b/README.pyside6.md
@@ -23,10 +23,15 @@ and [PyPi](https://pypi.org/project/PySide6/):
pip install PySide6
```
+> Please note: this wheel is an alias to other two wheels
+> [PySide6_Essentials](https://pypi.org/project/PySide6_Essentials) and
+> [PySide6_Addons](https://pypi.org/project/PySide6_Addons), which contains
+> a predefined list of Qt Modules.
+
#### Dependencies
PySide6 versions following 6.0 use a C++ parser based on
-[Clang](http://clang.org/). The Clang library (C-bindings), version 10.0 or
+[Clang](http://clang.org/). The Clang library (C-bindings), version 13.0 or
higher is required for building. Prebuilt versions of it can be downloaded from
[download.qt.io](http://download.qt.io/development_releases/prebuilt/libclang/).
diff --git a/README.pyside6_addons.md b/README.pyside6_addons.md
new file mode 100644
index 000000000..f6e2e6605
--- /dev/null
+++ b/README.pyside6_addons.md
@@ -0,0 +1,62 @@
+# PySide6 Addons
+
+PySide6 is the official Python module from the
+[Qt for Python project](http://wiki.qt.io/Qt_for_Python),
+which provides access to the complete Qt 6.0+ framework.
+
+The Qt for Python project is developed in the open, with all facilities you'd expect
+from any modern OSS project such as all code in a git repository and an open
+design process. We welcome any contribution conforming to the
+[Qt Contribution Agreement](https://www.qt.io/contributionagreement/).
+
+This is a complementary wheel for [PySide6](https://pypi.org/project/PySide6),
+it includes the following Qt modules:
+
+* Qt3DAnimation
+* Qt3DCore
+* Qt3DExtras
+* Qt3DInput
+* Qt3DLogic
+* Qt3DRender
+* QtAxContainer
+* QtBluetooth
+* QtCharts
+* QtDataVisualization
+* QtMultimedia
+* QtMultimediaWidgets
+* QtNetworkAuth
+* QtNfc
+* QtPositioning
+* QtQuick3D
+* QtRemoteObjects
+* QtScxml
+* QtSensors
+* QtSerialPort
+* QtStateMachine
+* QtVirtualKeyboard
+* QtWebChannel
+* QtWebEngineCore
+* QtWebEngineQuick
+* QtWebEngineWidgets
+* QtWebSockets
+
+### Documentation and Bugs
+
+You can find more information about the PySide6 module API in the
+[official Qt for Python documentation](https://doc.qt.io/qtforpython/).
+
+If you come across any issue, please file a bug report at our
+[JIRA tracker](https://bugreports.qt.io/projects/PYSIDE) following
+our [guidelines](https://wiki.qt.io/Qt_for_Python/Reporting_Bugs).
+
+### Community
+
+Check *#qt-pyside*, our official IRC channel on FreeNode, or contact us via our
+[mailing list](http://lists.qt-project.org/mailman/listinfo/pyside).
+
+### Licensing
+
+PySide6 is available under both Open Source (LGPLv3/GPLv2) and commercial
+license. Using PyPi is the recommended installation source, because the
+content of the wheels is valid for both cases. For more information, refer to
+the [Qt Licensing page](https://www.qt.io/licensing/).
diff --git a/README.pyside6_essentials.md b/README.pyside6_essentials.md
new file mode 100644
index 000000000..629db92ef
--- /dev/null
+++ b/README.pyside6_essentials.md
@@ -0,0 +1,56 @@
+# PySide6 Essentials
+
+PySide6 is the official Python module from the
+[Qt for Python project](http://wiki.qt.io/Qt_for_Python),
+which provides access to the complete Qt 6.0+ framework.
+
+The Qt for Python project is developed in the open, with all facilities you'd expect
+from any modern OSS project such as all code in a git repository and an open
+design process. We welcome any contribution conforming to the
+[Qt Contribution Agreement](https://www.qt.io/contributionagreement/).
+
+This is a minimal wheel for [PySide6](https://pypi.org/project/PySide6),
+it includes only the essentials Qt modules:
+
+* QtCore
+* QtGui
+* QtWidgets
+* QtHelp
+* QtNetwork
+* QtConcurrent
+* QtDBus
+* QtDesigner
+* QtOpenGL
+* QtOpenGLWidgets
+* QtPrintSupport
+* QtQml
+* QtQuick
+* QtQuickControls2
+* QtQuickWidgets
+* QtXml
+* QtTest
+* QtSql
+* QtSvg
+* QtSvgWidgets
+* QtUiTools
+
+### Documentation and Bugs
+
+You can find more information about the PySide6 module API in the
+[official Qt for Python documentation](https://doc.qt.io/qtforpython/).
+
+If you come across any issue, please file a bug report at our
+[JIRA tracker](https://bugreports.qt.io/projects/PYSIDE) following
+our [guidelines](https://wiki.qt.io/Qt_for_Python/Reporting_Bugs).
+
+### Community
+
+Check *#qt-pyside*, our official IRC channel on FreeNode, or contact us via our
+[mailing list](http://lists.qt-project.org/mailman/listinfo/pyside).
+
+### Licensing
+
+PySide6 is available under both Open Source (LGPLv3/GPLv2) and commercial
+license. Using PyPi is the recommended installation source, because the
+content of the wheels is valid for both cases. For more information, refer to
+the [Qt Licensing page](https://www.qt.io/licensing/).
diff --git a/build_scripts/main.py b/build_scripts/main.py
index e50ca791e..75850691b 100644
--- a/build_scripts/main.py
+++ b/build_scripts/main.py
@@ -44,6 +44,7 @@ import platform
import re
import sys
import importlib
+from pathlib import Path
from textwrap import dedent
import time
from .config import config
@@ -443,6 +444,23 @@ class PysideBuild(_build, DistUtilsCommandMixin, BuildInfoCollectorMixin):
# Build packages
_build.run(self)
+
+ # Keep packaged directories for wheel construction
+ # This is to take advantage of the packaging step
+ # to keep the data in the proper structure to create
+ # a wheel.
+ _path = Path(self.st_build_dir)
+ _wheel_path = _path.parent / "package_for_wheels"
+ if not _wheel_path.exists():
+ _wheel_path.mkdir()
+ _package_name = os.listdir(_path)[0]
+ _src = Path(_path / _package_name)
+ _dst = Path(_wheel_path / _package_name)
+ try:
+ Path(_path / _package_name).rename(_wheel_path / _package_name)
+ except Exception as e:
+ log.warn(f'***** problem renaming "{self.st_build_dir}"')
+ log.warn(f'ignored error: {type(e).__name__}: {e}')
else:
log.info("Skipped preparing and building packages.")
log.info(f"--- Build completed ({elapsed()}s)")
diff --git a/build_scripts/wheel_files.py b/build_scripts/wheel_files.py
new file mode 100644
index 000000000..237a16b38
--- /dev/null
+++ b/build_scripts/wheel_files.py
@@ -0,0 +1,893 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+
+import sys
+from dataclasses import Field, dataclass, field
+from typing import Any, Dict, List
+
+
+# This dataclass is in charge of holding the file information
+# that each Qt module needs to have to be packaged in a wheel
+@dataclass
+class ModuleData:
+ name: str
+ ext: str = ""
+ # Libraries not related to Qt modules
+ lib: List[str] = field(default_factory=list)
+ # Libraries related to Qt modules
+ qtlib: List[str] = field(default_factory=list)
+ # Files from the Qt/qml directory
+ qml: List[str] = field(default_factory=list)
+ pyi: List[str] = field(default_factory=list)
+ translations: List[str] = field(default_factory=list)
+ typesystems: List[str] = field(default_factory=list)
+ include: List[str] = field(default_factory=list)
+ glue: List[str] = field(default_factory=list)
+ metatypes: List[str] = field(default_factory=list)
+ examples: List[str] = field(default_factory=list)
+ plugins: List[str] = field(default_factory=list)
+
+ # For special cases when a file/directory doesn't fall into
+ # the previous categories.
+ extra_dirs: List[str] = field(default_factory=list)
+ extra_files: List[str] = field(default_factory=list)
+
+ # Once the object is created, this method will be executed
+ # and automatically will initialize some of the files that are
+ # common for each module.
+ # Note: The goal of this list is to be used for a MANIFEST.in
+ # meaning that in case a file gets added and it doesn't
+ # exist, the wheel creation process will only throw a
+ # warning, but it will not interrupt the packaging process.
+ def __post_init__(self) -> None:
+ if not self.ext:
+ self.ext = self.get_extension_from_platform(sys.platform)
+ _lo = self.name.lower()
+
+ self.lib.append(f"Qt{self.name}")
+ self.qtlib.append(f"libQt6{self.name}")
+ if not len(self.qml):
+ self.qml.append(f"Qt{self.name}")
+ self.pyi.append(f"Qt{self.name}.pyi")
+ self.typesystems.append(f"typesystem_{_lo}.xml")
+ self.include.append(f"Qt{self.name}/*.h")
+ self.glue.append(f"qt{_lo}.cpp")
+ if not len(self.metatypes):
+ self.metatypes.append(f"qt6{_lo}_relwithdebinfo_metatypes.json")
+ self.examples.append(f"{_lo}")
+
+ # The PySide6 directory that gets packaged by the build_scripts
+ # 'prepare_packages()' has a certain structure that depends on
+ # the platform. Because that directory is the base for the wheel
+ # packaging to work, we use the relative paths that are included
+ # on each file.
+ # Note: The MANIFEST.in file doesn't need to have '\' or other
+ # separator, and respect the '/' even on Windows.
+ def adjusts_paths_and_extensions(self) -> None:
+ if sys.platform == "win32":
+ self.lib = [f"{i}.*{self.ext}".replace("lib", "") for i in self.lib]
+ self.qtlib = [f"{i}.*dll".replace("lib", "") for i in self.qtlib]
+ self.qml = [f"qml/{i}" for i in self.qml]
+ self.translations = [f"translations/{i}" for i in self.translations]
+ self.metatypes = [
+ f"lib/metatypes/{i}".replace("_relwithdebinfo", "") for i in self.metatypes
+ ]
+ self.plugins = [f"plugins/{i}" for i in self.plugins]
+ else:
+ if sys.platform == "darwin":
+ self.qtlib = [f"Qt/lib/{i.replace('libQt6', 'Qt')}.framework" for i in self.qtlib]
+ self.lib = [self.macos_pyside_wrappers_lib(i) for i in self.lib]
+ else:
+ self.lib = [f"{i}.*{self.ext}*" for i in self.lib]
+ self.qtlib = [f"Qt/lib/{i}.*{self.ext}*" for i in self.qtlib]
+ self.qml = [f"Qt/qml/{i}" for i in self.qml]
+ self.translations = [f"Qt/translations/{i}" for i in self.translations]
+ self.metatypes = [f"Qt/lib/metatypes/{i}" for i in self.metatypes]
+ self.plugins = [f"Qt/plugins/{i}" for i in self.plugins]
+
+ self.typesystems = [f"typesystems/{i}" for i in self.typesystems]
+ self.include = [f"include/{i}" for i in self.include]
+ self.glue = [f"glue/{i}" for i in self.glue]
+ self.examples = [f"examples/{i}" for i in self.examples]
+
+ def macos_pyside_wrappers_lib(self, s):
+ if s.startswith("Qt"):
+ return f"{s}.*so*"
+ else:
+ return f"{s}.*{self.ext}*"
+
+ @classmethod
+ def get_fields(cls) -> Dict[str, Field]:
+ return cls.__dataclass_fields__
+
+ @staticmethod
+ def get_extension_from_platform(platform: str) -> str:
+ if platform == "linux":
+ return "so"
+ elif platform == "darwin":
+ return "dylib"
+ elif platform == "win32":
+ return "pyd"
+ else:
+ print(f"Platform '{platform}' not supported. Exiting")
+ sys.exit(-1)
+
+
+# Wheels auxiliary functions to return the ModuleData objects
+# for each module that will be included in the wheel.
+
+# PySide wheel
+def wheel_files_pyside_essentials() -> List[ModuleData]:
+ files = [
+ module_QtCore(),
+ module_QtGui(),
+ module_QtWidgets(),
+ module_QtHelp(),
+ module_QtNetwork(),
+ module_QtConcurent(),
+ module_QtDBus(),
+ module_QtDesigner(),
+ module_QtOpenGL(),
+ module_QtOpenGLWidgets(),
+ module_QtPrintSupport(),
+ module_QtQml(),
+ module_QtQuick(),
+ module_QtQuickControls2(),
+ module_QtQuickWidgets(),
+ module_QtXml(),
+ module_QtTest(),
+ module_QtSql(),
+ module_QtSvg(),
+ module_QtSvgWidgets(),
+ module_QtUiTools(),
+ # Only for plugins
+ module_QtWayland(),
+ ]
+ return files
+
+
+# PySide Addons wheel
+def wheel_files_pyside_addons() -> List[ModuleData]:
+ files = [
+ module_Qt3DAnimation(),
+ module_Qt3DCore(),
+ module_Qt3DExtras(),
+ module_Qt3DInput(),
+ module_Qt3DLogic(),
+ module_Qt3DRender(),
+ module_QtAxContainer(),
+ module_QtBluetooth(),
+ module_QtCharts(),
+ module_QtDataVisualization(),
+ module_QtMultimedia(),
+ module_QtMultimediaWidgets(),
+ module_QtNetworkAuth(),
+ module_QtNfc(),
+ module_QtPositioning(),
+ module_QtQuick3D(),
+ module_QtRemoteObjects(),
+ module_QtScxml(),
+ module_QtSensors(),
+ module_QtSerialPort(),
+ module_QtStateMachine(),
+ # Not available in 6.3
+ #module_QtTextToSpeech(),
+ module_QtVirtualKeyboard(),
+ module_QtWebChannel(),
+ module_QtWebEngineCore(),
+ module_QtWebEngineQuick(),
+ module_QtWebEngineWidgets(),
+ module_QtWebSockets(),
+ ]
+ return files
+
+
+# Functions that hold the information of all the files that needs
+# to be included for the module to work, including Qt libraries,
+# examples, typesystems, glue, etc.
+def module_QtCore() -> ModuleData:
+ # QtCore
+ data = ModuleData("Core", examples=["corelib"])
+ data.typesystems.append("core_common.xml")
+ data.typesystems.append("typesystem_core_common.xml")
+ data.typesystems.append("typesystem_core_win.xml")
+ data.include.append("*.h")
+ if sys.platform == "win32":
+ data.plugins.append("assetimporters")
+ data.plugins.append("styles")
+ data.qtlib.append("pyside6.*")
+ data.extra_files.append("qt.conf")
+ data.extra_files.append("uic.exe")
+ data.extra_files.append("rcc.exe")
+ data.extra_files.append("qtdiag.exe")
+ data.extra_files.append("d3dcompiler*")
+ data.extra_files.append("lconvert*")
+ data.extra_files.append("pyside6.*.lib")
+ data.extra_files.append("resources/icudtl.dat")
+ else:
+ data.lib.append("libpyside6.*")
+ if sys.platform == "darwin":
+ data.plugins.append("styles")
+
+ data.examples.append("samplebinding")
+ data.examples.append("widgetbinding")
+ data.examples.append("scriptableapplication")
+ data.examples.append("utils")
+ data.examples.append("external")
+ data.examples.append("installer_test")
+ data.examples.append("macextras")
+
+ # *.py
+ data.extra_dirs.append("support")
+ data.extra_dirs.append("scripts")
+
+ data.extra_dirs.append("Qt/libexec/")
+ data.extra_dirs.append("typesystems/glue")
+
+ data.extra_files.append("__feature__.pyi")
+ data.extra_files.append("__init__.py")
+ data.extra_files.append("_git_pyside_version.py")
+ data.extra_files.append("_config.py")
+ data.extra_files.append("py.typed")
+
+ # Assistant
+ if sys.platform == "darwin":
+ data.extra_dirs.append("Assistant.app")
+ else:
+ data.extra_files.append("assistant*")
+ data.translations.append("assistant_*")
+
+ # Designer
+ if sys.platform == "darwin":
+ data.extra_dirs.append("Designer.app")
+ else:
+ data.extra_files.append("designer*")
+ data.translations.append("designer_*")
+
+ # Linguist
+ if sys.platform == "darwin":
+ data.extra_dirs.append("Linguist.app")
+ else:
+ data.extra_files.append("linguist*")
+ data.translations.append("linguist_*")
+
+ data.extra_files.append("lrelease*")
+ data.extra_files.append("lupdate*")
+ data.extra_files.append("qmllint*")
+
+ # General translations
+ data.translations.append("qtbase_*")
+ data.translations.append("qt_help_*")
+ data.translations.append("qt_*")
+
+ data.extra_files.append("examples/examples.pyproject")
+
+ # plugins
+ data.plugins.append("platforms")
+ data.plugins.append("platformthemes")
+ data.plugins.append("platforminputcontexts")
+ data.plugins.append("imageformats")
+ data.plugins.append("generic")
+ data.plugins.append("xcbglintegrations")
+
+ # Extra libraries
+ data.qtlib.append("libicudata*")
+ data.qtlib.append("libicui18n*")
+ data.qtlib.append("libicule*")
+ data.qtlib.append("libiculx*")
+ data.qtlib.append("libicutest*")
+ data.qtlib.append("libicutu*")
+ data.qtlib.append("libicuuc*")
+ data.qtlib.append("libicuio*")
+
+ return data
+
+
+def module_QtGui() -> ModuleData:
+ data = ModuleData("Gui")
+ _typesystems = [
+ "gui_common.xml",
+ "typesystem_gui_common.xml",
+ "typesystem_gui_mac.xml",
+ "typesystem_gui_win.xml",
+ "typesystem_gui_x11.xml",
+ ]
+
+ _metatypes = [
+ "qt6eglfsdeviceintegrationprivate_relwithdebinfo_metatypes.json",
+ "qt6eglfskmssupportprivate_relwithdebinfo_metatypes.json",
+ "qt6kmssupportprivate_relwithdebinfo_metatypes.json",
+ "qt6xcbqpaprivate_relwithdebinfo_metatypes.json",
+ ]
+
+ _qtlib = [
+ "libQt6EglFSDeviceIntegration",
+ "libQt6EglFsKmsSupport",
+ "libQt6XcbQpa",
+ ]
+
+ data.typesystems.extend(_typesystems)
+ data.metatypes.extend(_metatypes)
+ data.qtlib.extend(_qtlib)
+
+ data.plugins.append("egldeviceintegrations")
+ data.extra_files.append("Qt/plugins/platforms/libqeglfs*")
+
+ return data
+
+
+def module_QtWidgets() -> ModuleData:
+ data = ModuleData("Widgets")
+ data.typesystems.append("widgets_common.xml")
+ data.typesystems.append("typesystem_widgets_common.xml")
+
+ return data
+
+
+def module_QtHelp() -> ModuleData:
+ data = ModuleData("Help")
+
+ return data
+
+
+def module_QtNetwork() -> ModuleData:
+ data = ModuleData("Network")
+ data.plugins.append("networkinformation")
+ data.plugins.append("tls")
+
+ return data
+
+
+def module_QtBluetooth() -> ModuleData:
+ data = ModuleData("Bluetooth")
+
+ return data
+
+
+def module_QtConcurent() -> ModuleData:
+ data = ModuleData("Concurrent")
+
+ return data
+
+
+def module_QtDBus() -> ModuleData:
+ data = ModuleData("DBus")
+
+ return data
+
+
+def module_QtDesigner() -> ModuleData:
+ data = ModuleData("Designer")
+ data.qtlib.append("libQt6DesignerComponents")
+ data.metatypes.append("qt6designercomponentsprivate_relwithdebinfo_metatypes.json")
+ data.plugins.append("designer")
+ data.extra_files.append("Qt/plugins/assetimporters/libuip*")
+
+ return data
+
+
+def module_QtNfc() -> ModuleData:
+ data = ModuleData("Nfc")
+
+ return data
+
+
+def module_QtPrintSupport() -> ModuleData:
+ data = ModuleData("PrintSupport")
+ data.typesystems.append("typesystem_printsupport_common.xml")
+ data.plugins.append("printsupport")
+
+ return data
+
+
+def module_QtQml() -> ModuleData:
+ data = ModuleData("Qml")
+
+ _qtlib = [
+ "libQt6LabsAnimation",
+ "libQt6LabsFolderListModel",
+ "libQt6LabsQmlModels*",
+ "libQt6LabsSettings",
+ "libQt6LabsSharedImage",
+ "libQt6LabsWavefrontMesh",
+ "libQt6QmlCore",
+ "libQt6QmlLocalStorage",
+ "libQt6QmlModels",
+ "libQt6QmlWorkerScript",
+ "libQt6QmlXmlListModel",
+ ]
+
+ _include = [
+ "pysideqml.h",
+ "pysideqmlmacros.h",
+ "pysideqmlregistertype.h",
+ ]
+
+ _metatypes = [
+ "qt6labsanimation_relwithdebinfo_metatypes.json",
+ "qt6labsfolderlistmodel_relwithdebinfo_metatypes.json",
+ "qt6labsqmlmodels_relwithdebinfo_metatypes.json",
+ "qt6labssettings_relwithdebinfo_metatypes.json",
+ "qt6labssharedimage_relwithdebinfo_metatypes.json",
+ "qt6labswavefrontmesh_relwithdebinfo_metatypes.json",
+ "qt6packetprotocolprivate_relwithdebinfo_metatypes.json",
+ "qt6qmlcompilerprivate_relwithdebinfo_metatypes.json",
+ "qt6qmlcore_relwithdebinfo_metatypes.json",
+ "qt6qmldebugprivate_relwithdebinfo_metatypes.json",
+ "qt6qmldomprivate_relwithdebinfo_metatypes.json",
+ "qt6qmllintprivate_relwithdebinfo_metatypes.json",
+ "qt6qmllocalstorage_relwithdebinfo_metatypes.json",
+ "qt6qmlmodels_relwithdebinfo_metatypes.json",
+ "qt6qmlworkerscript_relwithdebinfo_metatypes.json",
+ "qt6qmlxmllistmodel_relwithdebinfo_metatypes.json",
+ ]
+
+ _qml = [
+ "Qt/labs/animation",
+ "Qt/labs/folderlistmodel",
+ "Qt/labs/sharedimage",
+ "Qt/labs/wavefrontmesh",
+ "Qt/labs/qmlmodels",
+ "Qt/labs/platform",
+ "Qt/labs/settings",
+ ]
+
+ data.lib.append("libpyside6qml")
+ data.examples.append("declarative")
+ data.plugins.append("qmltooling")
+ data.translations.append("qtdeclarative_*")
+ if sys.platform == "win32":
+ data.extra_files.append("pyside6qml.*.lib")
+ data.extra_files.append("pyside6qml.*.dll")
+ data.extra_files.append("qml/builtins.qmltypes")
+ data.extra_files.append("qml/jsroot.qmltypes")
+ else:
+ data.extra_files.append("Qt/qml/builtins.qmltypes")
+ data.extra_files.append("Qt/qml/jsroot.qmltypes")
+
+ data.qtlib.extend(_qtlib)
+ data.include.extend(_include)
+ data.metatypes.extend(_metatypes)
+ data.qml.extend(_qml)
+
+ return data
+
+
+def module_QtQuick() -> ModuleData:
+ data = ModuleData("Quick")
+ _metatypes = [
+ "qt6quickcontrolstestutilsprivate_relwithdebinfo_metatypes.json",
+ "qt6quickdialogs2_relwithdebinfo_metatypes.json",
+ "qt6quickdialogs2quickimpl_relwithdebinfo_metatypes.json",
+ "qt6quickdialogs2utils_relwithdebinfo_metatypes.json",
+ "qt6quicketest_relwithdebinfo_metatypes.json",
+ "qt6quicketestutilsprivate_relwithdebinfo_metatypes.json",
+ "qt6quicklayouts_relwithdebinfo_metatypes.json",
+ "qt6quickparticlesprivate_relwithdebinfo_metatypes.json",
+ "qt6quickshapesprivate_relwithdebinfo_metatypes.json",
+ "qt6quicktemplates2_relwithdebinfo_metatypes.json",
+ "qt6quicktest_relwithdebinfo_metatypes.json",
+ "qt6quicktestutilsprivate_relwithdebinfo_metatypes.json",
+ "qt6quicktimeline_relwithdebinfo_metatypes.json",
+ ]
+ _qtlib = [
+ "libQt6QuickDialogs2",
+ "libQt6QuickDialogs2QuickImpl",
+ "libQt6QuickDialogs2Utils",
+ "libQt6QuickLayouts",
+ "libQt6QuickParticles",
+ "libQt6QuickShapes",
+ "libQt6QuickTemplates2",
+ "libQt6QuickTest",
+ "libQt6QuickTimeline",
+ ]
+
+ data.qtlib.extend(_qtlib)
+ data.metatypes.extend(_metatypes)
+
+ return data
+
+
+def module_QtQuickControls2() -> ModuleData:
+ data = ModuleData("QuickControls2")
+ data.qtlib.append("libQt6QuickControls2Impl")
+ data.metatypes.append("qt6quickcontrols2impl_relwithdebinfo_metatypes.json")
+
+ return data
+
+
+def module_QtQuickWidgets() -> ModuleData:
+ data = ModuleData("QuickWidgets")
+ return data
+
+
+def module_QtXml() -> ModuleData:
+ data = ModuleData("Xml")
+ return data
+
+
+def module_QtTest() -> ModuleData:
+ data = ModuleData("Test")
+ return data
+
+
+def module_QtSql() -> ModuleData:
+ data = ModuleData("Sql")
+ data.plugins.append("sqldrivers")
+
+ return data
+
+
+def module_QtSvg() -> ModuleData:
+ data = ModuleData("Svg")
+ data.plugins.append("iconengines")
+
+ return data
+
+
+def module_QtSvgWidgets() -> ModuleData:
+ data = ModuleData("SvgWidgets")
+
+ return data
+
+
+def module_QtTextToSpeech() -> ModuleData:
+ data = ModuleData("TextToSpeech")
+
+ return data
+
+
+def module_QtUiTools() -> ModuleData:
+ data = ModuleData("UiTools")
+
+ return data
+
+
+def module_QtWayland() -> ModuleData:
+ data = ModuleData("Wayland")
+
+ _qtlib = [
+ "libQt6WaylandClient",
+ "libQt6WaylandCompositor",
+ "libQt6WaylandEglClientHwIntegration",
+ "libQt6WaylandEglCompositorHwIntegration",
+ "libQt6WlShellIntegration",
+ ]
+
+ _metatypes = [
+ "qt6waylandclient_relwithdebinfo_metatypes.json",
+ "qt6waylandeglclienthwintegrationprivate_relwithdebinfo_metatypes.json",
+ "qt6wlshellintegrationprivate_relwithdebinfo_metatypes.json",
+ ]
+
+ # This is added by module_QtCore()
+ # data.plugins.append("platforms")
+ _plugins = [
+ "wayland-decoration",
+ "wayland-decoration-client",
+ "wayland-graphics-integration-client",
+ "wayland-graphics-integration-server",
+ "wayland-shell-integration",
+ ]
+
+ data.qtlib.extend(_qtlib)
+ data.metatypes.extend(_metatypes)
+ data.plugins.extend(_plugins)
+ return data
+
+
+def module_Qt3DCore() -> ModuleData:
+ data = ModuleData("3DCore", qml=["Qt3D/Core"])
+
+ _plugins = [
+ "geometryloaders",
+ "renderers",
+ "renderplugins",
+ "sceneparsers",
+ ]
+
+ data.plugins.extend(_plugins)
+ data.examples.append("3d")
+ return data
+
+
+def module_Qt3DAnimation() -> ModuleData:
+ data = ModuleData("3DAnimation", qml=["Qt3D/Animation"])
+
+ return data
+
+
+def module_Qt3DExtras() -> ModuleData:
+ data = ModuleData("3DExtras", qml=["Qt3D/Extras"])
+
+ return data
+
+
+def module_Qt3DInput() -> ModuleData:
+ data = ModuleData("3DInput", qml=["Qt3D/Input"])
+
+ return data
+
+
+def module_Qt3DLogic() -> ModuleData:
+ data = ModuleData("3DLogic", qml=["Qt3D/Logic"])
+
+ return data
+
+
+def module_Qt3DRender() -> ModuleData:
+ data = ModuleData("3DRender", qml=["Qt3D/Render"])
+
+ return data
+
+
+def module_QtQuick3D() -> ModuleData:
+ data = ModuleData("Quick3D")
+
+ _qtlib = [
+ "libQt6Quick3DAssetImport",
+ "libQt6Quick3DAssetUtils",
+ "libQt6Quick3DEffects",
+ "libQt6Quick3DGlslParser",
+ "libQt6Quick3DHelpers",
+ "libQt6Quick3DIblBaker",
+ "libQt6Quick3DParticleEffects",
+ "libQt6Quick3DParticles",
+ "libQt6Quick3DRuntimeRender",
+ "libQt6Quick3DUtils",
+ "libQt6ShaderTools",
+ "libQt63DQuick",
+ "libQt63DQuickAnimation",
+ "libQt63DQuickExtras",
+ "libQt63DQuickExtras",
+ "libQt63DQuickInput",
+ "libQt63DQuickRender",
+ "libQt63DQuickScene2D",
+ ]
+
+ _metatypes = [
+ "qt63dquick_relwithdebinfo_metatypes.json",
+ "qt63dquickanimation_relwithdebinfo_metatypes.json",
+ "qt63dquickextras_relwithdebinfo_metatypes.json",
+ "qt63dquickinput_relwithdebinfo_metatypes.json",
+ "qt63dquickrender_relwithdebinfo_metatypes.json",
+ "qt63dquickscene2d_relwithdebinfo_metatypes.json",
+ "qt6quick3dassetimport_relwithdebinfo_metatypes.json",
+ "qt6quick3dassetutils_relwithdebinfo_metatypes.json",
+ "qt6quick3deffects_relwithdebinfo_metatypes.json",
+ "qt6quick3dglslparserprivate_relwithdebinfo_metatypes.json",
+ "qt6quick3dhelpers_relwithdebinfo_metatypes.json",
+ "qt6quick3diblbaker_relwithdebinfo_metatypes.json",
+ "qt6quick3dparticleeffects_relwithdebinfo_metatypes.json",
+ "qt6quick3dparticles_relwithdebinfo_metatypes.json",
+ "qt6quick3druntimerender_relwithdebinfo_metatypes.json",
+ "qt6quick3dutils_relwithdebinfo_metatypes.json",
+ "qt6shadertools_relwithdebinfo_metatypes.json",
+ ]
+
+ data.qtlib.extend(_qtlib)
+ data.metatypes.extend(_metatypes)
+ data.extra_files.append("Qt/plugins/assetimporters/libassimp*")
+
+ return data
+
+
+def module_QtAxContainer() -> ModuleData:
+ data = ModuleData("AxContainer")
+ if sys.platform == "win32":
+ data.metatypes.append("qt6axbaseprivate_metatypes.json")
+ data.metatypes.append("qt6axserver_metatypes.json")
+
+ return data
+
+
+def module_QtWebEngineCore() -> ModuleData:
+ data = ModuleData("WebEngineCore", qml=["QtWebEngine"])
+ data.translations.append("qtwebengine_locales/*")
+ data.translations.append("qtwebengine_*")
+ data.extra_dirs.append("Qt/resources")
+ if sys.platform == "win32":
+ data.extra_files.append("resources/qtwebengine*.pak")
+ data.extra_files.append("QtWebEngineProcess.exe")
+
+ return data
+
+
+def module_QtWebEngineWidgets() -> ModuleData:
+ data = ModuleData("WebEngineWidgets")
+
+ return data
+
+
+def module_QtWebEngineQuick() -> ModuleData:
+ data = ModuleData("WebEngineQuick")
+ data.qtlib.append("libQt6WebEngineQuickDelegatesQml")
+ data.metatypes.append("qt6webenginequickdelegatesqml_relwithdebinfo_metatypes.json")
+
+ return data
+
+
+def module_QtCharts() -> ModuleData:
+ data = ModuleData("Charts")
+ data.qtlib.append("libQt6ChartsQml")
+ data.metatypes.append("qt6chartsqml_relwithdebinfo_metatypes.json")
+
+ return data
+
+
+def module_QtDataVisualization() -> ModuleData:
+ data = ModuleData("DataVisualization")
+ data.qtlib.append("libQt6DataVisualizationQml")
+ data.metatypes.append("qt6datavisualizationqml_relwithdebinfo_metatypes.json")
+ data.typesystems.append("datavisualization_common.xml")
+
+ return data
+
+
+def module_QtMultimedia() -> ModuleData:
+ data = ModuleData("Multimedia")
+ data.qtlib.append("libQt6MultimediaQuick")
+ data.metatypes.append("qt6multimediaquickprivate_relwithdebinfo_metatypes.json")
+ data.translations.append("qtmultimedia_*")
+
+ return data
+
+
+def module_QtMultimediaWidgets() -> ModuleData:
+ data = ModuleData("MultimediaWidgets")
+
+ return data
+
+
+def module_QtNetworkAuth() -> ModuleData:
+ data = ModuleData("NetworkAuth")
+
+ return data
+
+
+def module_QtPositioning() -> ModuleData:
+ data = ModuleData("Positioning")
+ data.qtlib.append("libQt6PositioningQuick")
+ data.metatypes.append("qt6positioningquick_relwithdebinfo_metatypes.json")
+ data.plugins.append("position")
+
+ return data
+
+
+def module_QtRemoteObjects() -> ModuleData:
+ data = ModuleData("RemoteObjects")
+ data.qtlib.append("libQt6RemoteObjectsQml")
+ data.metatypes.append("qt6remoteobjectsqml_relwithdebinfo_metatypes.json")
+
+ return data
+
+
+def module_QtSensors() -> ModuleData:
+ data = ModuleData("Sensors")
+ data.qtlib.append("libQt6SensorsQuick")
+ data.metatypes.append("qt6sensorsquick_relwithdebinfo_metatypes.json")
+ data.plugins.append("sensors")
+
+ return data
+
+
+def module_QtSerialPort() -> ModuleData:
+ data = ModuleData("SerialPort")
+ data.translations.append("qtserialport_*")
+
+ return data
+
+
+def module_QtStateMachine() -> ModuleData:
+ data = ModuleData("StateMachine")
+ data.qtlib.append("libQt6StateMachineQml")
+ data.metatypes.append("qt6statemachineqml_relwithdebinfo_metatypes.json")
+
+ return data
+
+
+def module_QtScxml() -> ModuleData:
+ data = ModuleData("Scxml")
+ data.qtlib.append("libQt6ScxmlQml")
+ data.metatypes.append("qt6scxmlqml_relwithdebinfo_metatypes.json")
+ data.plugins.append("scxmldatamodel")
+
+ return data
+
+
+def module_QtWebChannel() -> ModuleData:
+ data = ModuleData("WebChannel")
+
+ return data
+
+
+def module_QtWebSockets() -> ModuleData:
+ data = ModuleData("WebSockets")
+ data.translations.append("qtwebsockets_*")
+
+ return data
+
+
+def module_QtOpenGL() -> ModuleData:
+ data = ModuleData("OpenGL")
+ _typesystems = [
+ "opengl_common.xml",
+ "typesystem_opengl_modifications1_0.xml",
+ "typesystem_opengl_modifications1_0_compat.xml",
+ "typesystem_opengl_modifications1_1.xml",
+ "typesystem_opengl_modifications1_1_compat.xml",
+ "typesystem_opengl_modifications1_2_compat.xml",
+ "typesystem_opengl_modifications1_3_compat.xml",
+ "typesystem_opengl_modifications1_4.xml",
+ "typesystem_opengl_modifications1_4_compat.xml",
+ "typesystem_opengl_modifications2_0.xml",
+ "typesystem_opengl_modifications2_0_compat.xml",
+ "typesystem_opengl_modifications2_1.xml",
+ "typesystem_opengl_modifications3_0.xml",
+ "typesystem_opengl_modifications3_3.xml",
+ "typesystem_opengl_modifications3_3a.xml",
+ "typesystem_opengl_modifications4_0.xml",
+ "typesystem_opengl_modifications4_1.xml",
+ "typesystem_opengl_modifications4_3.xml",
+ "typesystem_opengl_modifications4_4.xml",
+ "typesystem_opengl_modifications4_4_core.xml",
+ "typesystem_opengl_modifications4_5.xml",
+ "typesystem_opengl_modifications4_5_core.xml",
+ "typesystem_opengl_modifications_va.xml",
+ ]
+
+ data.typesystems.extend(_typesystems)
+ if sys.platform == "win32":
+ data.extra_files.append("opengl32*.dll")
+
+ return data
+
+
+def module_QtOpenGLWidgets() -> ModuleData:
+ data = ModuleData("OpenGLWidgets")
+
+ return data
+
+
+def module_QtVirtualKeyboard() -> ModuleData:
+ data = ModuleData("VirtualKeyboard")
+ data.plugins.append("virtualkeyboard")
+
+ return data
diff --git a/coin_build_instructions.py b/coin_build_instructions.py
index 43f789a2e..ba281eb4d 100644
--- a/coin_build_instructions.py
+++ b/coin_build_instructions.py
@@ -140,7 +140,7 @@ def call_setup(python_ver, phase):
cmd = [env_python, "-u", "setup.py"]
if phase in ["BUILD"]:
- cmd += ["build", "--standalone", "--skip-packaging"]
+ cmd += ["build", "--standalone"]
elif phase in ["WHEEL"] or CI_RELEASE_CONF:
cmd += ["bdist_wheel", "--reuse-build", "--standalone", "--skip-cmake", "--skip-make-install", "--only-package"]
@@ -153,8 +153,8 @@ def call_setup(python_ver, phase):
if CI_USE_SCCACHE:
cmd += [f"--compiler-launcher={CI_USE_SCCACHE}"]
- if python_ver == "3":
- cmd += ["--limited-api=yes"]
+ cmd += ["--limited-api=yes"]
+
if is_snapshot_build():
cmd += ["--snapshot-build"]
@@ -173,6 +173,10 @@ def call_setup(python_ver, phase):
env = os.environ
run_instruction(cmd, "Failed to run setup.py for build", initial_env=env)
+ if phase in ["WHEEL"] or CI_RELEASE_CONF:
+ cmd = [env_python, "create_wheels.py"]
+ run_instruction(cmd, "Failed to create new wheels", initial_env=env)
+
if __name__ == "__main__":
# Remove some environment variables that impact cmake
diff --git a/coin_test_instructions.py b/coin_test_instructions.py
index 732a5ba86..dfb2029b2 100644
--- a/coin_test_instructions.py
+++ b/coin_test_instructions.py
@@ -106,8 +106,17 @@ def call_testrunner(python_ver, buildnro):
# Try to install built wheels, and build some buildable examples.
if CI_RELEASE_CONF:
wheel_tester_path = os.path.join("testing", "wheel_tester.py")
+ # Run the test for the old set of wheels
cmd = [env_python, wheel_tester_path, qmake_path]
- run_instruction(cmd, "Error while running wheel_tester.py")
+ run_instruction(cmd, "Error while running wheel_tester.py on old wheels")
+
+ # Uninstalling the other wheels
+ run_instruction([env_pip, "uninstall", "shiboken6", "shiboken6_generator", "pyside6", "-y"],
+ "Failed to uninstall old wheels")
+
+ # Run the test for the new set of wheels
+ cmd = [env_python, wheel_tester_path, qmake_path, "--wheels-dir=dist_new", "--new"]
+ run_instruction(cmd, "Error while running wheel_tester.py on new wheels")
def run_test_instructions():
# Remove some environment variables that impact cmake
diff --git a/create_wheels.py b/create_wheels.py
new file mode 100644
index 000000000..ff350f451
--- /dev/null
+++ b/create_wheels.py
@@ -0,0 +1,417 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+import os
+import platform
+import sys
+from argparse import ArgumentParser, Namespace
+from dataclasses import dataclass
+from pathlib import Path
+from shutil import copy, rmtree
+from sysconfig import get_config_var
+from typing import List, Optional, Tuple
+
+import build # type: ignore
+from build_scripts.wheel_files import (ModuleData, # type: ignore
+ wheel_files_pyside_addons,
+ wheel_files_pyside_essentials)
+
+
+@dataclass
+class SetupData:
+ name: str
+ version: str
+ description: str
+ long_description: str
+ console_scripts: List[str]
+
+
+def get_version_from_package(name: str) -> str:
+ # Get version from the already configured '__init__.py' file
+ version = ""
+ with open(package_path / name / "__init__.py") as f:
+ for line in f:
+ if line.strip().startswith("__version__"):
+ version = line.split("=")[1].strip().replace('"', "")
+ break
+ return version
+
+
+def get_manifest(wheel_name: str, data: List[ModuleData]) -> str:
+ lines = []
+
+ for module in data:
+ # It's crucial to have this adjust method here
+ # because it include all the necessary modifications to make
+ # our soltuion work on the three main platforms.
+ module.adjusts_paths_and_extensions()
+
+ for field in module.get_fields():
+ if field == "name":
+ lines.append(f"# {getattr(module, field)}")
+ continue
+ if field == "ext":
+ continue
+ for line in getattr(module, field):
+ if field in ("examples", "extra_dirs", "qml", "plugins"):
+ lines.append(f"graft PySide6/{line}")
+ elif field == "qtlib" and sys.platform == "darwin":
+ lines.append(f"graft PySide6/{line}")
+ else:
+ lines.append(f"include PySide6/{line}")
+ lines.append("recursive-exclude PySide6 *qt.conf*")
+ lines.append("")
+
+ # Skip certain files if needed
+ lines.append("recursive-exclude PySide6/Qt/qml *.debug")
+
+ return "\n".join(lines)
+
+
+def generate_setup_cfg(artifacts: Path, setup: SetupData) -> str:
+ content = None
+ _os = sys.platform
+ arch = platform.machine()
+
+ # as Qt6 we know it's GLIBC 2.28 on RHEL 8.4
+ _tag = ""
+ if _os == "linux":
+ glibc = platform.libc_ver()[1].replace(".", "_")
+ # Will generate manylinux_2_28_x86_64
+ _tag = f"manylinux_{glibc}_{arch}"
+ elif _os == "darwin":
+ target = get_config_var("MACOSX_DEPLOYMENT_TARGET")
+ if not target:
+ print("Error: couldn't get the value from MACOSX_DEPLOYMENT_TARGET. "
+ "Falling back to local platform version.")
+ mac_ver, _, _ = platform.mac_ver()
+ # We get 10.14.2 for example, and transform into 10_14
+ target = "_".join(mac_ver.split(".")[:2])
+ else:
+ version = target.split(".")
+ if len(version) > 1:
+ target = "_".join(version)
+ else:
+ target = f"{version[0]}_0"
+ # TODO: Make it general
+ # To check if is compatible with 64bit on multi-arch systems
+ # is_64bits = sys.maxsize > 2**32
+ #
+ # We know the CI builds universal2 wheels
+ _tag = f"macosx_{target}_universal2"
+ elif _os == "win32":
+ win_arch = platform.architecture()[0]
+ msvc_arch = "x86" if win_arch.startswith("32") else "amd64"
+ _tag = f"win_{msvc_arch}"
+
+ with open(artifacts / "setup.cfg.base") as f:
+ content = f.read().format(
+ name=setup.name,
+ version=setup.version,
+ description=setup.description,
+ long_description=setup.long_description,
+ tag=_tag,
+ )
+
+ return content
+
+
+def generate_setup_py(artifacts: Path, setup: SetupData):
+ content = None
+ _name = setup.name
+
+ # To get the 'abi3' tag on the wheel name, we need to use
+ # a fake extension to activate the limited-api option.
+ # Because of the order of copying, we will use a name of a real
+ # module for each package, so it gets overwrited.
+ if _name == "PySide6":
+ fext = "PySide6/QtCore"
+ elif _name == "PySide6_Addons":
+ fext = "PySide6/Qt3DCore"
+ else:
+ fext = "Shiboken"
+
+ # Installing dependencies
+ install_requires = []
+ if name == "PySide6":
+ install_requires.append(f"shiboken6=={setup.version}")
+ install_requires.append(f"PySide6_Essentials=={setup.version}")
+ install_requires.append(f"PySide6_Addons=={setup.version}")
+ elif _name == "PySide6_Essentials":
+ install_requires.append(f"shiboken6=={setup.version}")
+ elif _name == "PySide6_Addons":
+ install_requires.append(f"shiboken6=={setup.version}")
+ install_requires.append(f"PySide6_Essentials=={setup.version}")
+
+ # For special wheels based on 'PySide6'
+ # we force the name to be PySide6 for the package_name,
+ # so we can take the files from that packaged-directory
+ if setup.name in ("PySide6_Essentials", "PySide6_Addons"):
+ _name = "PySide6"
+
+ with open(artifacts / "setup.py.base") as f:
+ content = f.read().format(
+ name=_name,
+ fake_ext=fext,
+ install=install_requires,
+ console_scripts={"console_scripts": setup.console_scripts},
+ )
+
+ return content
+
+
+def wheel_shiboken_generator() -> Tuple[SetupData, None]:
+ setup = SetupData(
+ name="shiboken6_generator",
+ version=get_version_from_package("shiboken6_generator"),
+ description="Python/C++ bindings generator",
+ long_description="README.shiboken6-generator.md",
+ console_scripts=[
+ "shiboken6 = shiboken6_generator.scripts.shiboken_tool:main",
+ "shiboken6-genpyi = shiboken6_generator.scripts.shiboken_tool:genpyi",
+ ],
+ )
+
+ return setup, None
+
+
+def wheel_shiboken_module() -> Tuple[SetupData, None]:
+ setup = SetupData(
+ name="shiboken6",
+ version=get_version_from_package("shiboken6"),
+ description="Python/C++ bindings helper module",
+ long_description="README.shiboken6.md",
+ console_scripts=[],
+ )
+
+ return setup, None
+
+
+def wheel_pyside6_essentials() -> Tuple[SetupData, List[ModuleData]]:
+ setup = SetupData(
+ name="PySide6_Essentials",
+ version=get_version_from_package("PySide6"), # we use 'PySide6' here
+ description="Python bindings for the Qt cross-platform application and UI framework (Essentials)",
+ long_description="README.pyside6_essentials.md",
+ console_scripts=[
+ "pyside6-uic = PySide6.scripts.pyside_tool:uic",
+ "pyside6-rcc = PySide6.scripts.pyside_tool:rcc",
+ "pyside6-assistant = PySide6.scripts.pyside_tool:assistant",
+ "pyside6-designer= PySide6.scripts.pyside_tool:designer",
+ "pyside6-linguist = PySide6.scripts.pyside_tool:linguist",
+ "pyside6-lupdate = PySide6.scripts.pyside_tool:lupdate",
+ "pyside6-lrelease = PySide6.scripts.pyside_tool:lrelease",
+ "pyside6-genpyi = PySide6.scripts.pyside_tool:genpyi",
+ "pyside6-metaobjectdump = PySide6.scripts.pyside_tool:metaobjectdump",
+ "pyside6-qmltyperegistrar = PySide6.scripts.pyside_tool:qmltyperegistrar",
+ "pyside6-qmllint = PySide6.scripts.pyside_tool:qmllint",
+ ],
+ )
+
+ data = wheel_files_pyside_essentials()
+
+ return setup, data
+
+
+def wheel_pyside6_addons() -> Tuple[SetupData, List[ModuleData]]:
+ setup = SetupData(
+ name="PySide6_Addons",
+ version=get_version_from_package("PySide6"), # we use 'PySide6' here
+ description="Python bindings for the Qt cross-platform application and UI framework (Addons)",
+ long_description="README.pyside6_addons.md",
+ console_scripts=[],
+ )
+
+ data = wheel_files_pyside_addons()
+
+ return setup, data
+
+
+def wheel_pyside6() -> Tuple[SetupData, Optional[List[ModuleData]]]:
+ setup = SetupData(
+ name="PySide6",
+ version=get_version_from_package("PySide6"),
+ description="Python bindings for the Qt cross-platform application and UI framework",
+ long_description="README.pyside6.md",
+ console_scripts=[],
+ )
+
+ return setup, None
+
+
+def get_build_directory(options: Namespace):
+ _venv = ""
+ _directories = list(Path("build").glob("qfp*"))
+ # Search for a "--env" option first"
+ if options.env is not None:
+ _venv = f"{options.env}a"
+ # Search for a 'qfp' directory second
+ elif _directories and len(_directories) > 0:
+ # Take the first 'qfp' directory
+ _venv = _directories[0].name
+ # Fall back to the virtual environment name
+ else:
+ # Check if we are using a virtual environment
+ try:
+ _venv = os.environ["VIRTUAL_ENV"]
+ if not _venv:
+ raise Exception("No virtual environment found")
+ _venv = f"{_venv}a"
+ except Exception as e:
+ print(f"{type(e).__name__} : {e}")
+ sys.exit(-1)
+
+ return Path(_venv)
+
+
+if __name__ == "__main__":
+
+ # Command line option to find the build/<envname>a/package_for_wheels
+ parser = ArgumentParser()
+ parser.add_argument("--env", type=str, default=None)
+ options = parser.parse_args()
+
+ venv = get_build_directory(options)
+
+ verbose = False
+ # Setup paths
+ current_path = Path(__file__).resolve().parent
+ artifacts_path = Path("wheel_artifacts/")
+ # the extra 'a' is for compatibility with the build_scripts
+ # notation that adds an 'a' when using limited-api
+ package_path = Path("build") / venv.name / "package_for_wheels"
+
+ # Check for 'package_for_wheels' directory
+ if not package_path.is_dir():
+ print(f"Couldn't find the directory: {package_path}")
+ print("Maybe your build used '--skip-packaging'?. Exiting")
+ sys.exit(-1)
+
+ setup_cfg_path = package_path / "setup.cfg"
+ setup_py_path = package_path / "setup.py"
+
+ base_files = [
+ artifacts_path / "pyproject.toml",
+ current_path / "LICENSE.COMMERCIAL",
+ current_path / "LICENSE.FDL",
+ current_path / "LICENSE.GPL2",
+ current_path / "LICENSE.GPLv3",
+ current_path / "LICENSE.GPLv3-EXCEPT",
+ current_path / "LICENSE.LGPLv3",
+ ]
+
+ # Main generation
+ wheels = {
+ "shiboken6": wheel_shiboken_module,
+ "shiboken6_generator": wheel_shiboken_generator,
+ "PySide6_Essentials": wheel_pyside6_essentials,
+ "PySide6_Addons": wheel_pyside6_addons,
+ "PySide6": wheel_pyside6,
+ }
+
+ for name, wheel_info in wheels.items():
+
+ print(f"Starting process for: {name}")
+ setup, data = wheel_info()
+
+ # 1. Generate 'setup.cfg'
+ print("-- Generating setup.cfg")
+ setup_cfg_content = generate_setup_cfg(artifacts_path, setup)
+ with open(setup_cfg_path, "w") as f:
+ f.write(setup_cfg_content)
+
+ # 2. Generate 'setup.py'
+ print("-- Generating setup.py")
+ setup_py_content = generate_setup_py(artifacts_path, setup)
+ with open(setup_py_path, "w") as f:
+ f.write(setup_py_content)
+
+ # 3. Create the 'MANIFEST.in'
+ # Special case for shiboken and shiboken_generator
+ # so we copy the whole directory, only PySide and derivatives
+ # will need to have specific information
+ print("-- Creating MANIFEST.in")
+ if not data:
+ if name == "PySide6":
+ with open(package_path / "MANIFEST.in", "w") as f:
+ f.write(f"purge {name}\n")
+ else:
+ with open(package_path / "MANIFEST.in", "w") as f:
+ f.write(f"graft {name}\n")
+ else:
+ manifest_content = get_manifest(name, data)
+ with open(package_path / "MANIFEST.in", "w") as f:
+ f.write(manifest_content)
+
+ # 4. copy configuration files to create the wheel
+ print("-- Copy configuration files to create the wheel")
+ _files: List[Path] = base_files + [Path(setup.long_description)]
+ for fname in _files:
+ copy(fname, package_path)
+
+ # 5. call the build module to create the wheel
+ # print("-- Creating wheel")
+ # os.chdir(package_path)
+ if not verbose:
+ _runner = build.pep517.wrappers.quiet_subprocess_runner
+ else:
+ _runner = build.pep517.wrappers.default_subprocess_runner
+ builder = build.ProjectBuilder(package_path, runner=_runner)
+ builder.build("wheel", "dist_new")
+ # os.chdir(current_path)
+
+ # 6. Copy wheels back
+ print("-- Copying wheels to dist_new/")
+ dist_path = Path("dist_new")
+ if not dist_path.is_dir():
+ dist_path.mkdir()
+ for wheel in Path(package_path / "dist_new").glob("*.whl"):
+ copy(wheel, dist_path / wheel.name)
+
+ # 7. Remove leftover files
+ print("-- Removing leftover files")
+ all_files = set(package_path.glob("*"))
+ files_to_remove = all_files - {
+ package_path / i for i in ("PySide6", "shiboken6", "shiboken6_generator")
+ }
+ for _f in files_to_remove:
+ if _f.is_dir():
+ rmtree(_f)
+ elif _f.is_file():
+ _f.unlink()
diff --git a/requirements.txt b/requirements.txt
index a2b45fbc5..e1671d0d9 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
setuptools>=48.0
+build==0.7
sphinx
sphinx-panels
six
@@ -6,3 +7,4 @@ wheel>=0.35
PyOpenGL
pyinstaller==3.6
nuitka
+dataclasses; python_version < '3.7'
diff --git a/testing/wheel_tester.py b/testing/wheel_tester.py
index db36aa45e..c97647861 100644
--- a/testing/wheel_tester.py
+++ b/testing/wheel_tester.py
@@ -76,6 +76,7 @@ import platform
log.set_verbosity(1)
+NEW_WHEELS = False
def find_executable(executable, command_line_value):
value = command_line_value
@@ -104,8 +105,8 @@ QMAKE_PATH = None
CMAKE_PATH = None
-def get_wheels_dir():
- return os.path.join(setup_script_dir, "dist")
+def get_wheels_dir(dir_name):
+ return os.path.join(setup_script_dir, dir_name)
def get_examples_dir():
@@ -115,7 +116,10 @@ def get_examples_dir():
def package_prefix_names():
# Note: shiboken6_generator is not needed for compile_using_nuitka,
# but building modules with cmake needs it.
- return ["shiboken6", "shiboken6_generator", "PySide6"]
+ if NEW_WHEELS:
+ return ["shiboken6", "shiboken6_generator", "PySide6_Essentials", "PySide6_Addons", "PySide6"]
+ else:
+ return ["shiboken6", "shiboken6_generator", "PySide6"]
def clean_egg_info():
@@ -334,8 +338,8 @@ def try_build_examples():
execute_script(src_path / f"{modname}.pyi")
-def run_wheel_tests(install_wheels):
- wheels_dir = get_wheels_dir()
+def run_wheel_tests(install_wheels, wheels_dir_name):
+ wheels_dir = get_wheels_dir(wheels_dir_name)
py_version = f"{sys.version_info.major}.{sys.version_info.minor}"
if install_wheels:
@@ -358,8 +362,11 @@ if __name__ == "__main__":
)
parser.add_argument("--qmake", type=str, help="Path to qmake")
parser.add_argument("--cmake", type=str, help="Path to cmake")
+ parser.add_argument("--wheels-dir", type=str, help="Path to where the wheels are", default="dist")
+ parser.add_argument("--new", action="store_true", help="Option to test new wheels")
options = parser.parse_args()
QMAKE_PATH = find_executable("qmake", options.qmake)
CMAKE_PATH = find_executable("cmake", options.cmake)
+ NEW_WHEELS = options.new
- run_wheel_tests(not options.no_install_wheels)
+ run_wheel_tests(not options.no_install_wheels, options.wheels_dir)
diff --git a/wheel_artifacts/pyproject.toml b/wheel_artifacts/pyproject.toml
new file mode 100644
index 000000000..9787c3bdf
--- /dev/null
+++ b/wheel_artifacts/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["setuptools", "wheel"]
+build-backend = "setuptools.build_meta"
diff --git a/wheel_artifacts/setup.cfg.base b/wheel_artifacts/setup.cfg.base
new file mode 100644
index 000000000..9c8b60940
--- /dev/null
+++ b/wheel_artifacts/setup.cfg.base
@@ -0,0 +1,52 @@
+[metadata]
+name = {name}
+version = {version}
+description = {description}
+url = https://www.pyside.org
+download_url = https://download.qt.io/official_releases/QtForPython
+license = LGPL
+keywords = Qt
+author = Qt for Python Team
+author_email = pyside@qt-project.org
+long_description = file: {long_description}
+long_description_content_type = text/markdown
+ext_modules = None
+projects_urls =
+ Bug Tracker = https://bugreports.qt.io
+classifiers =
+ Development Status :: 5 - Production/Stable
+ Environment :: Console
+ Environment :: MacOS X
+ Environment :: X11 Applications :: Qt
+ Environment :: Win32 (MS Windows)
+ Intended Audience :: Developers
+ License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
+ License :: Other/Proprietary License
+ Operating System :: MacOS :: MacOS X
+ Operating System :: POSIX
+ Operating System :: POSIX :: Linux
+ Operating System :: Microsoft
+ Operating System :: Microsoft :: Windows
+ Programming Language :: C++
+ Programming Language :: Python
+ Programming Language :: Python :: 3
+ Programming Language :: Python :: 3.6
+ Programming Language :: Python :: 3.7
+ Programming Language :: Python :: 3.8
+ Programming Language :: Python :: 3.9
+ Programming Language :: Python :: 3.10
+ Topic :: Database
+ Topic :: Software Development
+ Topic :: Software Development :: Code Generators
+ Topic :: Software Development :: Libraries :: Application Frameworks
+ Topic :: Software Development :: User Interfaces
+ Topic :: Software Development :: Widget Sets
+
+[options]
+packages = find:
+python_requires = >=3.6, <3.11
+include_package_data = True
+
+[bdist_wheel]
+py_limited_api = cp36
+plat_name = {tag}
diff --git a/wheel_artifacts/setup.py.base b/wheel_artifacts/setup.py.base
new file mode 100644
index 000000000..18634cbf8
--- /dev/null
+++ b/wheel_artifacts/setup.py.base
@@ -0,0 +1,29 @@
+import setuptools
+from setuptools import setup, Extension
+from setuptools._distutils import cmd
+
+# This class and Extension file is intended only to force setuptools
+# to understand we are using extension modules, but because we don't
+# include the source files in the 'Extension' object, it gets wrongly
+# lost.
+class build_ext(cmd.Command):
+ def initialize_options(self):
+ pass
+ def finalize_options(self):
+ pass
+ def run(self):
+ pass
+ def get_source_files(self):
+ return []
+ def get_requires_for_build_wheel(self):
+ pass
+
+setup_args = dict(
+ include_package_data=True,
+ packages = ["{name}"],
+ entry_points = {console_scripts},
+ ext_modules = [Extension("{fake_ext}", [], py_limited_api=True)],
+ install_requires={install},
+ cmdclass=dict([("build_ext", build_ext)]),
+)
+setup(**setup_args)