diff mbox series

[v2,1/1] added python-pyside6 recipe

Message ID 20240726192904.234263-1-dylan.bespalko@gmail.com
State Changes Requested, archived
Headers show
Series [v2,1/1] added python-pyside6 recipe | expand

Commit Message

Dylan Bespalko July 26, 2024, 7:29 p.m. UTC
The Shiboken6 C++/Python binding generator and the PySide6
binding of the Qt6 C++ project is added. All PySide6 modules
are supported except:
  - PySide6.QtUITools is blocked by a build error in QtUITools
  - PySide.QtOpenGLWidgets runs, but cannot be tested in QEMU.
  - PySide6.QtQuickTest runs, but never passes any tests. 

1. Since Shiboken6 and PySide6 are in the same git repo, I needed
to re-implement the *_CONFIGURE_CMDS to navigate to a sub-directory
in the git repo. Two separate buildroot package recipes were needed
because:
  a) host-python-shiboken6 is needed, but not host-python-pyside6.
  b) PyQt also separates python-sip from python-pyqt.

2. Although PySide6 is a python-package, the Qt Company recommends
using the cmake-package build-system for package managers.

Signed-off-by: Dylan Bespalko <dylan.bespalko@gmail.com>
---
Changes v1 -> v2:
  - nothing. Made sure git send-email sends the commit message above.

 DEVELOPERS                                    |   4 +
 package/Config.in                             |   2 +
 package/python-pyside6/Config.in              |  19 ++
 package/python-pyside6/python-pyside6.hash    |  10 ++
 package/python-pyside6/python-pyside6.mk      | 123 +++++++++++++
 package/python-shiboken6/Config.in            |  24 +++
 .../python-shiboken6/python-shiboken6.hash    |  10 ++
 package/python-shiboken6/python-shiboken6.mk  | 137 +++++++++++++++
 .../tests/package/sample_python_pyside6.py    | 165 ++++++++++++++++++
 .../tests/package/test_python_pyside6.py      |  60 +++++++
 10 files changed, 554 insertions(+)
 create mode 100644 package/python-pyside6/Config.in
 create mode 100644 package/python-pyside6/python-pyside6.hash
 create mode 100644 package/python-pyside6/python-pyside6.mk
 create mode 100644 package/python-shiboken6/Config.in
 create mode 100644 package/python-shiboken6/python-shiboken6.hash
 create mode 100644 package/python-shiboken6/python-shiboken6.mk
 create mode 100644 support/testing/tests/package/sample_python_pyside6.py
 create mode 100644 support/testing/tests/package/test_python_pyside6.py

Comments

Thomas Petazzoni Aug. 3, 2024, 9:55 p.m. UTC | #1
Hello Dylan,

Thanks for your contribution! You are tackling some really difficult
packaging topic for what seems to be your very first Buildroot
contribution!

See below some comments/questions.

First very minor thing: commit message should be:

	package/python-{shiboken6,pyside6}: new packages

On Fri, 26 Jul 2024 12:29:03 -0700
Dylan Bespalko <dylan.bespalko@gmail.com> wrote:

> The Shiboken6 C++/Python binding generator and the PySide6
> binding of the Qt6 C++ project is added. All PySide6 modules
> are supported except:
>   - PySide6.QtUITools is blocked by a build error in QtUITools
>   - PySide.QtOpenGLWidgets runs, but cannot be tested in QEMU.
>   - PySide6.QtQuickTest runs, but never passes any tests. 

You don't have to support everything: if there's something that you
don't use/haven't been able to get to work or test, just disable it,
and leave it up to whoever comes next and needs it.

> 1. Since Shiboken6 and PySide6 are in the same git repo, I needed
> to re-implement the *_CONFIGURE_CMDS to navigate to a sub-directory
> in the git repo. Two separate buildroot package recipes were needed
> because:
>   a) host-python-shiboken6 is needed, but not host-python-pyside6.
>   b) PyQt also separates python-sip from python-pyqt.

I was surprised to see that actually PySide and Shiboken are available
as standalone Git repositories:

  https://code.qt.io/cgit/pyside/pyside.git/
  https://code.qt.io/cgit/pyside/shiboken.git/

but I guess these are the older (Qt 5) versions?

Regarding the re-implementation of the CMake configure command, have
you tried using <pkg>_SUBDIR ? Indeed if you set:

PYTHON_PYSIDE6_SUBDIR = sources/pyside6

then the cmake-package infra CONFIGURE_CMDS will use the CMakeLists.txt
in $(@D)/sources/pyside6/, which should give you want you want, and
would avoid duplicating the configure commands.

> 2. Although PySide6 is a python-package, the Qt Company recommends
> using the cmake-package build-system for package managers.

I was a bit confused by this
because https://code.qt.io/cgit/pyside/pyside-setup.git/tree/README.md#n196 says:

"""
Nevertheless the default build process is done via setup.py, in which case each
of the sub-projects are built and installed separately, as mentioned, the super
project is just for development convenience.
"""

But indeed, https://doc.qt.io/qtforpython-6/gettingstarted/linux.html
says "The setuptools approach includes internal CMake calls when
building and installing the project, but a CMake-only approach is only
recommended for packaging the project for distribution builds."

> diff --git a/DEVELOPERS b/DEVELOPERS
> index 9a8c92f122..b9685b620b 100644
> --- a/DEVELOPERS
> +++ b/DEVELOPERS
> @@ -881,6 +881,10 @@ F:	package/unscd/
>  N:	Dushara Jayasinghe <nidujay@gmail.com>
>  F:	package/prosody/
>  
> +N:      Dylan Bespalko <dylan.bespalko@gmail.com>
> +F:      package/python-shiboken6/
> +F:      package/python-pyside6/

Please use one tab for indentation.


> diff --git a/package/python-pyside6/Config.in b/package/python-pyside6/Config.in
> new file mode 100644
> index 0000000000..b999cadbbb
> --- /dev/null
> +++ b/package/python-pyside6/Config.in
> @@ -0,0 +1,19 @@
> +config BR2_PACKAGE_PYTHON_PYSIDE6
> +	bool "python-pyside6"
> +	depends on BR2_PACKAGE_QT6
> +	depends on BR2_PACKAGE_QT6BASE_GUI

So we can't use pyside6 for a headless system, for which QtGui is not
used/needed?

If yes, then please select BR2_PACKAGE_QT6BASE_GUI, do not use a
depends on.


> diff --git a/package/python-pyside6/python-pyside6.mk b/package/python-pyside6/python-pyside6.mk
> new file mode 100644
> index 0000000000..9db8aad384
> --- /dev/null
> +++ b/package/python-pyside6/python-pyside6.mk
> @@ -0,0 +1,123 @@
> +################################################################################
> +#
> +# python-pyside6
> +#
> +################################################################################
> +
> +PYTHON_PYSIDE6_VERSION = v6.7.2
> +PYTHON_PYSIDE6_SITE = https://code.qt.io/pyside/pyside-setup.git
> +PYTHON_PYSIDE6_SITE_METHOD = git
> +PYTHON_PYSIDE6_CPE_ID_VENDOR = qt
> +PYTHON_PYSIDE6_CPE_ID_PRODUCT = pyside6

Do you have some evidence that does CPE identifiers are correct?

> +PYTHON_PYSIDE6_SUPPORTS_IN_SOURCE_BUILD = NO
> +PYTHON_PYSIDE6_INSTALL_STAGING = YES
> +
> +PYTHON_PYSIDE6_LICENSE = \
> +	GPL-2.0+ or LGPL-3.0, \
> +	GPL-3.0 with exception (tools), \
> +	GFDL-1.3 (docs), \
> +	Apache-2.0, \
> +	BSD-3-Clause
> +
> +PYTHON_PYSIDE6_LICENSE_FILES = \
> +	LICENSES/Apache-2.0.txt \
> +	LICENSES/BSD-3-Clause.txt \
> +	LICENSES/GFDL-1.3-no-invariants-only.txt \
> +	LICENSES/GPL-2.0-only.txt \
> +	LICENSES/LGPL-3.0-only.txt \
> +	LICENSES/GPL-3.0-only.txt \
> +	LICENSES/Qt-GPL-exception-1.0.txt
> +
> +PYTHON_PYSIDE6_DEPENDENCIES = \
> +	host-python-shiboken6 \
> +	qt6base \
> +	python-shiboken6
> +
> +PYTHON_PYSIDE6_ALL_ESSENTIAL_MODULES = \
> +	Core \
> +	Gui \
> +	Widgets \
> +	$(if $(BR2_PACKAGE_QT6BASE_PRINTSUPPORT),PrintSupport) \
> +	$(if $(BR2_PACKAGE_QT6BASE_SQL),Sql) \
> +	$(if $(BR2_PACKAGE_QT6BASE_NETWORK),Network) \
> +	$(if $(BR2_PACKAGE_QT6BASE_TEST),Test) \
> +	$(if $(BR2_PACKAGE_QT6BASE_CONCURRENT),Concurrent)
> +
> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES = \
> +	$(if $(BR2_PACKAGE_QT6BASE_DBUS),DBus) \
> +	$(if $(BR2_PACKAGE_QT6BASE_XML),Xml) \
> +	$(if $(BR2_PACKAGE_QT6BASE_OPENGL),OpenGL) \
> +	$(if $(BR2_PACKAGE_QT6BASE_WIDGETS) && $(BR2_PACKAGE_QT6BASE_OPENGL),OpenGLWidgets)
> +
> +ifeq ($(BR2_PACKAGE_QT6DECLARATIVE),y)
> +PYTHON_PYSIDE6_DEPENDENCIES += qt6declarative
> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += \
> +	Qml \
> +	Quick \
> +	QuickControls2 \
> +	QuickTest \
> +	QuickWidgets
> +endif
> +ifeq ($(BR2_PACKAGE_QT6SERIALPORT),y)
> +PYTHON_PYSIDE6_DEPENDENCIES += qt6serialport
> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SerialPort
> +ifeq ($(BR2_PACKAGE_QT6SERIALBUS),y)
> +PYTHON_PYSIDE6_DEPENDENCIES += qt6serialbus
> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SerialBus
> +endif
> +endif
> +ifeq ($(BR2_PACKAGE_QT6SVG),y)
> +PYTHON_PYSIDE6_DEPENDENCIES += qt6svg
> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += Svg
> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SvgWidgets
> +endif
> +#ifeq ($(BR2_PACKAGE_QT6TOOLS),y)  # Failed to find the host tool "Qt6::lconvert".  It is part of the Qt6LinguistTools package
> +#PYTHON_PYSIDE6_DEPENDENCIES += qt6tools
> +#PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += UiTools
> +#endif

Please don't include commented code. Maybe mention which modules are
not enabled, and why.

> +PYTHON_PYSIDE6_ALL_MODULES = $(subst $(space),\;,$(PYTHON_PYSIDE6_ALL_ESSENTIAL_MODULES) $(PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES))

A comment above this would be useful, because I don't quite understand
the difference between "essential modules" and "optional modules", they
end up being all grouped together in this variable.

> +PYTHON_PYSIDE6_CONF_ENV = \
> +	LLVM_INSTALL_DIR=$(HOST_DIR)
> +
> +#Add option -DMODULES=Core\;Gui\;Widgets for minimum build

I don't understand this comment. Could you clarify?

> +PYTHON_PYSIDE6_CONF_CXXFLAGS = $(subst $(space),$(comma),$(TARGET_CXXFLAGS))

This variable is apparently not used anywhere.

