From f90a11a9df7eb86c5b2b584e8fa01d985e0fb312 Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Tue, 24 Mar 2020 18:35:10 +0100 Subject: [PATCH 1/2] pythonPackages.matplotlib: add GTK and Qt wrapper hooks --- pkgs/development/python-modules/matplotlib/2.nix | 8 +++++--- pkgs/development/python-modules/matplotlib/default.nix | 8 +++++--- pkgs/top-level/python-packages.nix | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pkgs/development/python-modules/matplotlib/2.nix b/pkgs/development/python-modules/matplotlib/2.nix index dd25860795baf..53c1a3403b5ae 100644 --- a/pkgs/development/python-modules/matplotlib/2.nix +++ b/pkgs/development/python-modules/matplotlib/2.nix @@ -3,10 +3,10 @@ , freetype, libpng, pkgconfig, mock, pytz, pygobject3, gobject-introspection, functools32, subprocess32 , fetchpatch , enableGhostscript ? false, ghostscript ? null, gtk3 -, enableGtk3 ? false, cairo +, enableGtk3 ? false, cairo, wrapGAppsHook ? null # darwin has its own "MacOSX" backend , enableTk ? !stdenv.isDarwin, tcl ? null, tk ? null, tkinter ? null, libX11 ? null -, enableQt ? false, pyqt4 +, enableQt ? false, pyqt4 ? null, wrapQtAppsHook ? null , Cocoa , pythonOlder }: @@ -43,7 +43,9 @@ buildPythonPackage rec { buildInputs = [ which sphinx ] ++ stdenv.lib.optional enableGhostscript ghostscript - ++ stdenv.lib.optional stdenv.isDarwin [ Cocoa ]; + ++ stdenv.lib.optional stdenv.isDarwin Cocoa + ++ stdenv.lib.optional enableQt wrapQtAppsHook + ++ stdenv.lib.optional enableGtk3 wrapGAppsHook; propagatedBuildInputs = [ cycler dateutil nose numpy pyparsing tornado freetype kiwisolver diff --git a/pkgs/development/python-modules/matplotlib/default.nix b/pkgs/development/python-modules/matplotlib/default.nix index 45f3173974674..e0f094fc4832c 100644 --- a/pkgs/development/python-modules/matplotlib/default.nix +++ b/pkgs/development/python-modules/matplotlib/default.nix @@ -3,10 +3,10 @@ , freetype, libpng, pkgconfig, mock, pytz, pygobject3, gobject-introspection , certifi, pillow , enableGhostscript ? true, ghostscript ? null, gtk3 -, enableGtk3 ? false, cairo +, enableGtk3 ? false, cairo ? null, wrapGAppsHook ? null # darwin has its own "MacOSX" backend , enableTk ? !stdenv.isDarwin, tcl ? null, tk ? null, tkinter ? null, libX11 ? null -, enableQt ? false, pyqt5 ? null +, enableQt ? false, pyqt5 ? null, wrapQtAppsHook ? null , Cocoa , pythonOlder }: @@ -32,7 +32,9 @@ buildPythonPackage rec { XDG_RUNTIME_DIR = "/tmp"; - nativeBuildInputs = [ pkgconfig ]; + nativeBuildInputs = [ pkgconfig ] + ++ stdenv.lib.optional enableQt wrapQtAppsHook + ++ stdenv.lib.optional enableGtk3 wrapGAppsHook; buildInputs = [ which sphinx ] ++ stdenv.lib.optional enableGhostscript ghostscript diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index db0ef635e9a5d..e672fdff124cf 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -3542,6 +3542,7 @@ in { stdenv = if stdenv.isDarwin then pkgs.clangStdenv else pkgs.stdenv; inherit (pkgs.darwin.apple_sdk.frameworks) Cocoa; inherit (pkgs) pkgconfig; + inherit (pkgs.qt5) wrapQtAppsHook; }; matrix-client = callPackage ../development/python-modules/matrix-client { }; From af1c62d52aa7aeee7217c1fae87039261740dce6 Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Wed, 8 Apr 2020 17:56:14 +0200 Subject: [PATCH 2/2] python: propagate makeWrapper arguments Python libraries that have runtime dependencies, like Qt and GTK libraries, are currently not working. These are not included in the interpreter wrapper and no mechanism exist to do so automatically. This commit adds a `nix-support/make-wrapper-args` file that stores the makeWrapper arguments of a python derivation (created with buildPythonPackage). The arguments are loaded from python.buildEnv when creating the Python environment and passed to the makeWrapper invocation. --- .../interpreters/python/default.nix | 3 +- .../interpreters/python/hooks/default.nix | 6 ++++ .../python/hooks/propagate-wrapper-args.sh | 33 +++++++++++++++++++ .../python/mk-python-derivation.nix | 2 ++ .../interpreters/python/wrapper.nix | 21 +++++++++--- pkgs/top-level/python-packages.nix | 1 + 6 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 pkgs/development/interpreters/python/hooks/propagate-wrapper-args.sh diff --git a/pkgs/development/interpreters/python/default.nix b/pkgs/development/interpreters/python/default.nix index 773e365889b3b..0fa2ed2bd398b 100644 --- a/pkgs/development/interpreters/python/default.nix +++ b/pkgs/development/interpreters/python/default.nix @@ -34,7 +34,8 @@ with pkgs; isPyPy = lib.hasInfix "pypy" interpreter; buildEnv = callPackage ./wrapper.nix { python = self; inherit (pythonPackages) requiredPythonModules; }; - withPackages = import ./with-packages.nix { inherit buildEnv pythonPackages;}; + withPackages = import ./with-packages.nix { inherit buildEnv pythonPackages; }; + pkgs = pythonPackages; interpreter = "${self}/bin/${executable}"; inherit executable implementation libPrefix pythonVersion sitePackages; diff --git a/pkgs/development/interpreters/python/hooks/default.nix b/pkgs/development/interpreters/python/hooks/default.nix index d14eb9cbb09dd..9e670caca5f4b 100644 --- a/pkgs/development/interpreters/python/hooks/default.nix +++ b/pkgs/development/interpreters/python/hooks/default.nix @@ -63,6 +63,12 @@ in rec { }; } ./pip-install-hook.sh) {}; + propagateWrapperArgsHook = callPackage ({ }: + makeSetupHook { + name = "propagate-wrapper-args"; + deps = [ ]; + } ./propagate-wrapper-args.sh) {}; + pytestCheckHook = callPackage ({ pytest }: makeSetupHook { name = "pytest-check-hook"; diff --git a/pkgs/development/interpreters/python/hooks/propagate-wrapper-args.sh b/pkgs/development/interpreters/python/hooks/propagate-wrapper-args.sh new file mode 100644 index 0000000000000..8f2a2662c264c --- /dev/null +++ b/pkgs/development/interpreters/python/hooks/propagate-wrapper-args.sh @@ -0,0 +1,33 @@ +# Hook that propagates wrapper arguments up to the +# python interpreter buildEnv environment. +echo "Sourcing propagate-wrapper-args.sh" + +storeWrapperArgsHook() { + # Store the arguments for use by other derivations + # and the python interpreter derivation. + echo "Executing propagateWrapperArgsHook" + + mkdir -p "$out/nix-support" + if [ ${#qtWrapperArgs[@]} -ne 0 ]; then + printf '%s\n' "${qtWrapperArgs[@]}" >> "$out/nix-support/make-wrapper-args" + fi + if [ ${#gappsWrapperArgs[@]} -ne 0 ]; then + printf '%s\n' "${gappsWrapperArgs[@]}" >> "$out/nix-support/make-wrapper-args" + fi + if [ ${#makeWrapperArgs[@]} -ne 0 ]; then + printf '%s\n' "${makeWrapperArgs[@]}" >> "$out/nix-support/make-wrapper-args" + fi +} + +loadWrapperArgsHook() { + # Load the arguments from all the dependencies. + # Note: this hook *must* run after storeWrapperArgsHook to + # avoid an exponential duplication of the wrapper arguments. + for path in $propagatedBuildInputs "$@"; do + if [ -f "$path/nix-support/make-wrapper-args" ]; then + makeWrapperArgs+=$(cat "$path/nix-support/make-wrapper-args") + fi + done +} + +postFixupHooks+=(storeWrapperArgsHook loadWrapperArgsHook) diff --git a/pkgs/development/interpreters/python/mk-python-derivation.nix b/pkgs/development/interpreters/python/mk-python-derivation.nix index df945c645a828..26c1810cb7e81 100644 --- a/pkgs/development/interpreters/python/mk-python-derivation.nix +++ b/pkgs/development/interpreters/python/mk-python-derivation.nix @@ -14,6 +14,7 @@ , flitBuildHook , pipBuildHook , pipInstallHook +, propagateWrapperArgsHook , pythonCatchConflictsHook , pythonImportsCheckHook , pythonNamespacesHook @@ -113,6 +114,7 @@ let ensureNewerSourcesForZipFilesHook # move to wheel installer (pip) or builder (setuptools, flit, ...)? pythonRecompileBytecodeHook # Remove when solved https://github.com/NixOS/nixpkgs/issues/81441 pythonRemoveTestsDirHook + propagateWrapperArgsHook ] ++ lib.optionals catchConflicts [ setuptools pythonCatchConflictsHook ] ++ lib.optionals removeBinBytecode [ diff --git a/pkgs/development/interpreters/python/wrapper.nix b/pkgs/development/interpreters/python/wrapper.nix index dffad6b98f5e5..d3909abb1deb1 100644 --- a/pkgs/development/interpreters/python/wrapper.nix +++ b/pkgs/development/interpreters/python/wrapper.nix @@ -12,7 +12,7 @@ # Create a python executable that knows about additional packages. let env = let - paths = requiredPythonModules (extraLibs ++ [ python ] ) ; + paths = requiredPythonModules (extraLibs ++ [ python ]); pythonPath = "${placeholder "out"}/${python.sitePackages}"; pythonExecutable = "${placeholder "out"}/bin/${python.executable}"; in buildEnv { @@ -22,29 +22,40 @@ let inherit ignoreCollisions; extraOutputsToInstall = [ "out" ] ++ extraOutputsToInstall; - postBuild = '' + buildInputs = [ python.pkgs.propagateWrapperArgsHook ]; + + postBuild = with stdenv.lib; '' . "${makeWrapper}/nix-support/setup-hook" + # Load propagated wrapper arguments from each + # path in the environment. + loadWrapperArgsHook ${concatStringsSep " " paths} + if [ -L "$out/bin" ]; then unlink "$out/bin" fi mkdir -p "$out/bin" - for path in ${stdenv.lib.concatStringsSep " " paths}; do + for path in ${concatStringsSep " " paths}; do if [ -d "$path/bin" ]; then cd "$path/bin" for prg in *; do if [ -f "$prg" ]; then rm -f "$out/bin/$prg" if [ -x "$prg" ]; then - makeWrapper "$path/bin/$prg" "$out/bin/$prg" --set NIX_PYTHONPREFIX "$out" --set NIX_PYTHONEXECUTABLE ${pythonExecutable} --set NIX_PYTHONPATH ${pythonPath} ${if permitUserSite then "" else ''--set PYTHONNOUSERSITE "true"''} ${stdenv.lib.concatStringsSep " " makeWrapperArgs} + makeWrapper "$path/bin/$prg" "$out/bin/$prg" \ + --set NIX_PYTHONPREFIX "$out" \ + --set NIX_PYTHONEXECUTABLE ${pythonExecutable} \ + --set NIX_PYTHONPATH \ + ${pythonPath} \ + ${optionalString (!permitUserSite) ''--set PYTHONNOUSERSITE "true"''} \ + ''${makeWrapperArgs[@]} fi fi done fi done '' + postBuild; - inherit (python) meta; passthru = python.passthru // { diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index e672fdff124cf..c8ab2dac188d9 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -114,6 +114,7 @@ in { flitBuildHook pipBuildHook pipInstallHook + propagateWrapperArgsHook pytestCheckHook pythonCatchConflictsHook pythonImportsCheckHook