at 22.05-pre 6.3 kB view raw
1# Generic builder. 2 3{ lib 4, config 5, python 6, wrapPython 7, unzip 8, ensureNewerSourcesForZipFilesHook 9# Whether the derivation provides a Python module or not. 10, toPythonModule 11, namePrefix 12, update-python-libraries 13, setuptools 14, flitBuildHook 15, pipBuildHook 16, pipInstallHook 17, pythonCatchConflictsHook 18, pythonImportsCheckHook 19, pythonNamespacesHook 20, pythonRemoveBinBytecodeHook 21, pythonRemoveTestsDirHook 22, setuptoolsBuildHook 23, setuptoolsCheckHook 24, wheelUnpackHook 25, eggUnpackHook 26, eggBuildHook 27, eggInstallHook 28}: 29 30{ name ? "${attrs.pname}-${attrs.version}" 31 32# Build-time dependencies for the package 33, nativeBuildInputs ? [] 34 35# Run-time dependencies for the package 36, buildInputs ? [] 37 38# Dependencies needed for running the checkPhase. 39# These are added to buildInputs when doCheck = true. 40, checkInputs ? [] 41 42# propagate build dependencies so in case we have A -> B -> C, 43# C can import package A propagated by B 44, propagatedBuildInputs ? [] 45 46# DEPRECATED: use propagatedBuildInputs 47, pythonPath ? [] 48 49# Enabled to detect some (native)BuildInputs mistakes 50, strictDeps ? true 51 52# used to disable derivation, useful for specific python versions 53, disabled ? false 54 55# Raise an error if two packages are installed with the same name 56# TODO: For cross we probably need a different PYTHONPATH, or not 57# add the runtime deps until after buildPhase. 58, catchConflicts ? (python.stdenv.hostPlatform == python.stdenv.buildPlatform) 59 60# Additional arguments to pass to the makeWrapper function, which wraps 61# generated binaries. 62, makeWrapperArgs ? [] 63 64# Skip wrapping of python programs altogether 65, dontWrapPythonPrograms ? false 66 67# Don't use Pip to install a wheel 68# Note this is actually a variable for the pipInstallPhase in pip's setupHook. 69# It's included here to prevent an infinite recursion. 70, dontUsePipInstall ? false 71 72# Skip setting the PYTHONNOUSERSITE environment variable in wrapped programs 73, permitUserSite ? false 74 75# Remove bytecode from bin folder. 76# When a Python script has the extension `.py`, bytecode is generated 77# Typically, executables in bin have no extension, so no bytecode is generated. 78# However, some packages do provide executables with extensions, and thus bytecode is generated. 79, removeBinBytecode ? true 80 81# Several package formats are supported. 82# "setuptools" : Install a common setuptools/distutils based package. This builds a wheel. 83# "wheel" : Install from a pre-compiled wheel. 84# "flit" : Install a flit package. This builds a wheel. 85# "pyproject": Install a package using a ``pyproject.toml`` file (PEP517). This builds a wheel. 86# "egg": Install a package from an egg. 87# "other" : Provide your own buildPhase and installPhase. 88, format ? "setuptools" 89 90, meta ? {} 91 92, passthru ? {} 93 94, doCheck ? config.doCheckByDefault or false 95 96, disabledTestPaths ? [] 97 98, ... } @ attrs: 99 100 101# Keep extra attributes from `attrs`, e.g., `patchPhase', etc. 102if disabled 103then throw "${name} not supported for interpreter ${python.executable}" 104else 105 106let 107 inherit (python) stdenv; 108 109 name_ = name; 110 111 self = toPythonModule (stdenv.mkDerivation ((builtins.removeAttrs attrs [ 112 "disabled" "checkPhase" "checkInputs" "doCheck" "doInstallCheck" "dontWrapPythonPrograms" "catchConflicts" "format" 113 "disabledTestPaths" 114 ]) // { 115 116 name = namePrefix + name_; 117 118 nativeBuildInputs = [ 119 python 120 wrapPython 121 ensureNewerSourcesForZipFilesHook # move to wheel installer (pip) or builder (setuptools, flit, ...)? 122 pythonRemoveTestsDirHook 123 ] ++ lib.optionals catchConflicts [ 124 setuptools pythonCatchConflictsHook 125 ] ++ lib.optionals removeBinBytecode [ 126 pythonRemoveBinBytecodeHook 127 ] ++ lib.optionals (lib.hasSuffix "zip" (attrs.src.name or "")) [ 128 unzip 129 ] ++ lib.optionals (format == "setuptools") [ 130 setuptoolsBuildHook 131 ] ++ lib.optionals (format == "flit") [ 132 flitBuildHook 133 ] ++ lib.optionals (format == "pyproject") [ 134 pipBuildHook 135 ] ++ lib.optionals (format == "wheel") [ 136 wheelUnpackHook 137 ] ++ lib.optionals (format == "egg") [ 138 eggUnpackHook eggBuildHook eggInstallHook 139 ] ++ lib.optionals (!(format == "other") || dontUsePipInstall) [ 140 pipInstallHook 141 ] ++ lib.optionals (stdenv.buildPlatform == stdenv.hostPlatform) [ 142 # This is a test, however, it should be ran independent of the checkPhase and checkInputs 143 pythonImportsCheckHook 144 ] ++ lib.optionals (python.pythonAtLeast "3.3") [ 145 # Optionally enforce PEP420 for python3 146 pythonNamespacesHook 147 ] ++ nativeBuildInputs; 148 149 buildInputs = buildInputs ++ pythonPath; 150 151 propagatedBuildInputs = propagatedBuildInputs ++ [ python ]; 152 153 inherit strictDeps; 154 155 LANG = "${if python.stdenv.isDarwin then "en_US" else "C"}.UTF-8"; 156 157 # Python packages don't have a checkPhase, only an installCheckPhase 158 doCheck = false; 159 doInstallCheck = attrs.doCheck or true; 160 installCheckInputs = [ 161 ] ++ lib.optionals (format == "setuptools") [ 162 # Longer-term we should get rid of this and require 163 # users of this function to set the `installCheckPhase` or 164 # pass in a hook that sets it. 165 setuptoolsCheckHook 166 ] ++ checkInputs; 167 168 postFixup = lib.optionalString (!dontWrapPythonPrograms) '' 169 wrapPythonPrograms 170 '' + attrs.postFixup or ""; 171 172 # Python packages built through cross-compilation are always for the host platform. 173 disallowedReferences = lib.optionals (python.stdenv.hostPlatform != python.stdenv.buildPlatform) [ python.pythonForBuild ]; 174 175 meta = { 176 # default to python's platforms 177 platforms = python.meta.platforms; 178 isBuildPythonPackage = python.meta.platforms; 179 } // lib.optionalAttrs (attrs?pname) { 180 mainProgram = attrs.pname; 181 } // meta; 182 } // lib.optionalAttrs (attrs?checkPhase) { 183 # If given use the specified checkPhase, otherwise use the setup hook. 184 # Longer-term we should get rid of `checkPhase` and use `installCheckPhase`. 185 installCheckPhase = attrs.checkPhase; 186 } // lib.optionalAttrs (disabledTestPaths != []) { 187 disabledTestPaths = lib.escapeShellArgs disabledTestPaths; 188 })); 189 190 passthru.updateScript = let 191 filename = builtins.head (lib.splitString ":" self.meta.position); 192 in attrs.passthru.updateScript or [ update-python-libraries filename ]; 193in lib.extendDerivation true passthru self