> +PYTHON_PYSIDE6_CONF_OPTS = \
> +	-DMODULES=$(PYTHON_PYSIDE6_ALL_MODULES) \
> +	-DQFP_SHIBOKEN_HOST_PATH=$(HOST_DIR) \
> +	-DSTANDALONE=ON \
> +	-DPYSIDE_TREAT_QT_INCLUDE_DIRS_AS_NON_SYSTEM=ON \
> +	-DSHIBOKEN_GENERATOR_EXTRA_FLAGS='\
> +		--compiler-path=$(HOST_DIR)/bin/clang'
> +
> +# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
> +# 2. sed -i s/\$\$(PKG)/PYTHON_PYSIDE6/g
> +# 3. sed -i s/\$\$/\$/g
> +# 4. append $(PYTHON_PYSIDE6_SRCDIR) with sources/shiboken6
> +define PYTHON_PYSIDE6_CONFIGURE_CMDS

As explained above this can probably be avoided by using
PYTHON_PYSIDE6_SUBDIR = sources/pyside6.


> diff --git a/package/python-shiboken6/Config.in b/package/python-shiboken6/Config.in
> new file mode 100644
> index 0000000000..1e42f0edcc
> --- /dev/null
> +++ b/package/python-shiboken6/Config.in
> @@ -0,0 +1,24 @@
> +config BR2_PACKAGE_PYTHON_SHIBOKEN6
> +	bool "python-shiboken6"
> +	depends on BR2_PACKAGE_QT6
> +	depends on BR2_PACKAGE_QT6BASE_GUI

Please select this option, if it's actually really needed.

> +	depends on BR2_PACKAGE_QT6_GL_SUPPORTS  # Requirement of PySide6.QtWidgets, but not QtWidgets
> +	select BR2_PACKAGE_QT6BASE_WIDGETS
> +	select BR2_PACKAGE_QT6BASE_OPENGL
> +	select BR2_PACKAGE_HOST_LIBXSLT
> +	select BR2_PACKAGE_HOST_CLANG
> +	select BR2_PACKAGE_HOST_CMAKE
> +	select BR2_PACKAGE_HOST_PERL
> +	select BR2_PACKAGE_HOST_QT6BASE
> +	select BR2_PACKAGE_HOST_QT6BASE_GUI
> +	select BR2_PACKAGE_HOST_QT6BASE_WIDGETS
> +	select BR2_PACKAGE_HOST_PYTHON3
> +	select BR2_PACKAGE_HOST_PYTHON_NUMPY
> +	select BR2_PACKAGE_HOST_PYTHON_SHIBOKEN6
> +	select BR2_PACKAGE_PYTHON3_ZLIB
> +	select BR2_PACKAGE_PYTHON_NUMPY

I am still confused by what Shiboken does compared to PySide, and why
we need both a target variant of Shiboken and a host variant... and why
numpy is needed for the target.


> +################################################################################
> +#
> +# python-shiboken6
> +#
> +################################################################################
> +
> +PYTHON_SHIBOKEN6_VERSION = v6.7.2

Could you add a comment above this _VERSION field here, and for the
pyside6 package to indicate that they should be updated in sync?

> +PYTHON_SHIBOKEN6_SITE = https://code.qt.io/pyside/pyside-setup.git
> +PYTHON_SHIBOKEN6_SITE_METHOD = git
> +PYTHON_SHIBOKEN6_CPE_ID_VENDOR = qt
> +PYTHON_SHIBOKEN6_CPE_ID_PRODUCT = shiboken
> +PYTHON_SHIBOKEN6_SUPPORTS_IN_SOURCE_BUILD = NO
> +PYTHON_SHIBOKEN6_INSTALL_STAGING = YES
> +
> +PYTHON_SHIBOKEN6_LICENSE = \
> +	GPL-2.0+ or LGPL-3.0, \
> +	GPL-3.0 with exception (tools), \
> +	GFDL-1.3 (docs), \
> +	Apache-2.0, \
> +	BSD-3-Clause
> +
> +PYTHON_SHIBOKEN6_LICENSE_FILES = \
> +	LICENSES/Apache-2.0.txt \
> +	LICENSES/BSD-3-Clause.txt \
> +	LICENSES/GFDL-1.3-no-invariants-only.txt \
> +	LICENSES/GPL-2.0-only.txt \
> +	LICENSES/LGPL-3.0-only.txt \
> +	LICENSES/GPL-3.0-only.txt \
> +	LICENSES/Qt-GPL-exception-1.0.txt
> +
> +PYTHON_SHIBOKEN6_DEPENDENCIES = \
> +	host-libxslt \
> +	host-clang \
> +	host-cmake \
> +	host-perl \
> +	host-qt6base \
> +	host-python3 \
> +	host-python-numpy \
> +	host-python-shiboken6 \
> +	qt6base \
> +	python3 \
> +	python-numpy

It must take a *huge* time to build all those dependencies: Perl,
Python, LLVM, etc...

> +HOST_PYTHON_SHIBOKEN6_DEPENDENCIES = \
> +	host-libxslt \
> +	host-clang \
> +	host-cmake \
> +	host-perl \
> +	host-qt6base \
> +	host-python3 \
> +	host-python-numpy
> +
> +PYTHON_SHIBOKEN6_CONF_OPTS = \
> +	-DQFP_SHIBOKEN_HOST_PATH=$(HOST_DIR) \
> +	-DQFP_PYTHON_HOST_PATH=$(HOST_DIR)/bin/python3
> +
> +HOST_PYTHON_SHIBOKEN6_CONF_OPTS =

Empty, so not needed.

> +# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
> +# 2. sed -i s/\$\$(PKG)/PYTHON_SHIBOKEN6/g
> +# 3. sed -i s/\$\$/\$/g
> +# 4. append $(PYTHON_SHIBOKEN6_SRCDIR) with sources/shiboken6
> +define PYTHON_SHIBOKEN6_CONFIGURE_CMDS

Use SUBDIR if possible.

> +# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
> +# 2. sed -i s/\$\$(PKG)/HOST_PYTHON_SHIBOKEN6/g
> +# 3. sed -i s/\$\$/\$/g
> +# 4. append $(HOST_PYTHON_SHIBOKEN6_SRCDIR) with sources/shiboken6
> +define HOST_PYTHON_SHIBOKEN6_CONFIGURE_CMDS

Likewise.

> diff --git a/support/testing/tests/package/sample_python_pyside6.py b/support/testing/tests/package/sample_python_pyside6.py
> new file mode 100644
> index 0000000000..079cece9d5
> --- /dev/null
> +++ b/support/testing/tests/package/sample_python_pyside6.py

Super, super great idea to have a test case! Please make sure to add
entry in the DEVELOPERS file also for the files added in
support/testing!


> +def test_python_pyside6_qtquicktest():
> +    from PySide6 import QtQuickTest
> +    QtQuickTest.QUICK_TEST_MAIN('/usr/lib/qt6/qml/QtTest/TestCase.qml')
> +    # The directory '/root' does not contain any test files matching 'tst_*.qml'
> +    # 1
> +    # todo: The tests run, but don't pass. I have no experience with this module.

So what happens? You don't check the results?

> +def test_python_pyside6_qtquickwidgets():
> +    from PySide6 import QtWidgets
> +    from PySide6 import QtQuickWidgets
> +    app = QtWidgets.QApplication()
> +    view = QtQuickWidgets.QQuickWidget()
> +    assert(str(view.status()) == 'Status.Null')
> +    view.setSource('/usr/lib/qt6/qml/QtQuick/Controls/Universal/Label.qml')
> +    assert(str(view.status()) == 'Status.Ready')
> +    QtWidgets.QApplication.shutdown(app)
> +
> +
> +def test_python_pyside6_qtserialport():
> +    from PySide6 import QtSerialPort
> +    ser = QtSerialPort.QSerialPort()
> +    ser.setPortName('/dev/ttyUSB0')
> +    assert(ser.portName() == 'ttyUSB0')

Will it work even if ttyUSB0 doesn't exist?

Thanks a lot for this first submission, it already looks really, really
good! Could you reply to the questions above, and work on a v2
addressing the comments?

Thanks again!

Thomas
Dylan Bespalko Aug. 12, 2024, 7:59 a.m. UTC | #2
Hi Thomas,

Thanks for reviewing my code. I have applied all of your changes and
submitted the code under subject:
[PATCH v3 1/1] added package/python-{shiboken6,pyside6}: new packages

This email contains replies to your comments.

 > Hello Dylan,
 >
 > Thanks for your contribution! You are tackling some really difficult
 > packaging topic for what seems to be your very first Buildroot
 > contribution!
 >
 > See below some comments/questions.
 >
 > First very minor thing: commit message should be:
 >
 >       package/python-{shiboken6,pyside6}: new packages
 >
 > On Fri, 26 Jul 2024 12:29:03 -0700
 > Dylan Bespalko <dylan.bespalko@gmail.com> wrote:
 >
 >> The Shiboken6 C++/Python binding generator and the PySide6
 >> binding of the Qt6 C++ project is added. All PySide6 modules
 >> are supported except:
 >>    - PySide6.QtUITools is blocked by a build error in QtUITools
 >>    - PySide.QtOpenGLWidgets runs, but cannot be tested in QEMU.
 >>    - PySide6.QtQuickTest runs, but never passes any tests.
 >
 > You don't have to support everything: if there's something that you
 > don't use/haven't been able to get to work or test, just disable it,
 > and leave it up to whoever comes next and needs it.
 >

I have removed QtUITools and QtQuickTest as they would cause problems
for a downstream user.

 >> 1. Since Shiboken6 and PySide6 are in the same git repo, I needed
 >> to re-implement the *_CONFIGURE_CMDS to navigate to a sub-directory
 >> in the git repo. Two separate buildroot package recipes were needed
 >> because:
 >>    a) host-python-shiboken6 is needed, but not host-python-pyside6.
 >>    b) PyQt also separates python-sip from python-pyqt.
 >
 > I was surprised to see that actually PySide and Shiboken are available
 > as standalone Git repositories:
 >
 >    https://code.qt.io/cgit/pyside/pyside.git/
 >    https://code.qt.io/cgit/pyside/shiboken.git/
 >
 > but I guess these are the older (Qt 5) versions?
 >

Correct they were separate in Qt5. There are actually three projects 
combined in Qt6:
   - Shiboken6
   - PySide6
   - pyside-tools (Not Included): which contains pyside6-uic/pyside6-rcc

 > Regarding the re-implementation of the CMake configure command, have
 > you tried using <pkg>_SUBDIR ? Indeed if you set:
 >
 > PYTHON_PYSIDE6_SUBDIR = sources/pyside6
 >

Thanks! The SUBDIR feature was much needed.

 > then the cmake-package infra CONFIGURE_CMDS will use the CMakeLists.txt
 > in $(@D)/sources/pyside6/, which should give you want you want, and
 > would avoid duplicating the configure commands.
 >
 >> 2. Although PySide6 is a python-package, the Qt Company recommends
 >> using the cmake-package build-system for package managers.
 >
 > I was a bit confused by this
 > because 
https://code.qt.io/cgit/pyside/pyside-setup.git/tree/README.md#n196 says:
 >
 > """
 > Nevertheless the default build process is done via setup.py, in which 
case each
 > of the sub-projects are built and installed separately, as mentioned, 
the super
 > project is just for development convenience.
 > """
 >
 > But indeed, https://doc.qt.io/qtforpython-6/gettingstarted/linux.html
 > says "The setuptools approach includes internal CMake calls when
 > building and installing the project, but a CMake-only approach is only
 > recommended for packaging the project for distribution builds."
 >

While Qt provides a way to build everything using CMake, I have no idea 
how to
combine Python AND C++ builds in Buildroot. Yocto covers this scenario by
allowing you to "inherit" python build settings AND cmake build 
settings. Does buildroot
allow you to define the following? If so, does order matter?

