···11+# Fix libtool libraries generated by qmake.
22+# qmake started inserting filenames of shared objects instead of the appropriate
33+# linker flags. fixQmakeLibtool searches for broken libtool libraries and
44+# replaces the filenames with the linker flags that should have been there.
55+fixQmakeLibtool() {
66+ if [ -d "$1" ]; then
77+ find "$1" -name '*.la' | while read la; do
88+ set +e
99+ framework_libs=$(grep '^dependency_libs' "$la" | grep -Eo -- '-framework +\w+' | tr '\n' ' ')
1010+ set -e
1111+ sed -i "$la" \
1212+ -e '/^dependency_libs/ s,\(/[^ ]\+\)/lib\([^/ ]\+\)\.so,-L\1 -l\2,g' \
1313+ -e '/^dependency_libs/ s,-framework \+\w\+,,g'
1414+ if [ ! -z "$framework_libs" ]; then
1515+ if grep '^inherited_linker_flags=' $la >/dev/null; then
1616+ sed -i "$la" -e "s/^\(inherited_linker_flags='[^']*\)/\1 $framework_libs/"
1717+ else
1818+ echo "inherited_linker_flags='$framework_libs'" >>"$la"
1919+ fi
2020+ fi
2121+ done
2222+ fi
2323+}
2424+2525+fixupOutputHooks+=('fixQmakeLibtool $prefix')
···11+updateToolPath() {
22+ local tool="$1"
33+ local target="$2"
44+ local original="${!outputBin}/$tool"
55+ local actual="${!outputDev}/$tool"
66+ if grep -q "$original" "$target"; then
77+ echo "updateToolPath: Updating \`$original' in \`$target\'..."
88+ sed -i "$target" -e "s|$original|$actual|"
99+ fi
1010+}
1111+1212+moveQtDevTools() {
1313+ if [ -n "$devTools" ]; then
1414+ for tool in $devTools; do
1515+ moveToOutput "$tool" "${!outputDev}"
1616+ done
1717+1818+ if [ -d "${!outputDev}/mkspecs" ]; then
1919+ find "${!outputDev}/mkspecs" -name '*.pr?' | while read pr_; do
2020+ for tool in $devTools; do
2121+ updateToolPath "$tool" "$pr_"
2222+ done
2323+ done
2424+ fi
2525+2626+ if [ -d "${!outputDev}/lib/cmake" ]; then
2727+ find "${!outputDev}/lib/cmake" -name '*.cmake' | while read cmake; do
2828+ for tool in $devTools; do
2929+ updateToolPath "$tool" "$cmake"
3030+ done
3131+ done
3232+ fi
3333+ fi
3434+}
···77 exit 1
88 fi
99else # Only set up Qt once.
1010-__nix_qtbase="@dev@"
1010+ __nix_qtbase="@dev@"
11111212-qtPluginPrefix=@qtPluginPrefix@
1313-qtQmlPrefix=@qtQmlPrefix@
1212+ qtPluginPrefix=@qtPluginPrefix@
1313+ qtQmlPrefix=@qtQmlPrefix@
14141515-# Disable debug symbols if qtbase was built without debugging.
1616-# This stops -dev paths from leaking into other outputs.
1717-if [ -z "@debug@" ]; then
1818- NIX_CFLAGS_COMPILE="${NIX_CFLAGS_COMPILE-}${NIX_CFLAGS_COMPILE:+ }-DQT_NO_DEBUG"
1919-fi
1515+ . @fix_qt_builtin_paths@
1616+ . @fix_qt_module_paths@
20172121-# Integration with CMake:
2222-# Set the CMake build type corresponding to how qtbase was built.
2323-if [ -n "@debug@" ]; then
2424- cmakeBuildType="Debug"
2525-else
2626- cmakeBuildType="Release"
2727-fi
1818+ # Disable debug symbols if qtbase was built without debugging.
1919+ # This stops -dev paths from leaking into other outputs.
2020+ if [ -z "@debug@" ]; then
2121+ NIX_CFLAGS_COMPILE="${NIX_CFLAGS_COMPILE-}${NIX_CFLAGS_COMPILE:+ }-DQT_NO_DEBUG"
2222+ fi
28232929-qtPreHook() {
3030- # Check that wrapQtAppsHook is used, or it is explicitly disabled.
3131- if [[ -z "$__nix_wrapQtAppsHook" && -z "$dontWrapQtApps" ]]; then
3232- echo >&2 "Error: wrapQtAppsHook is not used, and dontWrapQtApps is not set."
3333- exit 1
2424+ # Integration with CMake:
2525+ # Set the CMake build type corresponding to how qtbase was built.
2626+ if [ -n "@debug@" ]; then
2727+ cmakeBuildType="Debug"
2828+ else
2929+ cmakeBuildType="Release"
3430 fi
3535-}
3636-prePhases+=" qtPreHook"
3131+3232+ # Build tools are often confused if QMAKE is unset.
3333+ export QMAKE=@dev@/bin/qmake
37343838-addQtModulePrefix () {
3939- addToSearchPath QT_ADDITIONAL_PACKAGES_PREFIX_PATH $1
4040-}
4141-addEnvHooks "$hostOffset" addQtModulePrefix
3535+ export QMAKEPATH=
3636+3737+ export QMAKEMODULES=
3838+3939+ declare -Ag qmakePathSeen=()
4040+ qmakePathHook() {
4141+ # Skip this path if we have seen it before.
4242+ # MUST use 'if' because 'qmakePathSeen[$]' may be unset.
4343+ if [ -n "${qmakePathSeen[$1]-}" ]; then return; fi
4444+ qmakePathSeen[$1]=1
4545+ if [ -d "$1/mkspecs" ]; then
4646+ QMAKEMODULES="${QMAKEMODULES}${QMAKEMODULES:+:}/mkspecs"
4747+ QMAKEPATH="${QMAKEPATH}${QMAKEPATH:+:}$1"
4848+ fi
4949+ }
5050+ envBuildHostHooks+=(qmakePathHook)
5151+5252+ postPatchMkspecs() {
5353+ # Prevent this hook from running multiple times
5454+ dontPatchMkspecs=1
5555+5656+ local bin="${!outputBin}"
5757+ local dev="${!outputDev}"
5858+ local doc="${!outputDoc}"
5959+ local lib="${!outputLib}"
6060+6161+ moveToOutput "mkspecs" "$dev"
6262+6363+ if [ -d "$dev/mkspecs/modules" ]; then
6464+ fixQtModulePaths "$dev/mkspecs/modules"
6565+ fi
6666+6767+ if [ -d "$dev/mkspecs" ]; then
6868+ fixQtBuiltinPaths "$dev/mkspecs" '*.pr?'
6969+ fi
7070+7171+ if [ -d "$lib" ]; then
7272+ fixQtBuiltinPaths "$lib" '*.pr?'
7373+ fi
7474+ }
7575+ if [ -z "${dontPatchMkspecs-}" ]; then
7676+ postPhases="${postPhases-}${postPhases:+ }postPatchMkspecs"
7777+ fi
7878+7979+ qtPreHook() {
8080+ # Check that wrapQtAppsHook is used, or it is explicitly disabled.
8181+ if [[ -z "$__nix_wrapQtAppsHook" && -z "$dontWrapQtApps" ]]; then
8282+ echo >&2 "Error: wrapQtAppsHook is not used, and dontWrapQtApps is not set."
8383+ exit 1
8484+ fi
8585+ }
8686+ prePhases+=" qtPreHook"
8787+8888+ addQtModulePrefix() {
8989+ addToSearchPath QT_ADDITIONAL_PACKAGES_PREFIX_PATH $1
9090+ }
9191+ addEnvHooks "$hostOffset" addQtModulePrefix
42924393fi
···1818 perl
1919 cmake
2020 ninja
2121+ self.qmake
2122 ];
2223 propagatedBuildInputs = args.qtInputs ++ (args.propagatedBuildInputs or [ ]);
2424+2525+ preHook = ''
2626+ . ${./hooks/move-qt-dev-tools.sh}
2727+ . ${./hooks/fix-qt-builtin-paths.sh}
2828+ '';
23292430 outputs = args.outputs or [ "out" "dev" ];
2531···3238 moveToOutput "$dir" "$dev"
3339 done
3440 fi
4141+ fixQtBuiltinPaths $out/lib "*.pr?"
3542 ${args.postInstall or ""}
3643 '';
4444+4545+ preConfigure = args.preConfigure or "" + ''
4646+ fixQtBuiltinPaths . '*.pr?'
4747+ '' + lib.optionalString (builtins.compareVersions "5.15.0" version <= 0)
4848+ # Note: We use ${version%%-*} to remove any tag from the end of the version
4949+ # string. Version tags are added by Nixpkgs maintainers and not reflected in
5050+ # the source version.
5151+ ''
5252+ if [[ -z "$dontCheckQtModuleVersion" ]] \
5353+ && grep -q '^MODULE_VERSION' .qmake.conf 2>/dev/null \
5454+ && ! grep -q -F "''${version%%-*}" .qmake.conf 2>/dev/null
5555+ then
5656+ echo >&2 "error: could not find version ''${version%%-*} in .qmake.conf"
5757+ echo >&2 "hint: check .qmake.conf and update the package version in Nixpkgs"
5858+ exit 1
5959+ fi
6060+6161+ if [[ -z "$dontSyncQt" && -f sync.profile ]]; then
6262+ # FIXME: this probably breaks crosscompiling as it's not from nativeBuildInputs
6363+ # I don't know how to get /libexec from nativeBuildInputs to work, it's not under /bin
6464+ ${self.qtbase.dev.nativeDrv or self.qtbase.dev}/libexec/syncqt.pl -version "''${version%%-*}"
6565+ fi
6666+ '';
6767+6868+ postFixup = ''
6969+ if [ -d "''${!outputDev}/lib/pkgconfig" ]; then
7070+ find "''${!outputDev}/lib/pkgconfig" -name '*.pc' | while read pc; do
7171+ sed -i "$pc" \
7272+ -e "/^prefix=/ c prefix=''${!outputLib}" \
7373+ -e "/^exec_prefix=/ c exec_prefix=''${!outputBin}" \
7474+ -e "/^includedir=/ c includedir=''${!outputDev}/include"
7575+ done
7676+ fi
7777+7878+ moveQtDevTools
7979+ '' + args.postFixup or "";
37803881 meta = with lib; {
3982 homepage = "https://www.qt.io/";
+138
pkgs/development/python-modules/pyqt/6.x.nix
···11+{ lib
22+, buildPythonPackage
33+, isPy27
44+, fetchPypi
55+, pkg-config
66+, dbus
77+, lndir
88+, setuptools
99+, dbus-python
1010+, sip
1111+, pyqt6-sip
1212+, pyqt-builder
1313+, qt6Packages
1414+, pythonOlder
1515+, withMultimedia ? true
1616+, withWebSockets ? true
1717+# FIXME: Once QtLocation is available for Qt6 enable this
1818+# https://bugreports.qt.io/browse/QTBUG-96795
1919+#, withLocation ? true
2020+# Not currently part of PyQt6
2121+#, withConnectivity ? true
2222+}:
2323+2424+buildPythonPackage rec {
2525+ pname = "PyQt6";
2626+ version = "6.4.0";
2727+ format = "pyproject";
2828+2929+ disabled = pythonOlder "3.6";
3030+3131+ src = fetchPypi {
3232+ inherit pname version;
3333+ sha256 = "sha256-kTkkab4fSRkF+p54+k5AWaiathbd8uz9UlvB1lwmu5M=";
3434+ };
3535+3636+ patches = [
3737+ # Fix some wrong assumptions by ./project.py
3838+ # TODO: figure out how to send this upstream
3939+ # FIXME: make a version for PyQt6?
4040+ # ./pyqt5-fix-dbus-mainloop-support.patch
4141+ # confirm license when installing via pyqt6_sip
4242+ ./pyqt5-confirm-license.patch
4343+ ];
4444+4545+ # be more verbose
4646+ postPatch = ''
4747+ cat >> pyproject.toml <<EOF
4848+ [tool.sip.project]
4949+ verbose = true
5050+ EOF
5151+ '';
5252+5353+ enableParallelBuilding = true;
5454+ # HACK: paralellize compilation of make calls within pyqt's setup.py
5555+ # pkgs/stdenv/generic/setup.sh doesn't set this for us because
5656+ # make gets called by python code and not its build phase
5757+ # format=pyproject means the pip-build-hook hook gets used to build this project
5858+ # pkgs/development/interpreters/python/hooks/pip-build-hook.sh
5959+ # does not use the enableParallelBuilding flag
6060+ postUnpack = ''
6161+ export MAKEFLAGS+=" -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES"
6262+ '';
6363+6464+ outputs = [ "out" "dev" ];
6565+6666+ dontWrapQtApps = true;
6767+6868+ nativeBuildInputs = with qt6Packages; [
6969+ pkg-config
7070+ lndir
7171+ sip
7272+ qtbase
7373+ qtsvg
7474+ qtdeclarative
7575+ qtwebchannel
7676+ qmake
7777+ qtquick3d
7878+ qtquicktimeline
7979+ ]
8080+ # ++ lib.optional withConnectivity qtconnectivity
8181+ ++ lib.optional withMultimedia qtmultimedia
8282+ ++ lib.optional withWebSockets qtwebsockets
8383+ # ++ lib.optional withLocation qtlocation
8484+ ;
8585+8686+ buildInputs = with qt6Packages; [
8787+ dbus
8888+ qtbase
8989+ qtsvg
9090+ qtdeclarative
9191+ pyqt-builder
9292+ qtquick3d
9393+ qtquicktimeline
9494+ ]
9595+ # ++ lib.optional withConnectivity qtconnectivity
9696+ ++ lib.optional withWebSockets qtwebsockets
9797+ # ++ lib.optional withLocation qtlocation
9898+ ;
9999+100100+ propagatedBuildInputs = [
101101+ dbus-python
102102+ pyqt6-sip
103103+ setuptools
104104+ ];
105105+106106+ passthru = {
107107+ inherit sip pyqt6-sip;
108108+ multimediaEnabled = withMultimedia;
109109+ WebSocketsEnabled = withWebSockets;
110110+ };
111111+112112+ dontConfigure = true;
113113+114114+ # Checked using pythonImportsCheck, has no tests
115115+ doCheck = true;
116116+117117+ pythonImportsCheck = [
118118+ "PyQt6"
119119+ "PyQt6.QtCore"
120120+ "PyQt6.QtQml"
121121+ "PyQt6.QtWidgets"
122122+ "PyQt6.QtGui"
123123+ "PyQt6.QtQuick"
124124+ ]
125125+ ++ lib.optional withWebSockets "PyQt6.QtWebSockets"
126126+ ++ lib.optional withMultimedia "PyQt6.QtMultimedia"
127127+ # ++ lib.optional withConnectivity "PyQt6.QtConnectivity"
128128+ # ++ lib.optional withLocation "PyQt6.QtPositioning"
129129+ ;
130130+131131+ meta = with lib; {
132132+ description = "Python bindings for Qt6";
133133+ homepage = "https://riverbankcomputing.com/";
134134+ license = licenses.gpl3Only;
135135+ platforms = platforms.mesaPlatforms;
136136+ maintainers = with maintainers; [ LunNova ];
137137+ };
138138+}