问题
I have commercial licenses for Qt and PyQt, and am attempting to build static versions of all required software for generating a standalone, executable program that I'm currently writing using Python3 and PyQt. I plan to build natively using VirtualBox, and will probably target Linux and Windows. I'm currently trying to get the Linux build environment set up.
The first step to accomplish this is to build a system root directory, as outlined here: http://pyqt.sourceforge.net/Docs/pyqtdeploy/build_sysroot.html
I am using build-sysroot.py, which is presented here: https://www.riverbankcomputing.com/hg/pyqtdeploy/file/tip/Developers/build-sysroot.py
Following the instructions in the first link, I have created a root directory (sysroot-linux) containing a directory named src, which has g-zipped source code folders for Qt5, PyQt5, sip, PyQtChart, and Python.
I am using Xubuntu 16.04 64-bit in a VBox, along with commercial PyQt-5.8, commercial PyQtChart-5.8, Python-3.6.1, commercial Qt-5.8.0, and sip-4.19.2. I copied my Qt license information into a file located at /home/(user)/.qt-license. I copied my PyQt license file into the g-zipped PyQt/sip directory.
When I run the following command in the Terminal:
python3 build-sysroot.py --build qt python sip pyqt5 pyqtchart --sysroot /home/(user)/(path-to)/sysroot-linux
Where (user) is user name and (path-to) is the path to the system root directory.
About 1.5 hours into the process, I get an error during the PyQt build that reads
Makefile:953: recipe for target 'sipQtNetworkpart1.o' failed
make[1]: \*** [sipQtNetworkpart1.o] Error 1
make[1]: Leaving directory '/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork'
Makefile:414: recipe for target 'sub-QtNetwork-make_first-ordered' failed
make: \*** [sub-QtNetwork-make_first-ordered] Error 2
Traceback (most recent call last):
File "build-sysroot.py", line 1073, in <module>
build_pyqt5(host, target, args.all, args.debug)
File "build-sysroot.py", line 735, in build_pyqt5
host.run(host.make)
File "build-sysroot.py", line 313, in run
subprocess.check_call(args)
File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '('make',)' returned non-zero exit status 2
The company that sells PyQt advised me that my build of Qt doesn't support SSL but my PyQt configuration file has it enabled.
So I tried disabling QtNetwork in the PyQt configuration using "disable=QtNetwork" in build-sysroot.py, function "build_pyqt5" in "args" (python list type; see line 721 of 1st link), but to no avail - the option seems to have been ignored and the build of QtNetwork is attempted anyway.
I am in touch with the company that sells PyQt, but I wanted to reach out to the broader programming community to see if anyone has successfully done this in the past, and could perhaps offer insight. Any help is much appreciated.
Thank you, Chris
EDIT 1 Here is the complete error output, only directory paths modified:
make[1]: Entering directory '/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork'
g++ -c -pipe -O2 -fPIC -std=gnu++11 -fvisibility=hidden -fvisibility-inlines-hidden -fno-exceptions -Wall -W -D_REENTRANT -DSIP_PROTECTED_IS_PUBLIC -Dprotected=public -DQT_NO_EXCEPTIONS -DQT_NO_DEBUG -DQT_NETWORK_LIB -DQT_CORE_LIB -I. -I. -I../../../include/python3.6 -I../../../Qt/include -I../../../Qt/include/QtNetwork -I../../../Qt/include/QtCore -I. -I../../../Qt/mkspecs/linux-g++ -o sipQtNetworkpart1.o sipQtNetworkpart1.cpp
/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork/sipQtNetworkpart1.cpp: In function ‘PyObject* meth_QNetworkReply_sslConfiguration(PyObject*, PyObject*)’:
/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork/sipQtNetworkpart1.cpp:1094:55: error: ‘const class QNetworkReply’ has no member named ‘sslConfiguration’
sipRes = new ::QSslConfiguration(sipCpp->sslConfiguration());
^
/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork/sipQtNetworkpart1.cpp:1094:73: error: invalid use of incomplete type ‘class QSslConfiguration’
sipRes = new ::QSslConfiguration(sipCpp->sslConfiguration());
^
In file included from ../../../Qt/include/QtNetwork/QNetworkRequest:1:0,
from ../../../Qt/include/QtNetwork/qnetworkreply.h:48,
from /home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/sip/QtNetwork/qnetworkreply.sip:18:
../../../Qt/include/QtNetwork/qnetworkrequest.h:52:7: note: forward declaration of ‘class QSslConfiguration’
class QSslConfiguration;
^
/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork/sipQtNetworkpart1.cpp: In function ‘PyObject* meth_QNetworkReply_setSslConfiguration(PyObject*, PyObject*)’:
/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork/sipQtNetworkpart1.cpp:1120:21: error: ‘class QNetworkReply’ has no member named ‘setSslConfiguration’
sipCpp->setSslConfiguration(*a0);
^
/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork/sipQtNetworkpart1.cpp: In function ‘PyObject* meth_QNetworkReply_ignoreSslErrors(PyObject*, PyObject*)’:
/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork/sipQtNetworkpart1.cpp:1162:40: error: no matching function for call to ‘QNetworkReply::ignoreSslErrors(const QList<QSslError>&)’
sipCpp->ignoreSslErrors(*a0);
^
In file included from /home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/sip/QtNetwork/qnetworkreply.sip:18:0:
../../../Qt/include/QtNetwork/qnetworkreply.h:154:18: note: candidate: virtual void QNetworkReply::ignoreSslErrors()
virtual void ignoreSslErrors();
^
../../../Qt/include/QtNetwork/qnetworkreply.h:154:18: note: candidate expects 0 arguments, 1 provided
/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork/sipQtNetworkpart1.cpp: In function ‘PyObject* meth_QNetworkAccessManager_connectToHostEncrypted(PyObject*, PyObject*, PyObject*)’:
/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork/sipQtNetworkpart1.cpp:12735:45: error: incomplete type ‘QSslConfiguration’ used in nested name specifier
{sipName_PutOperation, static_cast<int>( ::QNetworkAccessManager::PutOperation), 55},
^
/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork/sipQtNetworkpart1.cpp:12747:21: error: ‘class QNetworkAccessManager’ has no member named ‘connectToHostEncrypted’
{"encrypted(QNetworkReply*)", "\1encrypted(self, QNetworkReply)", 0, 0},
^
Makefile:953: recipe for target 'sipQtNetworkpart1.o' failed
make[1]: *** [sipQtNetworkpart1.o] Error 1
make[1]: Leaving directory '/home/(user)/(path-to)/sysroot-linux/build/PyQt5_commercial-5.8/QtNetwork'
Makefile:414: recipe for target 'sub-QtNetwork-make_first-ordered' failed
make: *** [sub-QtNetwork-make_first-ordered] Error 2
Traceback (most recent call last):
File "build-sysroot.py", line 1073, in <module>
build_pyqt5(host, target, args.all, args.debug)
File "build-sysroot.py", line 735, in build_pyqt5
host.run(host.make)
File "build-sysroot.py", line 313, in run
subprocess.check_call(args)
File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '('make',)' returned non-zero exit status 2
回答1:
I'll go ahead and share my workaround, in case someone else encounters this issue.
Currently, the build-sysroot.py script uses pyqtdeploycli to generate a configuration file for building PyQt, which includes Qt modules that cannot be statically built, such as QtWebEngine. At any rate, I ended up making a configuration file for PyQt5, and placing it into the top g-zipped folder for the PyQt5 source:
/home/(user)/(path-to)/sysroot-linux/src/PyQt5_commercial-5.8.2.tar.gz/PyQt5_commercial-5.8.2/pyqt5-linux-64.cfg
PyQt5 configuration file (pyqt5-linux-64.cfg):
# The configuration for building PyQt5 for Linux.
# The target Python installation.
py_platform = linux
py_inc_dir = %(sysroot)/include/python%(py_major).%(py_minor)
py_pylib_dir = %(sysroot)/lib
py_pylib_lib = python%(py_major).%(py_minor)m
# The target PyQt installation.
pyqt_module_dir = %(sysroot)/lib/python%(py_major).%(py_minor)/site-packages
pyqt_sip_dir = %(sysroot)/share/sip/PyQt5
# Qt configuration common to all versions.
qt_shared = False
[Qt 5.6]
pyqt_modules = QtCore QtGui QtWidgets
[Qt 5.5]
pyqt_modules = QtCore QtGui QtWidgets
[Qt 5.4]
pyqt_modules = QtCore QtGui QtWidgets
[Qt 5.3]
pyqt_modules = QtCore QtGui QtWidgets
[Qt 5.2]
pyqt_modules = QtCore QtGui QtWidgets
I then modified the build-sysroot.py build_pyqt5 function to no longer evoke pyqtdeploycli, and instead just use the manually-created configuration file, as follows:
def build_pyqt5(host, target, optional, debug):
""" Build a target static PyQt5. """
source = host.sysroot.find_source('PyQt5_*', optional=optional)
if source is None:
return
host.sysroot.unpack_source(source)
license_path = os.path.join(host.sysroot.src_dir, 'pyqt-commercial.sip')
if os.path.isfile(license_path):
shutil.copy(license_path, 'sip')
configuration = 'pyqt5-' + target.name + '.cfg'
# Disable the call to pyqtdeploycli here
# host.run(host.pyqtdeploycli, '--package', 'pyqt5', '--output',
# configuration, '--target', target.name, 'configure')
args = [host.interpreter, 'configure.py', '--static', '--qmake',
host.qmake, '--sysroot', str(host.sysroot), '--no-tools',
'--no-qsci-api', '--no-designer-plugin', '--no-python-dbus',
'--no-qml-plugin', '--no-stubs', '--configuration', configuration,
'--sip', host.sip, '--confirm-license', '-c', '-j2']
if debug:
args.append('--debug')
host.run(*args)
host.run(host.make)
host.run(host.make, 'install')
I have only gotten this to work for QtCore, QtGui, and QtWidgets, but others may be possible.
来源:https://stackoverflow.com/questions/43700790/pyqt-static-build-fails-at-make