```Makefile
$(eval $(cmake-package))
$(eval $(python-package))
```

Currently, I just create two separate buildroot packages for the C++ and 
Python builds.

 >> diff --git a/DEVELOPERS b/DEVELOPERS
 >> index 9a8c92f122..b9685b620b 100644
 >> --- a/DEVELOPERS
 >> +++ b/DEVELOPERS
 >> @@ -881,6 +881,10 @@ F:      package/unscd/
 >>   N: Dushara Jayasinghe <nidujay@gmail.com>
 >>   F: package/prosody/
 >>
 >> +N:      Dylan Bespalko <dylan.bespalko@gmail.com>
 >> +F:      package/python-shiboken6/
 >> +F:      package/python-pyside6/
 >
 > Please use one tab for indentation.
 >

Done

 >> diff --git a/package/python-pyside6/Config.in 
b/package/python-pyside6/Config.in
 >> new file mode 100644
 >> index 0000000000..b999cadbbb
 >> --- /dev/null
 >> +++ b/package/python-pyside6/Config.in
 >> @@ -0,0 +1,19 @@
 >> +config BR2_PACKAGE_PYTHON_PYSIDE6
 >> +    bool "python-pyside6"
 >> +    depends on BR2_PACKAGE_QT6
 >> +    depends on BR2_PACKAGE_QT6BASE_GUI
 >
 > So we can't use pyside6 for a headless system, for which QtGui is not
 > used/needed?
 >
 > If yes, then please select BR2_PACKAGE_QT6BASE_GUI, do not use a
 > depends on.
 >

I had this wrong. I have "selected" the packages as requested.

 >> diff --git a/package/python-pyside6/python-pyside6.mk 
b/package/python-pyside6/python-pyside6.mk
 >> new file mode 100644
 >> index 0000000000..9db8aad384
 >> --- /dev/null
 >> +++ b/package/python-pyside6/python-pyside6.mk
 >> @@ -0,0 +1,123 @@
 >> 
+################################################################################
 >> +#
 >> +# python-pyside6
 >> +#
 >> 
+################################################################################
 >> +
 >> +PYTHON_PYSIDE6_VERSION = v6.7.2
 >> +PYTHON_PYSIDE6_SITE = https://code.qt.io/pyside/pyside-setup.git
 >> +PYTHON_PYSIDE6_SITE_METHOD = git
 >> +PYTHON_PYSIDE6_CPE_ID_VENDOR = qt
 >> +PYTHON_PYSIDE6_CPE_ID_PRODUCT = pyside6
 >
 > Do you have some evidence that does CPE identifiers are correct?
 >

qt is the correct CPE_ID_VENDER, but there is no CPE_ID_PRODUCT for 
pyside6 or
shiboken6, so I have made my best guess.

 >> +PYTHON_PYSIDE6_SUPPORTS_IN_SOURCE_BUILD = NO
 >> +PYTHON_PYSIDE6_INSTALL_STAGING = YES
 >> +
 >> +PYTHON_PYSIDE6_LICENSE = \
 >> +    GPL-2.0+ or LGPL-3.0, \
 >> +    GPL-3.0 with exception (tools), \
 >> +    GFDL-1.3 (docs), \
 >> +    Apache-2.0, \
 >> +    BSD-3-Clause
 >> +
 >> +PYTHON_PYSIDE6_LICENSE_FILES = \
 >> +    LICENSES/Apache-2.0.txt \
 >> +    LICENSES/BSD-3-Clause.txt \
 >> +    LICENSES/GFDL-1.3-no-invariants-only.txt \
 >> +    LICENSES/GPL-2.0-only.txt \
 >> +    LICENSES/LGPL-3.0-only.txt \
 >> +    LICENSES/GPL-3.0-only.txt \
 >> +    LICENSES/Qt-GPL-exception-1.0.txt
 >> +
 >> +PYTHON_PYSIDE6_DEPENDENCIES = \
 >> +    host-python-shiboken6 \
 >> +    qt6base \
 >> +    python-shiboken6
 >> +
 >> +PYTHON_PYSIDE6_ALL_ESSENTIAL_MODULES = \
 >> +    Core \
 >> +    Gui \
 >> +    Widgets \
 >> +    $(if $(BR2_PACKAGE_QT6BASE_PRINTSUPPORT),PrintSupport) \
 >> +    $(if $(BR2_PACKAGE_QT6BASE_SQL),Sql) \
 >> +    $(if $(BR2_PACKAGE_QT6BASE_NETWORK),Network) \
 >> +    $(if $(BR2_PACKAGE_QT6BASE_TEST),Test) \
 >> +    $(if $(BR2_PACKAGE_QT6BASE_CONCURRENT),Concurrent)
 >> +
 >> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES = \
 >> +    $(if $(BR2_PACKAGE_QT6BASE_DBUS),DBus) \
 >> +    $(if $(BR2_PACKAGE_QT6BASE_XML),Xml) \
 >> +    $(if $(BR2_PACKAGE_QT6BASE_OPENGL),OpenGL) \
 >> +    $(if $(BR2_PACKAGE_QT6BASE_WIDGETS) && 
$(BR2_PACKAGE_QT6BASE_OPENGL),OpenGLWidgets)
 >> +
 >> +ifeq ($(BR2_PACKAGE_QT6DECLARATIVE),y)
 >> +PYTHON_PYSIDE6_DEPENDENCIES += qt6declarative
 >> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += \
 >> +    Qml \
 >> +    Quick \
 >> +    QuickControls2 \
 >> +    QuickTest \
 >> +    QuickWidgets
 >> +endif
 >> +ifeq ($(BR2_PACKAGE_QT6SERIALPORT),y)
 >> +PYTHON_PYSIDE6_DEPENDENCIES += qt6serialport
 >> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SerialPort
 >> +ifeq ($(BR2_PACKAGE_QT6SERIALBUS),y)
 >> +PYTHON_PYSIDE6_DEPENDENCIES += qt6serialbus
 >> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SerialBus
 >> +endif
 >> +endif
 >> +ifeq ($(BR2_PACKAGE_QT6SVG),y)
 >> +PYTHON_PYSIDE6_DEPENDENCIES += qt6svg
 >> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += Svg
 >> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SvgWidgets
 >> +endif
 >> +#ifeq ($(BR2_PACKAGE_QT6TOOLS),y)  # Failed to find the host tool 
"Qt6::lconvert".  It is part of the Qt6LinguistTools package
 >> +#PYTHON_PYSIDE6_DEPENDENCIES += qt6tools
 >> +#PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += UiTools
 >> +#endif
 >
 > Please don't include commented code. Maybe mention which modules are
 > not enabled, and why.
 >

Commented code has been removed

 >> +PYTHON_PYSIDE6_ALL_MODULES = $(subst 
$(space),\;,$(PYTHON_PYSIDE6_ALL_ESSENTIAL_MODULES) 
$(PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES))
 >
 > A comment above this would be useful, because I don't quite understand
 > the difference between "essential modules" and "optional modules", they
 > end up being all grouped together in this variable.
 >
 >> +PYTHON_PYSIDE6_CONF_ENV = \
 >> +    LLVM_INSTALL_DIR=$(HOST_DIR)
 >> +
 >> +#Add option -DMODULES=Core\;Gui\;Widgets for minimum build
 >
 > I don't understand this comment. Could you clarify?
 >

I added detailed comments to explain these three variables. I mostly
named them in a way that allows me to grep for new modules for easier
maintenance when Qt6 modules are added.

```Makefile
+# Essential Modules: grep -A 8 -r "set(ALL_ESSENTIAL_MODULES" on repo
+PYTHON_PYSIDE6_ALL_ESSENTIAL_MODULES = \
...
+# Add-On Modules: grep -A 33 -r "set(ALL_OPTIONAL_MODULES" on repo
+PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES = \
...
+# All Modules: grep -r "set(MODULES" on repo for updated list
+# The Modules are defined here: https://doc.qt.io/qt-6/qtmodules.html
+PYTHON_PYSIDE6_MODULES = ...
```

 >> +PYTHON_PYSIDE6_CONF_CXXFLAGS = $(subst 
$(space),$(comma),$(TARGET_CXXFLAGS))
 >
 > This variable is apparently not used anywhere.
 >

Removed

 >> +PYTHON_PYSIDE6_CONF_OPTS = \
 >> +    -DMODULES=$(PYTHON_PYSIDE6_ALL_MODULES) \
 >> +    -DQFP_SHIBOKEN_HOST_PATH=$(HOST_DIR) \
 >> +    -DSTANDALONE=ON \
 >> +    -DPYSIDE_TREAT_QT_INCLUDE_DIRS_AS_NON_SYSTEM=ON \
 >> +    -DSHIBOKEN_GENERATOR_EXTRA_FLAGS='\
 >> +            --compiler-path=$(HOST_DIR)/bin/clang'
 >> +
 >> +# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
 >> +# 2. sed -i s/\$\$(PKG)/PYTHON_PYSIDE6/g
 >> +# 3. sed -i s/\$\$/\$/g
 >> +# 4. append $(PYTHON_PYSIDE6_SRCDIR) with sources/shiboken6
 >> +define PYTHON_PYSIDE6_CONFIGURE_CMDS
 >
 > As explained above this can probably be avoided by using
 > PYTHON_PYSIDE6_SUBDIR = sources/pyside6.
 >

Done

 >
 >> diff --git a/package/python-shiboken6/Config.in 
b/package/python-shiboken6/Config.in
 >> new file mode 100644
 >> index 0000000000..1e42f0edcc
 >> --- /dev/null
 >> +++ b/package/python-shiboken6/Config.in
 >> @@ -0,0 +1,24 @@
 >> +config BR2_PACKAGE_PYTHON_SHIBOKEN6
 >> +    bool "python-shiboken6"
 >> +    depends on BR2_PACKAGE_QT6
 >> +    depends on BR2_PACKAGE_QT6BASE_GUI
 >
 > Please select this option, if it's actually really needed.
 >

Selected option instead of depends on

 >> +    depends on BR2_PACKAGE_QT6_GL_SUPPORTS  # Requirement of 
PySide6.QtWidgets, but not QtWidgets
 >> +    select BR2_PACKAGE_QT6BASE_WIDGETS
 >> +    select BR2_PACKAGE_QT6BASE_OPENGL
 >> +    select BR2_PACKAGE_HOST_LIBXSLT
 >> +    select BR2_PACKAGE_HOST_CLANG
 >> +    select BR2_PACKAGE_HOST_CMAKE
 >> +    select BR2_PACKAGE_HOST_PERL
 >> +    select BR2_PACKAGE_HOST_QT6BASE
 >> +    select BR2_PACKAGE_HOST_QT6BASE_GUI
 >> +    select BR2_PACKAGE_HOST_QT6BASE_WIDGETS
 >> +    select BR2_PACKAGE_HOST_PYTHON3
 >> +    select BR2_PACKAGE_HOST_PYTHON_NUMPY
 >> +    select BR2_PACKAGE_HOST_PYTHON_SHIBOKEN6
 >> +    select BR2_PACKAGE_PYTHON3_ZLIB
 >> +    select BR2_PACKAGE_PYTHON_NUMPY
 >
 > I am still confused by what Shiboken does compared to PySide, and why
 > we need both a target variant of Shiboken and a host variant... and why
 > numpy is needed for the target.
 >

Shiboken is a general purpose C++/Python binding generator similar to 
PyBind11 and
Sip/SWIG. It also contains a Shiboken6 module that can debug the binding 
during runtime
on the target device. You can use it for ANY C++ code.

