1{ lib
2, stdenv
3, buildPythonPackage
4, setuptools
5, isPy27
6, fetchPypi
7, pkg-config
8, dbus
9, lndir
10, dbus-python
11, sip
12, pyqt5_sip
13, pyqt-builder
14, libsForQt5
15, enableVerbose ? true
16, withConnectivity ? false
17, withMultimedia ? false
18, withWebKit ? false
19, withWebSockets ? false
20, withLocation ? false
21, withSerialPort ? false
22, withTools ? false
23, pkgsBuildTarget
24, buildPackages
25, dbusSupport ? !stdenv.isDarwin
26}:
27
28buildPythonPackage rec {
29 pname = "PyQt5";
30 version = "5.15.9";
31 format = "pyproject";
32
33 disabled = isPy27;
34
35 src = fetchPypi {
36 inherit pname version;
37 hash = "sha256-3EHoQBqQ3D4raStBG9VJKrVZrieidCTu1L05FVZOxMA=";
38 };
39
40 patches = [
41 # Fix some wrong assumptions by ./project.py
42 # TODO: figure out how to send this upstream
43 ./pyqt5-fix-dbus-mainloop-support.patch
44 # confirm license when installing via pyqt5_sip
45 ./pyqt5-confirm-license.patch
46 ];
47
48 postPatch =
49 # be more verbose
50 ''
51 cat >> pyproject.toml <<EOF
52 '' + lib.optionalString enableVerbose ''
53 [tool.sip.project]
54 verbose = true
55 ''
56 # Due to bug in SIP .whl name generation we have to bump minimal macos sdk upto 11.0 for
57 # aarch64-darwin. This patch can be removed once SIP will fix it in upstream,
58 # see https://github.com/NixOS/nixpkgs/pull/186612#issuecomment-1214635456.
59 + lib.optionalString (stdenv.isDarwin && stdenv.isAarch64) ''
60 minimum-macos-version = "11.0"
61 '' + ''
62 EOF
63 ''
64
65 # pyqt-builder tries to compile *and run* these programs. This
66 # is really sad because the only thing they do is print out a
67 # flag based on whether or not some compile-time symbol was
68 # defined. This could all be done without having to *execute*
69 # cross-compiled programs!
70 #
71 # Here is the complete list of things checked:
72 #
73 # QT_NO_PRINTDIALOG => PyQt_PrintDialog
74 # QT_NO_PRINTER => PyQt_Printer
75 # QT_NO_PRINTPREVIEWDIALOG => PyQt_PrintPreviewDialog
76 # QT_NO_PRINTPREVIEWWIDGET => PyQt_PrintPreviewWidget
77 # QT_NO_SSL => PyQt_SSL
78 # QT_SHARED || QT_DLL => shared (otherwise static)
79 # QT_NO_PROCESS => PyQt_Process
80 # QT_NO_FPU || Q_PROCESSOR_ARM || Q_OS_WINCE => PyQt_qreal_double
81 # sizeof (qreal) != sizeof (double) => PyQt_qreal_double
82 # !Q_COMPILER_CONSTEXPR !Q_COMPILER_UNIFORM_INIT => PyQt_CONSTEXPR
83 # QT_NO_ACCESSIBILITY => PyQt_Accessibility
84 # QT_NO_OPENGL => PyQt_OpenGL PyQt_Desktop_OpenGL
85 # defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES_3) => PyQt_Desktop_OpenGL
86 # QT_NO_RAWFONT => PyQt_RawFont
87 # QT_NO_SESSIONMANAGER => PyQt_SessionManager
88 #
89 + lib.optionalString (!(stdenv.buildPlatform.canExecute stdenv.hostPlatform)) ''
90 rm config-tests/cfgtest_QtCore.cpp
91 rm config-tests/cfgtest_QtGui.cpp
92 rm config-tests/cfgtest_QtNetwork.cpp
93 rm config-tests/cfgtest_QtPrintSupport.cpp
94 '';
95
96 enableParallelBuilding = true;
97 # HACK: paralellize compilation of make calls within pyqt's setup.py
98 # pkgs/stdenv/generic/setup.sh doesn't set this for us because
99 # make gets called by python code and not its build phase
100 # format=pyproject means the pip-build-hook hook gets used to build this project
101 # pkgs/development/interpreters/python/hooks/pip-build-hook.sh
102 # does not use the enableParallelBuilding flag
103 postUnpack = ''
104 export MAKEFLAGS+="''${enableParallelBuilding:+-j$NIX_BUILD_CORES}"
105 '';
106
107 # tons of warnings from subpackages, no point in playing whack-a-mole
108 env = lib.optionalAttrs (!enableVerbose) {
109 NIX_CFLAGS_COMPILE = "-w";
110 };
111
112 outputs = [ "out" "dev" ];
113
114 dontWrapQtApps = true;
115
116 nativeBuildInputs = [
117 pkg-config
118 ] ++ lib.optionals (stdenv.buildPlatform == stdenv.hostPlatform) [
119 libsForQt5.qmake
120 ] ++ [
121 setuptools
122 lndir
123 sip
124 ] ++ (with pkgsBuildTarget.targetPackages.libsForQt5; [
125 ] ++ lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform) [
126 qmake
127 ] ++ [
128 qtbase
129 qtsvg
130 qtdeclarative
131 qtwebchannel
132 ]
133 ++ lib.optional withConnectivity qtconnectivity
134 ++ lib.optional withMultimedia qtmultimedia
135 ++ lib.optional withWebKit qtwebkit
136 ++ lib.optional withWebSockets qtwebsockets
137 ++ lib.optional withLocation qtlocation
138 ++ lib.optional withSerialPort qtserialport
139 ++ lib.optional withTools qttools
140 );
141
142 buildInputs = with libsForQt5; [
143 dbus
144 ] ++ lib.optionals (stdenv.buildPlatform == stdenv.hostPlatform) [
145 qtbase
146 ] ++ [
147 qtsvg
148 qtdeclarative
149 pyqt-builder
150 ]
151 ++ lib.optional withConnectivity qtconnectivity
152 ++ lib.optional withWebKit qtwebkit
153 ++ lib.optional withWebSockets qtwebsockets
154 ++ lib.optional withLocation qtlocation
155 ++ lib.optional withSerialPort qtserialport
156 ++ lib.optional withTools qttools
157 ;
158
159 propagatedBuildInputs = [
160 dbus-python
161 pyqt5_sip
162 ];
163
164 passthru = {
165 inherit sip pyqt5_sip;
166 multimediaEnabled = withMultimedia;
167 webKitEnabled = withWebKit;
168 WebSocketsEnabled = withWebSockets;
169 connectivityEnabled = withConnectivity;
170 locationEnabled = withLocation;
171 serialPortEnabled = withSerialPort;
172 toolsEnabled = withTools;
173 };
174
175 dontConfigure = true;
176
177 # Checked using pythonImportsCheck
178 doCheck = false;
179
180 pythonImportsCheck = [
181 "PyQt5"
182 "PyQt5.QtCore"
183 "PyQt5.QtQml"
184 "PyQt5.QtWidgets"
185 "PyQt5.QtGui"
186 ]
187 ++ lib.optional withWebSockets "PyQt5.QtWebSockets"
188 ++ lib.optional withWebKit "PyQt5.QtWebKit"
189 ++ lib.optional withMultimedia "PyQt5.QtMultimedia"
190 ++ lib.optional withConnectivity "PyQt5.QtBluetooth"
191 ++ lib.optional withLocation "PyQt5.QtPositioning"
192 ++ lib.optional withSerialPort "PyQt5.QtSerialPort"
193 ++ lib.optional withTools "PyQt5.QtDesigner"
194 ;
195
196 meta = with lib; {
197 description = "Python bindings for Qt5";
198 homepage = "https://riverbankcomputing.com/";
199 license = licenses.gpl3Only;
200 platforms = platforms.mesaPlatforms;
201 maintainers = with maintainers; [ sander ];
202 };
203}