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}