PySide is the result of running the Shiboken binding generator on the 
Qt6 C++ code.

I tested that Numpy is not needed. I have no idea how it got in there. 
Good catch.

 >
 >> 
+################################################################################
 >> +#
 >> +# python-shiboken6
 >> +#
 >> 
+################################################################################
 >> +
 >> +PYTHON_SHIBOKEN6_VERSION = v6.7.2
 >
 > Could you add a comment above this _VERSION field here, and for the
 > pyside6 package to indicate that they should be updated in sync?
 >
Good idea. I have added comments to both PySide6 and Shiboken6 reminding 
the maintainer
to sync with the version of Qt.

 >> +PYTHON_SHIBOKEN6_SITE = https://code.qt.io/pyside/pyside-setup.git
 >> +PYTHON_SHIBOKEN6_SITE_METHOD = git
 >> +PYTHON_SHIBOKEN6_CPE_ID_VENDOR = qt
 >> +PYTHON_SHIBOKEN6_CPE_ID_PRODUCT = shiboken
 >> +PYTHON_SHIBOKEN6_SUPPORTS_IN_SOURCE_BUILD = NO
 >> +PYTHON_SHIBOKEN6_INSTALL_STAGING = YES
 >> +
 >> +PYTHON_SHIBOKEN6_LICENSE = \
 >> +    GPL-2.0+ or LGPL-3.0, \
 >> +    GPL-3.0 with exception (tools), \
 >> +    GFDL-1.3 (docs), \
 >> +    Apache-2.0, \
 >> +    BSD-3-Clause
 >> +
 >> +PYTHON_SHIBOKEN6_LICENSE_FILES = \
 >> +    LICENSES/Apache-2.0.txt \
 >> +    LICENSES/BSD-3-Clause.txt \
 >> +    LICENSES/GFDL-1.3-no-invariants-only.txt \
 >> +    LICENSES/GPL-2.0-only.txt \
 >> +    LICENSES/LGPL-3.0-only.txt \
 >> +    LICENSES/GPL-3.0-only.txt \
 >> +    LICENSES/Qt-GPL-exception-1.0.txt
 >> +
 >> +PYTHON_SHIBOKEN6_DEPENDENCIES = \
 >> +    host-libxslt \
 >> +    host-clang \
 >> +    host-cmake \
 >> +    host-perl \
 >> +    host-qt6base \
 >> +    host-python3 \
 >> +    host-python-numpy \
 >> +    host-python-shiboken6 \
 >> +    qt6base \
 >> +    python3 \
 >> +    python-numpy
 >
 > It must take a *huge* time to build all those dependencies: Perl,
 > Python, LLVM, etc...
 >

I have a *huge* server :)

 >> +HOST_PYTHON_SHIBOKEN6_DEPENDENCIES = \
 >> +    host-libxslt \
 >> +    host-clang \
 >> +    host-cmake \
 >> +    host-perl \
 >> +    host-qt6base \
 >> +    host-python3 \
 >> +    host-python-numpy
 >> +
 >> +PYTHON_SHIBOKEN6_CONF_OPTS = \
 >> +    -DQFP_SHIBOKEN_HOST_PATH=$(HOST_DIR) \
 >> +    -DQFP_PYTHON_HOST_PATH=$(HOST_DIR)/bin/python3
 >> +
 >> +HOST_PYTHON_SHIBOKEN6_CONF_OPTS =
 >
 > Empty, so not needed.
 >

Done

 >> +# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
 >> +# 2. sed -i s/\$\$(PKG)/PYTHON_SHIBOKEN6/g
 >> +# 3. sed -i s/\$\$/\$/g
 >> +# 4. append $(PYTHON_SHIBOKEN6_SRCDIR) with sources/shiboken6
 >> +define PYTHON_SHIBOKEN6_CONFIGURE_CMDS
 >
 > Use SUBDIR if possible.
 >

Done

 >> +# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
 >> +# 2. sed -i s/\$\$(PKG)/HOST_PYTHON_SHIBOKEN6/g
 >> +# 3. sed -i s/\$\$/\$/g
 >> +# 4. append $(HOST_PYTHON_SHIBOKEN6_SRCDIR) with sources/shiboken6
 >> +define HOST_PYTHON_SHIBOKEN6_CONFIGURE_CMDS
 >
 > Likewise.

Done

 >> diff --git a/support/testing/tests/package/sample_python_pyside6.py 
b/support/testing/tests/package/sample_python_pyside6.py
 >> new file mode 100644
 >> index 0000000000..079cece9d5
 >> --- /dev/null
 >> +++ b/support/testing/tests/package/sample_python_pyside6.py
 >
 > Super, super great idea to have a test case! Please make sure to add
 > entry in the DEVELOPERS file also for the files added in
 > support/testing!
 >

Done

 >
 >> +def test_python_pyside6_qtquicktest():
 >> +    from PySide6 import QtQuickTest
 >> +    QtQuickTest.QUICK_TEST_MAIN('/usr/lib/qt6/qml/QtTest/TestCase.qml')
 >> +    # The directory '/root' does not contain any test files 
matching 'tst_*.qml'
 >> +    # 1
 >> +    # todo: The tests run, but don't pass. I have no experience 
with this module.
 >
 > So what happens? You don't check the results?
 >

Not a good test case, removed qtquicktest test case.

 >> +def test_python_pyside6_qtquickwidgets():
 >> +    from PySide6 import QtWidgets
 >> +    from PySide6 import QtQuickWidgets
 >> +    app = QtWidgets.QApplication()
 >> +    view = QtQuickWidgets.QQuickWidget()
 >> +    assert(str(view.status()) == 'Status.Null')
 >> + 
view.setSource('/usr/lib/qt6/qml/QtQuick/Controls/Universal/Label.qml')
 >> +    assert(str(view.status()) == 'Status.Ready')
 >> +    QtWidgets.QApplication.shutdown(app)
 >> +
 >> +
 >> +def test_python_pyside6_qtserialport():
 >> +    from PySide6 import QtSerialPort
 >> +    ser = QtSerialPort.QSerialPort()
 >> +    ser.setPortName('/dev/ttyUSB0')
 >> +    assert(ser.portName() == 'ttyUSB0')
 >
 > Will it work even if ttyUSB0 doesn't exist?

I simplified the test to use "/dev/tty" instead of "/dev/ttyUSB0". Also
added a comment stating that the filepath does not need to exist for the
test to pass. I do not connect the serial port.

Thanks,

Dylan


