Hello, since Scott is working on update to sip 5 (thank you!) I've figured this is a good time check if we can use the PyQt-builder Python build backend with our pyproject-rpm-macros.
tl;dr It is broken in various ways and I am unsure where to attempt to fix things.
-------------
This was my case study:
I've used the python-pyqtchart package as a test subject, as it is fairly simple and has an open pull request to port it to sip5 [1].
I've pretty much reconstructed the spec file as I would normally do:
%generate_buildrequires %pyproject_buildrequires
%build %pyproject_wheel
%install %pyproject_install
To ease things up, I've kept the non-Python-packages BuilRequires intact, so the package still BuildRequires python3-qt5-devel, qt5-qtcharts-devel and qt5-qtbase-private-devel. I've removed the BuildRequires on python3dist(sip) and python3dist(pyqt-builder) as I've expected those to be generated.
The simplified pyproject.toml file looks like this:
[build-system] requires = ["sip >=5.3, <7", "PyQt-builder >=1.6, <2"] build-backend = "sipbuild.api"
[tool.sip.metadata] name = "PyQtChart" version = "5.15.2" ... requires-dist = "PyQt5 (>=5.15)"
[tool.sip] project-factory = "pyqtbuild:PyQtProject"
[tool.sip.project] tag-prefix = "QtChart"
[tool.sip.bindings.QtChart] qmake-QT = ["charts"]
I've also tried with version 5.15.4, but not much is different.
I've used the copr with sip5 [2] to build the package.
-------------
%pyproject_buildrequires works and generates requirements on python3dist(sip) and python3dist(pyqt-builder) \o/
%pyproject_buildrequires -r doesn't work. It says:
ValueError: build backend cannot provide build metadata (incl. runtime requirements) before buld
Except for the typo [3], this is the expected behavior for a build backend that does not support the prepare_metadata_for_build_wheel hook. Bummer, but fair.
We can RFE PyQt-builder to add that hook.
-------------
%pyproject_wheel fails very badly. The traceback is unparseable by humans. It ends with:
pip._internal.exceptions.InstallationSubprocessError: Command errored out with exit status 1: ... Check the logs for full command output.
I have no idea where are the logs. We might want to improve this in pip.
After some digging, I've realized the problem is that PyQt-builder calls "qmake" and that command was not available. I've looked into the code and the "qmake" name is hardcoded, but searched on $PATH.
The "original" non-pyproject spec has:
sip-build ... --qmake="%{_qt5_qmake}"
But there is no (known) way to pass such options to the backend.
I was able to make it work by exporting PATH="%{_qt5_bindir}:$PATH".
I was wondering whether the Fedora's sip5 (or PyQt-builder) package might change the default to make this work, but maybe there is no reasonable default here, as PyQt-builder is Qt version agnostic. Hence I don't know how to make it work out of the box. Not sure where to improve this experience.
Anyway, workaround exists.
-------------
During %pyproject_wheel, "make" is called internally by the backend. The build is not parallelized. I was able to workaround this by using MAKEFLAGS='%{?_smp_mflags}'.
We might want to set this environment variable to '%{_make_output_sync} %{?_smp_mflags} %{_make_verbose}' in the %pyproject_wheel macro, so any backed that utilizes make gets the default arguments Fedora packages should use.
Anyway, this is not a blocker to build the package.
-------------
Processing files: python-pyqtchart-debugsource-5.15.4-1.fc35.x86_64 RPM build errors: error: Empty %files file /builddir/build/BUILD/PyQtChart-5.15.4 /debugsourcefiles.list
This is a problem I get next. It likely means the build flags are not propagated. Our macros set the CFLAGS and LDFLAGS environment variables, but the build does not respect them. I've tried exporting CXXFLAGS as well, but no dice.
Apparently, the build backend does not pass the variables to the build.
I've tried a workaround like this:
export MAKEFLAGS='%{?_smp_mflags} CPPFLAGS="%{build_cxxflags}"'
But it makes the internal make call just dump the targets instead of actually building, so I guess I am doing it wrong. Either way, I think we need to fix PyQt-builder/sip to respect the flags from the environment variables.
Funnily enbough, when I break make like this, it creates the wheel anyway, but with no dist-info metadata in it. I guess if users break make by setting wrong MAKEFLAGS, the wheel should not be created at all :/
To move forward, I've used %global debug_package %{nil}, but I consider not using the Fedora's flag a blocker before we recommend the macros for packages that use PyQt-builder.
-------------
The next problem I got was:
error: File not found: /builddir/build/BUILDROOT/python-pyqtchart-5.15.4-1.fc35.x86_64/usr/share/qt5/qsci/api/python/PyQtChart.api
The "original" non-pyproject specfile had:
sip-build ... --api-dir=%{_qt5_datadir}/qsci/api/python
And as said previously, I don't know a way to pass such options to the backend.
I am not skilled enough in Qt and SIP, so I have no idea if we need to ship the .api file or not. But if we need or want to, we should be able to. When the option is not used, the api file is not installed anywhere. I was unable to figure this out yet.
-------------
That's it. I don't really know where to fix things, and I'd appreciate some pointers. This is not a very high priority for me right now, but once the new Python guidelines [4] are in place, I think we should make this work, possibly with some reasonable worarounds.
[1] https://src.fedoraproject.org/rpms/python-pyqtchart/pull-request/6 [2] https://copr.fedorainfracloud.org/coprs/swt2c/pyqt5-sip5/ [3] https://src.fedoraproject.org/rpms/pyproject-rpm-macros/pull-request/167 [4] https://fedoraproject.org/wiki/Changes/PythonPackagingGuidelines202x
Hi, This looks like the pip issue for passing options to backends (like sip-build, presumably): https://github.com/pypa/pip/issues/5771
On 23. 06. 21 13:17, Miro Hrončok wrote:
Hello, since Scott is working on update to sip 5 (thank you!) I've figured this is a good time check if we can use the PyQt-builder Python build backend with our pyproject-rpm-macros.
tl;dr It is broken in various ways and I am unsure where to attempt to fix things.
This was my case study:
I've used the python-pyqtchart package as a test subject, as it is fairly simple and has an open pull request to port it to sip5 [1].
I've pretty much reconstructed the spec file as I would normally do:
%generate_buildrequires %pyproject_buildrequires
%build %pyproject_wheel
%install %pyproject_install
To ease things up, I've kept the non-Python-packages BuilRequires intact, so the package still BuildRequires python3-qt5-devel, qt5-qtcharts-devel and qt5-qtbase-private-devel. I've removed the BuildRequires on python3dist(sip) and python3dist(pyqt-builder) as I've expected those to be generated.
The simplified pyproject.toml file looks like this:
[build-system] requires = ["sip >=5.3, <7", "PyQt-builder >=1.6, <2"] build-backend = "sipbuild.api"
[tool.sip.metadata] name = "PyQtChart" version = "5.15.2" ... requires-dist = "PyQt5 (>=5.15)"
[tool.sip] project-factory = "pyqtbuild:PyQtProject"
[tool.sip.project] tag-prefix = "QtChart"
[tool.sip.bindings.QtChart] qmake-QT = ["charts"]
I've also tried with version 5.15.4, but not much is different.
I've used the copr with sip5 [2] to build the package.
[...] build
backend that does not support the prepare_metadata_for_build_wheel hook. Bummer, but fair.
We can RFE PyQt-builder to add that hook.
[...] PyQt-builder calls
"qmake" and that command was not available. I've looked into the code and the "qmake" name is hardcoded, but searched on $PATH.
The "original" non-pyproject spec has:
sip-build ... --qmake="%{_qt5_qmake}"
But there is no (known) way to pass such options to the backend.
[...] workaround exists.
During %pyproject_wheel, "make" is called internally by the backend. The build is not parallelized. I was able to workaround this by using MAKEFLAGS='%{?_smp_mflags}'.
We might want to set this environment variable to '%{_make_output_sync} %{?_smp_mflags} %{_make_verbose}' in the %pyproject_wheel macro, so any backed that utilizes make gets the default arguments Fedora packages should use.
Anyway, this is not a blocker to build the package.
Processing files: python-pyqtchart-debugsource-5.15.4-1.fc35.x86_64 RPM build errors: error: Empty %files file /builddir/build/BUILD/PyQtChart-5.15.4 /debugsourcefiles.list
This is a problem I get next. It likely means the build flags are not propagated. Our macros set the CFLAGS and LDFLAGS environment variables, but the build does not respect them. I've tried exporting CXXFLAGS as well, but no dice.
Apparently, the build backend does not pass the variables to the build.
I've tried a workaround like this:
export MAKEFLAGS='%{?_smp_mflags} CPPFLAGS="%{build_cxxflags}"'
But it makes the internal make call just dump the targets instead of actually building, so I guess I am doing it wrong. Either way, I think we need to fix PyQt-builder/sip to respect the flags from the environment variables.
Funnily enbough, when I break make like this, it creates the wheel anyway, but with no dist-info metadata in it. I guess if users break make by setting wrong MAKEFLAGS, the wheel should not be created at all :/
To move forward, I've used %global debug_package %{nil}, but I consider not using the Fedora's flag a blocker before we recommend the macros for packages that use PyQt-builder.
The next problem I got was:
error: File not found: /builddir/build/BUILDROOT/python-pyqtchart-5.15.4-1.fc35.x86_64/usr/share/qt5/qsci/api/python/PyQtChart.api
The "original" non-pyproject specfile had:
sip-build ... --api-dir=%{_qt5_datadir}/qsci/api/python
And as said previously, I don't know a way to pass such options to the backend.
I am not skilled enough in Qt and SIP, so I have no idea if we need to ship the .api file or not. But if we need or want to, we should be able to. When the option is not used, the api file is not installed anywhere. I was unable to figure this out yet.
That's it. I don't really know where to fix things, and I'd appreciate some pointers. This is not a very high priority for me right now, but once the new Python guidelines [4] are in place, I think we should make this work, possibly with some reasonable worarounds.
[1] https://src.fedoraproject.org/rpms/python-pyqtchart/pull-request/6 [2] https://copr.fedorainfracloud.org/coprs/swt2c/pyqt5-sip5/ [3] https://src.fedoraproject.org/rpms/pyproject-rpm-macros/pull-request/167 [4] https://fedoraproject.org/wiki/Changes/PythonPackagingGuidelines202x
On Wed, 23 Jun 2021, Miro Hrončok wrote:
%pyproject_buildrequires works and generates requirements on python3dist(sip) and python3dist(pyqt-builder) \o/
%pyproject_buildrequires -r doesn't work. It says:
ValueError: build backend cannot provide build metadata (incl. runtime requirements) before buld
Except for the typo [3], this is the expected behavior for a build backend that does not support the prepare_metadata_for_build_wheel hook. Bummer, but fair.
We can RFE PyQt-builder to add that hook.
As a start to tackling these problems, I sent this RFE upstream. It looks like it should be relatively easy to implement, as far as I can see.
Miro, do you know any examples of Fedora packages that are using PEP-517 build systems that build extension modules (successfully)?
Scott
On 21. 07. 21 20:25, Scott Talbert wrote:
Miro, do you know any examples of Fedora packages that are using PEP-517 build systems that build extension modules (successfully)?
This following CI spec files:
printrun.spec python-ldap.spec python-markupsafe.spec python-mistune.spec
All in https://src.fedoraproject.org/rpms/pyproject-rpm-macros/blob/rawhide/f/tests
At least the following actual packages in Fedora:
python-indexed_gzip python-pendulum python-xmlsec
If by “are using PEP-517 build systems” you just mean those that use pyproject-rpm-macros in their spec files, I can also offer python-asyncpg and python-pyrsistent as examples.
If you mean that upstream does not use setuptools in setup.py, but instead uses flit or poetry via pyproject.toml, then python-pendulum, which uses poetry, may be the only example right now.
python-devel@lists.fedoraproject.org