On 8/3/24 14:55, Thomas Petazzoni wrote:
> Hello Dylan,
> 
> Thanks for your contribution! You are tackling some really difficult
> packaging topic for what seems to be your very first Buildroot
> contribution!
> 
> See below some comments/questions.
> 
> First very minor thing: commit message should be:
> 
> 	package/python-{shiboken6,pyside6}: new packages
> 
> On Fri, 26 Jul 2024 12:29:03 -0700
> Dylan Bespalko <dylan.bespalko@gmail.com> wrote:
> 
>> The Shiboken6 C++/Python binding generator and the PySide6
>> binding of the Qt6 C++ project is added. All PySide6 modules
>> are supported except:
>>    - PySide6.QtUITools is blocked by a build error in QtUITools
>>    - PySide.QtOpenGLWidgets runs, but cannot be tested in QEMU.
>>    - PySide6.QtQuickTest runs, but never passes any tests.
> 
> You don't have to support everything: if there's something that you
> don't use/haven't been able to get to work or test, just disable it,
> and leave it up to whoever comes next and needs it.
> 
>> 1. Since Shiboken6 and PySide6 are in the same git repo, I needed
>> to re-implement the *_CONFIGURE_CMDS to navigate to a sub-directory
>> in the git repo. Two separate buildroot package recipes were needed
>> because:
>>    a) host-python-shiboken6 is needed, but not host-python-pyside6.
>>    b) PyQt also separates python-sip from python-pyqt.
> 
> I was surprised to see that actually PySide and Shiboken are available
> as standalone Git repositories:
> 
>    https://code.qt.io/cgit/pyside/pyside.git/
>    https://code.qt.io/cgit/pyside/shiboken.git/
> 
> but I guess these are the older (Qt 5) versions?
> 
> Regarding the re-implementation of the CMake configure command, have
> you tried using <pkg>_SUBDIR ? Indeed if you set:
> 
> PYTHON_PYSIDE6_SUBDIR = sources/pyside6
> 
> then the cmake-package infra CONFIGURE_CMDS will use the CMakeLists.txt
> in $(@D)/sources/pyside6/, which should give you want you want, and
> would avoid duplicating the configure commands.
> 
>> 2. Although PySide6 is a python-package, the Qt Company recommends
>> using the cmake-package build-system for package managers.
> 
> I was a bit confused by this
> because https://code.qt.io/cgit/pyside/pyside-setup.git/tree/README.md#n196 says:
> 
> """
> Nevertheless the default build process is done via setup.py, in which case each
> of the sub-projects are built and installed separately, as mentioned, the super
> project is just for development convenience.
> """
> 
> But indeed, https://doc.qt.io/qtforpython-6/gettingstarted/linux.html
> says "The setuptools approach includes internal CMake calls when
> building and installing the project, but a CMake-only approach is only
> recommended for packaging the project for distribution builds."
> 
>> diff --git a/DEVELOPERS b/DEVELOPERS
>> index 9a8c92f122..b9685b620b 100644
>> --- a/DEVELOPERS
>> +++ b/DEVELOPERS
>> @@ -881,6 +881,10 @@ F:	package/unscd/
>>   N:	Dushara Jayasinghe <nidujay@gmail.com>
>>   F:	package/prosody/
>>   
>> +N:      Dylan Bespalko <dylan.bespalko@gmail.com>
>> +F:      package/python-shiboken6/
>> +F:      package/python-pyside6/
> 
> Please use one tab for indentation.
> 
> 
>> diff --git a/package/python-pyside6/Config.in b/package/python-pyside6/Config.in
>> new file mode 100644
>> index 0000000000..b999cadbbb
>> --- /dev/null
>> +++ b/package/python-pyside6/Config.in
>> @@ -0,0 +1,19 @@
>> +config BR2_PACKAGE_PYTHON_PYSIDE6
>> +	bool "python-pyside6"
>> +	depends on BR2_PACKAGE_QT6
>> +	depends on BR2_PACKAGE_QT6BASE_GUI
> 
> So we can't use pyside6 for a headless system, for which QtGui is not
> used/needed?
> 
> If yes, then please select BR2_PACKAGE_QT6BASE_GUI, do not use a
> depends on.
> 
> 
>> diff --git a/package/python-pyside6/python-pyside6.mk b/package/python-pyside6/python-pyside6.mk
>> new file mode 100644
>> index 0000000000..9db8aad384
>> --- /dev/null
>> +++ b/package/python-pyside6/python-pyside6.mk
>> @@ -0,0 +1,123 @@
>> +################################################################################
>> +#
>> +# python-pyside6
>> +#
>> +################################################################################
>> +
>> +PYTHON_PYSIDE6_VERSION = v6.7.2
>> +PYTHON_PYSIDE6_SITE = https://code.qt.io/pyside/pyside-setup.git
>> +PYTHON_PYSIDE6_SITE_METHOD = git
>> +PYTHON_PYSIDE6_CPE_ID_VENDOR = qt
>> +PYTHON_PYSIDE6_CPE_ID_PRODUCT = pyside6
> 
> Do you have some evidence that does CPE identifiers are correct?
> 
>> +PYTHON_PYSIDE6_SUPPORTS_IN_SOURCE_BUILD = NO
>> +PYTHON_PYSIDE6_INSTALL_STAGING = YES
>> +
>> +PYTHON_PYSIDE6_LICENSE = \
>> +	GPL-2.0+ or LGPL-3.0, \
>> +	GPL-3.0 with exception (tools), \
>> +	GFDL-1.3 (docs), \
>> +	Apache-2.0, \
>> +	BSD-3-Clause
>> +
>> +PYTHON_PYSIDE6_LICENSE_FILES = \
>> +	LICENSES/Apache-2.0.txt \
>> +	LICENSES/BSD-3-Clause.txt \
>> +	LICENSES/GFDL-1.3-no-invariants-only.txt \
>> +	LICENSES/GPL-2.0-only.txt \
>> +	LICENSES/LGPL-3.0-only.txt \
>> +	LICENSES/GPL-3.0-only.txt \
>> +	LICENSES/Qt-GPL-exception-1.0.txt
>> +
>> +PYTHON_PYSIDE6_DEPENDENCIES = \
>> +	host-python-shiboken6 \
>> +	qt6base \
>> +	python-shiboken6
>> +
>> +PYTHON_PYSIDE6_ALL_ESSENTIAL_MODULES = \
>> +	Core \
>> +	Gui \
>> +	Widgets \
>> +	$(if $(BR2_PACKAGE_QT6BASE_PRINTSUPPORT),PrintSupport) \
>> +	$(if $(BR2_PACKAGE_QT6BASE_SQL),Sql) \
>> +	$(if $(BR2_PACKAGE_QT6BASE_NETWORK),Network) \
>> +	$(if $(BR2_PACKAGE_QT6BASE_TEST),Test) \
>> +	$(if $(BR2_PACKAGE_QT6BASE_CONCURRENT),Concurrent)
>> +
>> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES = \
>> +	$(if $(BR2_PACKAGE_QT6BASE_DBUS),DBus) \
>> +	$(if $(BR2_PACKAGE_QT6BASE_XML),Xml) \
>> +	$(if $(BR2_PACKAGE_QT6BASE_OPENGL),OpenGL) \
>> +	$(if $(BR2_PACKAGE_QT6BASE_WIDGETS) && $(BR2_PACKAGE_QT6BASE_OPENGL),OpenGLWidgets)
>> +
>> +ifeq ($(BR2_PACKAGE_QT6DECLARATIVE),y)
>> +PYTHON_PYSIDE6_DEPENDENCIES += qt6declarative
>> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += \
>> +	Qml \
>> +	Quick \
>> +	QuickControls2 \
>> +	QuickTest \
>> +	QuickWidgets
>> +endif
>> +ifeq ($(BR2_PACKAGE_QT6SERIALPORT),y)
>> +PYTHON_PYSIDE6_DEPENDENCIES += qt6serialport
>> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SerialPort
>> +ifeq ($(BR2_PACKAGE_QT6SERIALBUS),y)
>> +PYTHON_PYSIDE6_DEPENDENCIES += qt6serialbus
>> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SerialBus
>> +endif
>> +endif
>> +ifeq ($(BR2_PACKAGE_QT6SVG),y)
>> +PYTHON_PYSIDE6_DEPENDENCIES += qt6svg
>> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += Svg
>> +PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SvgWidgets
>> +endif
>> +#ifeq ($(BR2_PACKAGE_QT6TOOLS),y)  # Failed to find the host tool "Qt6::lconvert".  It is part of the Qt6LinguistTools package
>> +#PYTHON_PYSIDE6_DEPENDENCIES += qt6tools
>> +#PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += UiTools
>> +#endif
> 
> Please don't include commented code. Maybe mention which modules are
> not enabled, and why.
> 
>> +PYTHON_PYSIDE6_ALL_MODULES = $(subst $(space),\;,$(PYTHON_PYSIDE6_ALL_ESSENTIAL_MODULES) $(PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES))
> 
> A comment above this would be useful, because I don't quite understand
> the difference between "essential modules" and "optional modules", they
> end up being all grouped together in this variable.
> 
>> +PYTHON_PYSIDE6_CONF_ENV = \
>> +	LLVM_INSTALL_DIR=$(HOST_DIR)
>> +
>> +#Add option -DMODULES=Core\;Gui\;Widgets for minimum build
> 
> I don't understand this comment. Could you clarify?
> 
>> +PYTHON_PYSIDE6_CONF_CXXFLAGS = $(subst $(space),$(comma),$(TARGET_CXXFLAGS))
> 
> This variable is apparently not used anywhere.
> 
>> +PYTHON_PYSIDE6_CONF_OPTS = \
>> +	-DMODULES=$(PYTHON_PYSIDE6_ALL_MODULES) \
>> +	-DQFP_SHIBOKEN_HOST_PATH=$(HOST_DIR) \
>> +	-DSTANDALONE=ON \
>> +	-DPYSIDE_TREAT_QT_INCLUDE_DIRS_AS_NON_SYSTEM=ON \
>> +	-DSHIBOKEN_GENERATOR_EXTRA_FLAGS='\
>> +		--compiler-path=$(HOST_DIR)/bin/clang'
>> +
>> +# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
>> +# 2. sed -i s/\$\$(PKG)/PYTHON_PYSIDE6/g
>> +# 3. sed -i s/\$\$/\$/g
>> +# 4. append $(PYTHON_PYSIDE6_SRCDIR) with sources/shiboken6
>> +define PYTHON_PYSIDE6_CONFIGURE_CMDS
> 
> As explained above this can probably be avoided by using
> PYTHON_PYSIDE6_SUBDIR = sources/pyside6.
> 
> 
>> diff --git a/package/python-shiboken6/Config.in b/package/python-shiboken6/Config.in
>> new file mode 100644
>> index 0000000000..1e42f0edcc
>> --- /dev/null
>> +++ b/package/python-shiboken6/Config.in
>> @@ -0,0 +1,24 @@
>> +config BR2_PACKAGE_PYTHON_SHIBOKEN6
>> +	bool "python-shiboken6"
>> +	depends on BR2_PACKAGE_QT6
>> +	depends on BR2_PACKAGE_QT6BASE_GUI
> 
> Please select this option, if it's actually really needed.
> 
>> +	depends on BR2_PACKAGE_QT6_GL_SUPPORTS  # Requirement of PySide6.QtWidgets, but not QtWidgets
>> +	select BR2_PACKAGE_QT6BASE_WIDGETS
>> +	select BR2_PACKAGE_QT6BASE_OPENGL
>> +	select BR2_PACKAGE_HOST_LIBXSLT
>> +	select BR2_PACKAGE_HOST_CLANG
>> +	select BR2_PACKAGE_HOST_CMAKE
>> +	select BR2_PACKAGE_HOST_PERL
>> +	select BR2_PACKAGE_HOST_QT6BASE
>> +	select BR2_PACKAGE_HOST_QT6BASE_GUI
>> +	select BR2_PACKAGE_HOST_QT6BASE_WIDGETS
>> +	select BR2_PACKAGE_HOST_PYTHON3
>> +	select BR2_PACKAGE_HOST_PYTHON_NUMPY
>> +	select BR2_PACKAGE_HOST_PYTHON_SHIBOKEN6
>> +	select BR2_PACKAGE_PYTHON3_ZLIB
>> +	select BR2_PACKAGE_PYTHON_NUMPY
> 
> I am still confused by what Shiboken does compared to PySide, and why
> we need both a target variant of Shiboken and a host variant... and why
> numpy is needed for the target.
> 
> 
>> +################################################################################
>> +#
>> +# python-shiboken6
>> +#
>> +################################################################################
>> +
>> +PYTHON_SHIBOKEN6_VERSION = v6.7.2
> 
> Could you add a comment above this _VERSION field here, and for the
> pyside6 package to indicate that they should be updated in sync?
> 
>> +PYTHON_SHIBOKEN6_SITE = https://code.qt.io/pyside/pyside-setup.git
>> +PYTHON_SHIBOKEN6_SITE_METHOD = git
>> +PYTHON_SHIBOKEN6_CPE_ID_VENDOR = qt
>> +PYTHON_SHIBOKEN6_CPE_ID_PRODUCT = shiboken
>> +PYTHON_SHIBOKEN6_SUPPORTS_IN_SOURCE_BUILD = NO
>> +PYTHON_SHIBOKEN6_INSTALL_STAGING = YES
>> +
>> +PYTHON_SHIBOKEN6_LICENSE = \
>> +	GPL-2.0+ or LGPL-3.0, \
>> +	GPL-3.0 with exception (tools), \
>> +	GFDL-1.3 (docs), \
>> +	Apache-2.0, \
>> +	BSD-3-Clause
>> +
>> +PYTHON_SHIBOKEN6_LICENSE_FILES = \
>> +	LICENSES/Apache-2.0.txt \
>> +	LICENSES/BSD-3-Clause.txt \
>> +	LICENSES/GFDL-1.3-no-invariants-only.txt \
>> +	LICENSES/GPL-2.0-only.txt \
>> +	LICENSES/LGPL-3.0-only.txt \
>> +	LICENSES/GPL-3.0-only.txt \
>> +	LICENSES/Qt-GPL-exception-1.0.txt
>> +
>> +PYTHON_SHIBOKEN6_DEPENDENCIES = \
>> +	host-libxslt \
>> +	host-clang \
>> +	host-cmake \
>> +	host-perl \
>> +	host-qt6base \
>> +	host-python3 \
>> +	host-python-numpy \
>> +	host-python-shiboken6 \
>> +	qt6base \
>> +	python3 \
>> +	python-numpy
> 
> It must take a *huge* time to build all those dependencies: Perl,
> Python, LLVM, etc...
> 
>> +HOST_PYTHON_SHIBOKEN6_DEPENDENCIES = \
>> +	host-libxslt \
>> +	host-clang \
>> +	host-cmake \
>> +	host-perl \
>> +	host-qt6base \
>> +	host-python3 \
>> +	host-python-numpy
>> +
>> +PYTHON_SHIBOKEN6_CONF_OPTS = \
>> +	-DQFP_SHIBOKEN_HOST_PATH=$(HOST_DIR) \
>> +	-DQFP_PYTHON_HOST_PATH=$(HOST_DIR)/bin/python3
>> +
>> +HOST_PYTHON_SHIBOKEN6_CONF_OPTS =
> 
> Empty, so not needed.
> 
>> +# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
>> +# 2. sed -i s/\$\$(PKG)/PYTHON_SHIBOKEN6/g
>> +# 3. sed -i s/\$\$/\$/g
>> +# 4. append $(PYTHON_SHIBOKEN6_SRCDIR) with sources/shiboken6
>> +define PYTHON_SHIBOKEN6_CONFIGURE_CMDS
> 
> Use SUBDIR if possible.
> 
>> +# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
>> +# 2. sed -i s/\$\$(PKG)/HOST_PYTHON_SHIBOKEN6/g
>> +# 3. sed -i s/\$\$/\$/g
>> +# 4. append $(HOST_PYTHON_SHIBOKEN6_SRCDIR) with sources/shiboken6
>> +define HOST_PYTHON_SHIBOKEN6_CONFIGURE_CMDS
> 
> Likewise.
> 
>> diff --git a/support/testing/tests/package/sample_python_pyside6.py b/support/testing/tests/package/sample_python_pyside6.py
>> new file mode 100644
>> index 0000000000..079cece9d5
>> --- /dev/null
>> +++ b/support/testing/tests/package/sample_python_pyside6.py
> 
> Super, super great idea to have a test case! Please make sure to add
> entry in the DEVELOPERS file also for the files added in
> support/testing!
> 
> 
>> +def test_python_pyside6_qtquicktest():
>> +    from PySide6 import QtQuickTest
>> +    QtQuickTest.QUICK_TEST_MAIN('/usr/lib/qt6/qml/QtTest/TestCase.qml')
>> +    # The directory '/root' does not contain any test files matching 'tst_*.qml'
>> +    # 1
>> +    # todo: The tests run, but don't pass. I have no experience with this module.
> 
> So what happens? You don't check the results?
> 
>> +def test_python_pyside6_qtquickwidgets():
>> +    from PySide6 import QtWidgets
>> +    from PySide6 import QtQuickWidgets
>> +    app = QtWidgets.QApplication()
>> +    view = QtQuickWidgets.QQuickWidget()
>> +    assert(str(view.status()) == 'Status.Null')
>> +    view.setSource('/usr/lib/qt6/qml/QtQuick/Controls/Universal/Label.qml')
>> +    assert(str(view.status()) == 'Status.Ready')
>> +    QtWidgets.QApplication.shutdown(app)
>> +
>> +
>> +def test_python_pyside6_qtserialport():
>> +    from PySide6 import QtSerialPort
>> +    ser = QtSerialPort.QSerialPort()
>> +    ser.setPortName('/dev/ttyUSB0')
>> +    assert(ser.portName() == 'ttyUSB0')
> 
> Will it work even if ttyUSB0 doesn't exist?
> 
> Thanks a lot for this first submission, it already looks really, really
> good! Could you reply to the questions above, and work on a v2
> addressing the comments?
> 
> Thanks again!
> 
> Thomas
diff mbox series

Patch

diff --git a/DEVELOPERS b/DEVELOPERS
index 9a8c92f122..b9685b620b 100644
--- a/DEVELOPERS
+++ b/DEVELOPERS
@@ -881,6 +881,10 @@  F:	package/unscd/
 N:	Dushara Jayasinghe <nidujay@gmail.com>
 F:	package/prosody/
 
+N:      Dylan Bespalko <dylan.bespalko@gmail.com>
+F:      package/python-shiboken6/
+F:      package/python-pyside6/
+
 N:	Edgar Bonet <bonet@grenoble.cnrs.fr>
 F:	board/acmesystems/acqua-a5/
 F:	configs/acmesystems_acqua_a5_256mb_defconfig
diff --git a/package/Config.in b/package/Config.in
index 90f1ecc877..2a449c884d 100644
--- a/package/Config.in
+++ b/package/Config.in
@@ -1309,6 +1309,7 @@  menu "External python modules"
 	source "package/python-pysendfile/Config.in"
 	source "package/python-pysensors/Config.in"
 	source "package/python-pysftp/Config.in"
+	source "package/python-pyside6/Config.in"
 	source "package/python-pysmb/Config.in"
 	source "package/python-pysmi/Config.in"
 	source "package/python-pysnmp/Config.in"
@@ -1364,6 +1365,7 @@  menu "External python modules"
 	source "package/python-setproctitle/Config.in"
 	source "package/python-setuptools/Config.in"
 	source "package/python-sh/Config.in"
+	source "package/python-shiboken6/Config.in"
 	source "package/python-shutilwhich/Config.in"
 	source "package/python-simpleaudio/Config.in"
 	source "package/python-simplegeneric/Config.in"
diff --git a/package/python-pyside6/Config.in b/package/python-pyside6/Config.in
new file mode 100644
index 0000000000..b999cadbbb
--- /dev/null
+++ b/package/python-pyside6/Config.in
@@ -0,0 +1,19 @@ 
+config BR2_PACKAGE_PYTHON_PYSIDE6
+	bool "python-pyside6"
+	depends on BR2_PACKAGE_QT6
+	depends on BR2_PACKAGE_QT6BASE_GUI
+	depends on BR2_PACKAGE_QT6_GL_SUPPORTS  # Requirement of PySide6.QtWidgets, but not QtWidgets
+	select BR2_PACKAGE_QT6BASE_WIDGETS
+	select BR2_PACKAGE_QT6BASE_OPENGL
+	select BR2_PACKAGE_OPENSSL  # Requirement of PySide6.QtNetwork, but not QtNetwork
+	select BR2_PACKAGE_HOST_PYTHON_SHIBOKEN6
+	select BR2_PACKAGE_PYTHON_SHIBOKEN6
+	help
+	  Qt For Python is the Python Qt bindings project.
+	  Make sure to select a qpa-platform using:
+	  - BR2_PACKAGE_QT6BASE_DEFAULT_QPA="<qpa-platform>"
+	  - Or, QT_QPA_PLATFORM=<qpa-platform> python3
+
+	  PySide6 auto-detects the Qt6 Modules that are present.
+
+	  https://wiki.qt.io/Qt_for_Python
diff --git a/package/python-pyside6/python-pyside6.hash b/package/python-pyside6/python-pyside6.hash
new file mode 100644
index 0000000000..361ae66124
--- /dev/null
+++ b/package/python-pyside6/python-pyside6.hash
@@ -0,0 +1,10 @@ 
+# Locally computed sha256 checksums
+md5  385a4463908d14cc86d54aac0454e871  python-pyside6-v6.7.2-git4.tar.gz
+sha256  5ddb1bac70c9504d57f31005f4cdf5921c71fbf91190abe22abf45537d725d3b  python-pyside6-v6.7.2-git4.tar.gz
+sha256  9f0490f18656c6f2435bd14f603ef0c96434d1825615363dce43abb42ed1dcce  BSD-3-Clause.txt
+sha256  110535522396708cea37c72a802c5e7e81391139f5f7985631c93ef242b206a4  GFDL-1.3-no-invariants-only.txt
+sha256  8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643  GPL-2.0-only.txt
+sha256  8ceb4b9ee5adedde47b31e975c1d90c73ad27b6b165a1dcd80c7c545eb65b903  GPL-3.0-only.txt
+sha256  da7eabb7bafdf7d3ae5e9f223aa5bdc1eece45ac569dc21b3b037520b4464768  LGPL-3.0-only.txt
+sha256  9b1f50aae6267f9d5e0ceb6775ee86450262c25ec7c0573e151fe5d3f18a4700  LicenseRef-Qt-Commercial.txt
+sha256  40678d338ce53cd93f8b22b281a2ecbcaa3ee65ce60b25ffb0c462b0530846b2  Qt-GPL-exception-1.0.txt
diff --git a/package/python-pyside6/python-pyside6.mk b/package/python-pyside6/python-pyside6.mk
new file mode 100644
index 0000000000..9db8aad384
--- /dev/null
+++ b/package/python-pyside6/python-pyside6.mk
@@ -0,0 +1,123 @@ 
+################################################################################
+#
+# python-pyside6
+#
+################################################################################
+
+PYTHON_PYSIDE6_VERSION = v6.7.2
+PYTHON_PYSIDE6_SITE = https://code.qt.io/pyside/pyside-setup.git
+PYTHON_PYSIDE6_SITE_METHOD = git
+PYTHON_PYSIDE6_CPE_ID_VENDOR = qt
+PYTHON_PYSIDE6_CPE_ID_PRODUCT = pyside6
+PYTHON_PYSIDE6_SUPPORTS_IN_SOURCE_BUILD = NO
+PYTHON_PYSIDE6_INSTALL_STAGING = YES
+
+PYTHON_PYSIDE6_LICENSE = \
+	GPL-2.0+ or LGPL-3.0, \
+	GPL-3.0 with exception (tools), \
+	GFDL-1.3 (docs), \
+	Apache-2.0, \
+	BSD-3-Clause
+
+PYTHON_PYSIDE6_LICENSE_FILES = \
+	LICENSES/Apache-2.0.txt \
+	LICENSES/BSD-3-Clause.txt \
+	LICENSES/GFDL-1.3-no-invariants-only.txt \
+	LICENSES/GPL-2.0-only.txt \
+	LICENSES/LGPL-3.0-only.txt \
+	LICENSES/GPL-3.0-only.txt \
+	LICENSES/Qt-GPL-exception-1.0.txt
+
+PYTHON_PYSIDE6_DEPENDENCIES = \
+	host-python-shiboken6 \
+	qt6base \
+	python-shiboken6
+
+PYTHON_PYSIDE6_ALL_ESSENTIAL_MODULES = \
+	Core \
+	Gui \
+	Widgets \
+	$(if $(BR2_PACKAGE_QT6BASE_PRINTSUPPORT),PrintSupport) \
+	$(if $(BR2_PACKAGE_QT6BASE_SQL),Sql) \
+	$(if $(BR2_PACKAGE_QT6BASE_NETWORK),Network) \
+	$(if $(BR2_PACKAGE_QT6BASE_TEST),Test) \
+	$(if $(BR2_PACKAGE_QT6BASE_CONCURRENT),Concurrent)
+
+PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES = \
+	$(if $(BR2_PACKAGE_QT6BASE_DBUS),DBus) \
+	$(if $(BR2_PACKAGE_QT6BASE_XML),Xml) \
+	$(if $(BR2_PACKAGE_QT6BASE_OPENGL),OpenGL) \
+	$(if $(BR2_PACKAGE_QT6BASE_WIDGETS) && $(BR2_PACKAGE_QT6BASE_OPENGL),OpenGLWidgets)
+
+ifeq ($(BR2_PACKAGE_QT6DECLARATIVE),y)
+PYTHON_PYSIDE6_DEPENDENCIES += qt6declarative
+PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += \
+	Qml \
+	Quick \
+	QuickControls2 \
+	QuickTest \
+	QuickWidgets
+endif
+ifeq ($(BR2_PACKAGE_QT6SERIALPORT),y)
+PYTHON_PYSIDE6_DEPENDENCIES += qt6serialport
+PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SerialPort
+ifeq ($(BR2_PACKAGE_QT6SERIALBUS),y)
+PYTHON_PYSIDE6_DEPENDENCIES += qt6serialbus
+PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SerialBus
+endif
+endif
+ifeq ($(BR2_PACKAGE_QT6SVG),y)
+PYTHON_PYSIDE6_DEPENDENCIES += qt6svg
+PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += Svg
+PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += SvgWidgets
+endif
+#ifeq ($(BR2_PACKAGE_QT6TOOLS),y)  # Failed to find the host tool "Qt6::lconvert".  It is part of the Qt6LinguistTools package
+#PYTHON_PYSIDE6_DEPENDENCIES += qt6tools
+#PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES += UiTools
+#endif
+
+PYTHON_PYSIDE6_ALL_MODULES = $(subst $(space),\;,$(PYTHON_PYSIDE6_ALL_ESSENTIAL_MODULES) $(PYTHON_PYSIDE6_ALL_OPTIONAL_MODULES))
+
+PYTHON_PYSIDE6_CONF_ENV = \
+	LLVM_INSTALL_DIR=$(HOST_DIR)
+
+#Add option -DMODULES=Core\;Gui\;Widgets for minimum build
+PYTHON_PYSIDE6_CONF_CXXFLAGS = $(subst $(space),$(comma),$(TARGET_CXXFLAGS))
+PYTHON_PYSIDE6_CONF_OPTS = \
+	-DMODULES=$(PYTHON_PYSIDE6_ALL_MODULES) \
+	-DQFP_SHIBOKEN_HOST_PATH=$(HOST_DIR) \
+	-DSTANDALONE=ON \
+	-DPYSIDE_TREAT_QT_INCLUDE_DIRS_AS_NON_SYSTEM=ON \
+	-DSHIBOKEN_GENERATOR_EXTRA_FLAGS='\
+		--compiler-path=$(HOST_DIR)/bin/clang'
+
+# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
+# 2. sed -i s/\$\$(PKG)/PYTHON_PYSIDE6/g
+# 3. sed -i s/\$\$/\$/g
+# 4. append $(PYTHON_PYSIDE6_SRCDIR) with sources/shiboken6
+define PYTHON_PYSIDE6_CONFIGURE_CMDS
+	(mkdir -p $(PYTHON_PYSIDE6_BUILDDIR) && \
+	cd $(PYTHON_PYSIDE6_BUILDDIR) && \
+	rm -f CMakeCache.txt && \
+	PATH=$(BR_PATH) \
+	$(PYTHON_PYSIDE6_CONF_ENV) $(BR2_CMAKE) $(PYTHON_PYSIDE6_SRCDIR)/sources/pyside6 \
+		-G$(PYTHON_PYSIDE6_GENERATOR) \
+		-DCMAKE_MAKE_PROGRAM="$(PYTHON_PYSIDE6_GENERATOR_PROGRAM)" \
+		-DCMAKE_TOOLCHAIN_FILE="$(HOST_DIR)/share/buildroot/toolchainfile.cmake" \
+		-DCMAKE_INSTALL_PREFIX="/usr" \
+		-DCMAKE_INSTALL_RUNSTATEDIR="/run" \
+		-DCMAKE_COLOR_MAKEFILE=OFF \
+		-DBUILD_DOC=OFF \
+		-DBUILD_DOCS=OFF \
+		-DBUILD_EXAMPLE=OFF \
+		-DBUILD_EXAMPLES=OFF \
+		-DBUILD_TEST=OFF \
+		-DBUILD_TESTS=OFF \
+		-DBUILD_TESTING=OFF \
+		-DBUILD_SHARED_LIBS=$(if $(BR2_STATIC_LIBS),OFF,ON) \
+		$(CMAKE_QUIET) \
+		$(PYTHON_PYSIDE6_CONF_OPTS) \
+		)
+endef
+
+$(eval $(cmake-package))
diff --git a/package/python-shiboken6/Config.in b/package/python-shiboken6/Config.in
new file mode 100644
index 0000000000..1e42f0edcc
--- /dev/null
+++ b/package/python-shiboken6/Config.in
@@ -0,0 +1,24 @@ 
+config BR2_PACKAGE_PYTHON_SHIBOKEN6
+	bool "python-shiboken6"
+	depends on BR2_PACKAGE_QT6
+	depends on BR2_PACKAGE_QT6BASE_GUI
+	depends on BR2_PACKAGE_QT6_GL_SUPPORTS  # Requirement of PySide6.QtWidgets, but not QtWidgets
+	select BR2_PACKAGE_QT6BASE_WIDGETS
+	select BR2_PACKAGE_QT6BASE_OPENGL
+	select BR2_PACKAGE_HOST_LIBXSLT
+	select BR2_PACKAGE_HOST_CLANG
+	select BR2_PACKAGE_HOST_CMAKE
+	select BR2_PACKAGE_HOST_PERL
+	select BR2_PACKAGE_HOST_QT6BASE
+	select BR2_PACKAGE_HOST_QT6BASE_GUI
+	select BR2_PACKAGE_HOST_QT6BASE_WIDGETS
+	select BR2_PACKAGE_HOST_PYTHON3
+	select BR2_PACKAGE_HOST_PYTHON_NUMPY
+	select BR2_PACKAGE_HOST_PYTHON_SHIBOKEN6
+	select BR2_PACKAGE_PYTHON3_ZLIB
+	select BR2_PACKAGE_PYTHON_NUMPY
+	help
+	  Shiboken generates bindings for C++ libraries using
+	  CPython source code
+
+	  https://wiki.qt.io/Qt_for_Python
diff --git a/package/python-shiboken6/python-shiboken6.hash b/package/python-shiboken6/python-shiboken6.hash
new file mode 100644
index 0000000000..d6f479a477
--- /dev/null
+++ b/package/python-shiboken6/python-shiboken6.hash
@@ -0,0 +1,10 @@ 
+# Locally computed sha256 checksums
+md5  0bc8a2fcc8ab4c31711b7c6e1254dae8  python-shiboken6-v6.7.2-git4.tar.gz
+sha256  586a245db884a4d020f696b985d3afee0b81f11cc3aeeb62aa2c4632d43f4e67  python-shiboken6-v6.7.2-git4.tar.gz
+sha256  9f0490f18656c6f2435bd14f603ef0c96434d1825615363dce43abb42ed1dcce  BSD-3-Clause.txt
+sha256  110535522396708cea37c72a802c5e7e81391139f5f7985631c93ef242b206a4  GFDL-1.3-no-invariants-only.txt
+sha256  8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643  GPL-2.0-only.txt
+sha256  8ceb4b9ee5adedde47b31e975c1d90c73ad27b6b165a1dcd80c7c545eb65b903  GPL-3.0-only.txt
+sha256  da7eabb7bafdf7d3ae5e9f223aa5bdc1eece45ac569dc21b3b037520b4464768  LGPL-3.0-only.txt
+sha256  9b1f50aae6267f9d5e0ceb6775ee86450262c25ec7c0573e151fe5d3f18a4700  LicenseRef-Qt-Commercial.txt
+sha256  40678d338ce53cd93f8b22b281a2ecbcaa3ee65ce60b25ffb0c462b0530846b2  Qt-GPL-exception-1.0.txt
diff --git a/package/python-shiboken6/python-shiboken6.mk b/package/python-shiboken6/python-shiboken6.mk
new file mode 100644
index 0000000000..333d610605
--- /dev/null
+++ b/package/python-shiboken6/python-shiboken6.mk
@@ -0,0 +1,137 @@ 
+################################################################################
+#
+# python-shiboken6
+#
+################################################################################
+
+PYTHON_SHIBOKEN6_VERSION = v6.7.2
+PYTHON_SHIBOKEN6_SITE = https://code.qt.io/pyside/pyside-setup.git
+PYTHON_SHIBOKEN6_SITE_METHOD = git
+PYTHON_SHIBOKEN6_CPE_ID_VENDOR = qt
+PYTHON_SHIBOKEN6_CPE_ID_PRODUCT = shiboken
+PYTHON_SHIBOKEN6_SUPPORTS_IN_SOURCE_BUILD = NO
+PYTHON_SHIBOKEN6_INSTALL_STAGING = YES
+
+PYTHON_SHIBOKEN6_LICENSE = \
+	GPL-2.0+ or LGPL-3.0, \
+	GPL-3.0 with exception (tools), \
+	GFDL-1.3 (docs), \
+	Apache-2.0, \
+	BSD-3-Clause
+
+PYTHON_SHIBOKEN6_LICENSE_FILES = \
+	LICENSES/Apache-2.0.txt \
+	LICENSES/BSD-3-Clause.txt \
+	LICENSES/GFDL-1.3-no-invariants-only.txt \
+	LICENSES/GPL-2.0-only.txt \
+	LICENSES/LGPL-3.0-only.txt \
+	LICENSES/GPL-3.0-only.txt \
+	LICENSES/Qt-GPL-exception-1.0.txt
+
+PYTHON_SHIBOKEN6_DEPENDENCIES = \
+	host-libxslt \
+	host-clang \
+	host-cmake \
+	host-perl \
+	host-qt6base \
+	host-python3 \
+	host-python-numpy \
+	host-python-shiboken6 \
+	qt6base \
+	python3 \
+	python-numpy
+
+HOST_PYTHON_SHIBOKEN6_DEPENDENCIES = \
+	host-libxslt \
+	host-clang \
+	host-cmake \
+	host-perl \
+	host-qt6base \
+	host-python3 \
+	host-python-numpy
+
+PYTHON_SHIBOKEN6_CONF_OPTS = \
+	-DQFP_SHIBOKEN_HOST_PATH=$(HOST_DIR) \
+	-DQFP_PYTHON_HOST_PATH=$(HOST_DIR)/bin/python3
+
+HOST_PYTHON_SHIBOKEN6_CONF_OPTS =
+
+# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
+# 2. sed -i s/\$\$(PKG)/PYTHON_SHIBOKEN6/g
+# 3. sed -i s/\$\$/\$/g
+# 4. append $(PYTHON_SHIBOKEN6_SRCDIR) with sources/shiboken6
+define PYTHON_SHIBOKEN6_CONFIGURE_CMDS
+	(mkdir -p $(PYTHON_SHIBOKEN6_BUILDDIR) && \
+	cd $(PYTHON_SHIBOKEN6_BUILDDIR) && \
+	rm -f CMakeCache.txt && \
+	PATH=$(BR_PATH) \
+	$(PYTHON_SHIBOKEN6_CONF_ENV) $(BR2_CMAKE) $(PYTHON_SHIBOKEN6_SRCDIR)/sources/shiboken6 \
+		-G$(PYTHON_SHIBOKEN6_GENERATOR) \
+		-DCMAKE_MAKE_PROGRAM="$(PYTHON_SHIBOKEN6_GENERATOR_PROGRAM)" \
+		-DCMAKE_TOOLCHAIN_FILE="$(HOST_DIR)/share/buildroot/toolchainfile.cmake" \
+		-DCMAKE_INSTALL_PREFIX="/usr" \
+		-DCMAKE_INSTALL_RUNSTATEDIR="/run" \
+		-DCMAKE_COLOR_MAKEFILE=OFF \
+		-DBUILD_DOC=OFF \
+		-DBUILD_DOCS=OFF \
+		-DBUILD_EXAMPLE=OFF \
+		-DBUILD_EXAMPLES=OFF \
+		-DBUILD_TEST=OFF \
+		-DBUILD_TESTS=OFF \
+		-DBUILD_TESTING=OFF \
+		-DBUILD_SHARED_LIBS=$(if $(BR2_STATIC_LIBS),OFF,ON) \
+		$(CMAKE_QUIET) \
+		$(PYTHON_SHIBOKEN6_CONF_OPTS) \
+		)
+endef
+
+# 1. copy $(2)_CONIFIGURE_CMDS from packages/pkg-cmake.mk
+# 2. sed -i s/\$\$(PKG)/HOST_PYTHON_SHIBOKEN6/g
+# 3. sed -i s/\$\$/\$/g
+# 4. append $(HOST_PYTHON_SHIBOKEN6_SRCDIR) with sources/shiboken6
+define HOST_PYTHON_SHIBOKEN6_CONFIGURE_CMDS
+	(mkdir -p $(HOST_PYTHON_SHIBOKEN6_BUILDDIR) && \
+	cd $(HOST_PYTHON_SHIBOKEN6_BUILDDIR) && \
+	rm -f CMakeCache.txt && \
+	PATH=$(BR_PATH) \
+	PKG_CONFIG="$(PKG_CONFIG_HOST_BINARY)" \
+	PKG_CONFIG_SYSROOT_DIR="/" \
+	PKG_CONFIG_LIBDIR="$(HOST_DIR)/lib/pkgconfig:$(HOST_DIR)/share/pkgconfig" \
+	PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 \
+	PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 \
+	$(HOST_PYTHON_SHIBOKEN6_CONF_ENV) $(BR2_CMAKE) $(HOST_PYTHON_SHIBOKEN6_SRCDIR)/sources/shiboken6 \
+		-G$(HOST_PYTHON_SHIBOKEN6_GENERATOR) \
+		-DCMAKE_MAKE_PROGRAM="$(HOST_PYTHON_SHIBOKEN6_GENERATOR_PROGRAM)" \
+		-DCMAKE_INSTALL_SO_NO_EXE=0 \
+		-DCMAKE_FIND_ROOT_PATH="$(HOST_DIR)" \
+		-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM="BOTH" \
+		-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY="BOTH" \
+		-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE="BOTH" \
+		-DCMAKE_INSTALL_PREFIX="$(HOST_DIR)" \
+		-DCMAKE_C_FLAGS="$(HOST_CFLAGS)" \
+		-DCMAKE_CXX_FLAGS="$(HOST_CXXFLAGS)" \
+		-DCMAKE_EXE_LINKER_FLAGS="$(HOST_LDFLAGS)" \
+		-DCMAKE_SHARED_LINKER_FLAGS="$(HOST_LDFLAGS)" \
+		-DCMAKE_ASM_COMPILER="$(HOSTAS)" \
+		-DCMAKE_C_COMPILER="$(CMAKE_HOST_C_COMPILER)" \
+		-DCMAKE_CXX_COMPILER="$(CMAKE_HOST_CXX_COMPILER)" \
+		$(if $(CMAKE_HOST_C_COMPILER_LAUNCHER),\
+			-DCMAKE_C_COMPILER_LAUNCHER="$(CMAKE_HOST_C_COMPILER_LAUNCHER)" \
+			-DCMAKE_CXX_COMPILER_LAUNCHER="$(CMAKE_HOST_CXX_COMPILER_LAUNCHER)" \
+		) \
+		-DCMAKE_COLOR_MAKEFILE=OFF \
+		-DBUILD_DOC=OFF \
+		-DBUILD_DOCS=OFF \
+		-DBUILD_EXAMPLE=OFF \
+		-DBUILD_EXAMPLES=OFF \
+		-DBUILD_TEST=OFF \
+		-DBUILD_TESTS=OFF \
+		-DBUILD_TESTING=OFF \
+		-DBUILD_SHARED_LIBS=ON \
+		$(CMAKE_QUIET) \
+		$(HOST_PYTHON_SHIBOKEN6_CONF_OPTS) \
+		)
+endef
+
+$(eval $(cmake-package))
+$(eval $(host-cmake-package))
diff --git a/support/testing/tests/package/sample_python_pyside6.py b/support/testing/tests/package/sample_python_pyside6.py
new file mode 100644
index 0000000000..079cece9d5
--- /dev/null
+++ b/support/testing/tests/package/sample_python_pyside6.py
@@ -0,0 +1,165 @@ 
+# ALL_ESSENTIAL_MODULES
+def test_python_pyside6_qt():
+    from PySide6.QtCore import Qt
+    enum = Qt.white
+    assert(str(enum) == 'GlobalColor.white')
+
+
+def test_python_pyside6_qtcore():
+    from PySide6 import QtCore
+    obj = QtCore.QObject()
+    obj.setObjectName('MyObject')
+    assert(obj.objectName() == 'MyObject')
+
+
+def test_python_pyside6_qtgui():
+    from PySide6 import QtGui
+    color = QtGui.QColor.fromRgb(255, 255, 255, 255)
+    assert(color.name(QtGui.QColor.HexArgb) == "#ffffffff")
+
+
+def test_python_pyside6_qtwidgets():
+    from PySide6 import QtWidgets
+    app = QtWidgets.QApplication()
+    label = QtWidgets.QLabel('Hello World')
+    assert(label.text() == 'Hello World')
+    QtWidgets.QApplication.shutdown(app)
+
+
+def test_python_pyside6_qtprintsupport():
+    from PySide6 import QtWidgets
+    from PySide6 import QtPrintSupport
+    app = QtWidgets.QApplication()
+    p = QtPrintSupport.QPrinter()
+    assert(p.creator() == '')
+    QtWidgets.QApplication.shutdown(app)
+
+
+def test_python_pyside6_qtsql():
+    from PySide6 import QtSql
+    db = QtSql.QSqlDatabase()
+    assert(db.hostName() == '')
+
+
+def test_python_pyside6_qtnetwork():
+    from PySide6 import QtNetwork
+    host_info = QtNetwork.QHostInfo()
+    assert(host_info.localHostName() == 'buildroot')
+
+
+def test_python_pyside6_qttest():
+    from PySide6 import QtTest
+    text = QtTest.QTest.toPrettyCString('hello there', 5)
+    assert(text == '"hello"')
+
+
+def test_python_pyside6_qtconcurrent():
+    from PySide6 import QtConcurrent
+    future = QtConcurrent.QFutureQString()
+    assert(future.isRunning() is False)
+
+
+# ALL_OPTIONAL_MODULES
+def test_python_pyside6_qtdbus():
+    from PySide6 import QtDBus
+    message = QtDBus.QDBusMessage()
+    assert(message.errorMessage() == '')
+
+
+def test_python_pyside6_qtxml():
+    from PySide6 import QtXml
+    doc = QtXml.QDomDocument('temp.xml')
+    assert(doc.toString() == '')
+
+
+def test_python_pyside6_qtopengl():
+    from PySide6 import QtOpenGL
+    log = QtOpenGL.QOpenGLDebugLogger()
+    assert(log.isLogging() is False)
+
+
+def test_python_pyside6_qtopenglwidgets():
+    from PySide6 import QtWidgets
+    from PySide6 import QtOpenGLWidgets
+    app = QtWidgets.QApplication()
+    _ = QtOpenGLWidgets.QOpenGLWidget()
+    # assert(widget.isValid() == False)
+    # QOpenGLWidget is not supported on this platform.
+    QtWidgets.QApplication.shutdown(app)
+
+
+def test_python_pyside6_qtquickcontrols():
+    from PySide6 import QtWidgets
+    from PySide6 import QtQuick
+    app = QtWidgets.QApplication()
+    view = QtQuick.QQuickView()
+    assert(str(view.status()) == 'Status.Null')
+    view.setSource('/usr/lib/qt6/qml/QtQuick/Controls/Universal/Label.qml')
+    assert(str(view.status()) == 'Status.Ready')
+    view.close()
+    QtWidgets.QApplication.shutdown(app)
+
+
+def test_python_pyside6_qtquicktest():
+    from PySide6 import QtQuickTest
+    QtQuickTest.QUICK_TEST_MAIN('/usr/lib/qt6/qml/QtTest/TestCase.qml')
+    # The directory '/root' does not contain any test files matching 'tst_*.qml'
+    # 1
+    # todo: The tests run, but don't pass. I have no experience with this module.
+
+
+def test_python_pyside6_qtquickwidgets():
+    from PySide6 import QtWidgets
+    from PySide6 import QtQuickWidgets
+    app = QtWidgets.QApplication()
+    view = QtQuickWidgets.QQuickWidget()
+    assert(str(view.status()) == 'Status.Null')
+    view.setSource('/usr/lib/qt6/qml/QtQuick/Controls/Universal/Label.qml')
+    assert(str(view.status()) == 'Status.Ready')
+    QtWidgets.QApplication.shutdown(app)
+
+
+def test_python_pyside6_qtserialport():
+    from PySide6 import QtSerialPort
+    ser = QtSerialPort.QSerialPort()
+    ser.setPortName('/dev/ttyUSB0')
+    assert(ser.portName() == 'ttyUSB0')
+
+
+def test_python_pyside6_qtsvg():
+    from PySide6 import QtSvg
+    renderer = QtSvg.QSvgRenderer()
+    renderer.setFramesPerSecond(30)
+    assert(renderer.framesPerSecond() == 30)
+
+
+def test_python_pyside6_qtsvgwidgets():
+    from PySide6 import QtWidgets
+    from PySide6 import QtSvgWidgets
+    app = QtWidgets.QApplication()
+    widget = QtSvgWidgets.QSvgWidget()
+    widget.setObjectName('MyObject')
+    assert(widget.objectName() == 'MyObject')
+    QtWidgets.QApplication.shutdown(app)
+
+
+if __name__ == "__main__":
+    test_python_pyside6_qt()
+    test_python_pyside6_qtcore()
+    test_python_pyside6_qtgui()
+    test_python_pyside6_qtwidgets()
+    test_python_pyside6_qtprintsupport()
+    test_python_pyside6_qtsql()
+    test_python_pyside6_qtnetwork()
+    test_python_pyside6_qttest()
+    test_python_pyside6_qtconcurrent()
+    test_python_pyside6_qtdbus()
+    test_python_pyside6_qtxml()
+    test_python_pyside6_qtopengl()
+    test_python_pyside6_qtopenglwidgets()
+    test_python_pyside6_qtquickcontrols()
+    test_python_pyside6_qtquicktest()
+    test_python_pyside6_qtquickwidgets()
+    test_python_pyside6_qtserialport()
+    test_python_pyside6_qtsvg()
+    test_python_pyside6_qtsvgwidgets()
diff --git a/support/testing/tests/package/test_python_pyside6.py b/support/testing/tests/package/test_python_pyside6.py
new file mode 100644
index 0000000000..a5a4872182
--- /dev/null
+++ b/support/testing/tests/package/test_python_pyside6.py
@@ -0,0 +1,60 @@ 
+import os
+
+from tests.package.test_python import TestPythonPackageBase
+
+
+class TestPythonPy3PySide6(TestPythonPackageBase):
+    __test__ = True
+    config = \
+        """
+        BR2_aarch64=y
+        BR2_TOOLCHAIN_EXTERNAL=y
+        BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
+        BR2_LINUX_KERNEL=y
+        BR2_LINUX_KERNEL_CUSTOM_VERSION=y
+        BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.72"
+        BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
+        BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
+        BR2_PACKAGE_MESA3D=y
+        BR2_PACKAGE_MESA3D_OSMESA_GALLIUM=y
+        BR2_PACKAGE_MESA3D_OPENGL_EGL=y
+        BR2_PACKAGE_MESA3D_OPENGL_ES=y
+        BR2_PACKAGE_QT6=y
+        BR2_PACKAGE_QT6BASE_GUI=y
+        BR2_PACKAGE_QT6BASE_WIDGETS=y
+        BR2_PACKAGE_QT6BASE_PRINTSUPPORT=y
+        BR2_PACKAGE_QT6BASE_SQL=y
+        BR2_PACKAGE_QT6BASE_SQLITE=y
+        BR2_PACKAGE_QT6BASE_NETWORK=y
+        BR2_PACKAGE_QT6BASE_TEST=y
+        BR2_PACKAGE_QT6BASE_CONCURRENT=y
+        BR2_PACKAGE_QT6BASE_DBUS=y
+        BR2_PACKAGE_QT6BASE_XML=y
+        BR2_PACKAGE_QT6BASE_OPENGL=y
+        BR2_PACKAGE_QT6DECLARATIVE=y
+        BR2_PACKAGE_QT6DECLARATIVE_QUICK=y
+        BR2_PACKAGE_QT6SERIALPORT=y
+        BR2_PACKAGE_QT6SERIALBUS=y
+        BR2_PACKAGE_QT6SVG=y
+        BR2_PACKAGE_QT6BASE_DEFAULT_QPA="offscreen"
+        BR2_PACKAGE_PYTHON3=y
+        BR2_PACKAGE_PYTHON_PYSIDE6=y
+        BR2_TARGET_ROOTFS_EXT2=y
+        BR2_TARGET_ROOTFS_EXT2_SIZE="512M"
+        # BR2_TARGET_ROOTFS_TAR is not set
+        """
+    sample_scripts = ["tests/package/sample_python_pyside6.py"]
+    timeout = 30
+
+    def login(self):
+        drive = os.path.join(self.builddir, "images", "rootfs.ext2")
+        kern = os.path.join(self.builddir, "images", "Image")
+        self.emulator.boot(arch="aarch64",
+                           kernel=kern,
+                           kernel_cmdline=["root=/dev/vda console=ttyAMA0"],
+                           options=["-M", "virt",
+                                    "-cpu", "cortex-a57",
+                                    "-m", "512M",
+                                    "-smp", "2",
+                                    "-drive", f"file={drive},if=virtio,format=raw"])
+        self.emulator.login()