Something went wrong. Try again.
What happens if I push all of nixpkgs
Something went wrong. Try again.
11 kB · 314 lines
Nix
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315# Generic builder.
{ lib, config, python, wrapPython, unzip, ensureNewerSourcesForZipFilesHook# Whether the derivation provides a Python module or not., toPythonModule, namePrefix, update-python-libraries, setuptools, pypaBuildHook, pypaInstallHook, pythonCatchConflictsHook, pythonImportsCheckHook, pythonNamespacesHook, pythonOutputDistHook, pythonRemoveBinBytecodeHook, pythonRemoveTestsDirHook, pythonRuntimeDepsCheckHook, setuptoolsBuildHook, setuptoolsCheckHook, wheelUnpackHook, eggUnpackHook, eggBuildHook, eggInstallHook}:
{ name ? "${attrs.pname}-${attrs.version}"
# Build-time dependencies for the package, nativeBuildInputs ? []
# Run-time dependencies for the package, buildInputs ? []
# Dependencies needed for running the checkPhase.# These are added to buildInputs when doCheck = true., checkInputs ? [], nativeCheckInputs ? []
# propagate build dependencies so in case we have A -> B -> C,# C can import package A propagated by B, propagatedBuildInputs ? []
# DEPRECATED: use propagatedBuildInputs, pythonPath ? []
# Enabled to detect some (native)BuildInputs mistakes, strictDeps ? true
, outputs ? [ "out" ]
# used to disable derivation, useful for specific python versions, disabled ? false
# Raise an error if two packages are installed with the same name# TODO: For cross we probably need a different PYTHONPATH, or not# add the runtime deps until after buildPhase., catchConflicts ? (python.stdenv.hostPlatform == python.stdenv.buildPlatform)
# Additional arguments to pass to the makeWrapper function, which wraps# generated binaries., makeWrapperArgs ? []
# Skip wrapping of python programs altogether, dontWrapPythonPrograms ? false
# Don't use Pip to install a wheel# Note this is actually a variable for the pipInstallPhase in pip's setupHook.# It's included here to prevent an infinite recursion., dontUsePipInstall ? false
# Skip setting the PYTHONNOUSERSITE environment variable in wrapped programs, permitUserSite ? false
# Remove bytecode from bin folder.# When a Python script has the extension `.py`, bytecode is generated# Typically, executables in bin have no extension, so no bytecode is generated.# However, some packages do provide executables with extensions, and thus bytecode is generated., removeBinBytecode ? true
# pyproject = true <-> format = "pyproject"# pyproject = false <-> format = "other"# https://github.com/NixOS/nixpkgs/issues/253154, pyproject ? null
# Several package formats are supported.# "setuptools" : Install a common setuptools/distutils based package. This builds a wheel.# "wheel" : Install from a pre-compiled wheel.# "pyproject": Install a package using a ``pyproject.toml`` file (PEP517). This builds a wheel.# "egg": Install a package from an egg.# "other" : Provide your own buildPhase and installPhase., format ? null
, meta ? {}
, passthru ? {}
, doCheck ? config.doCheckByDefault or false
, disabledTestPaths ? []
# Allow passing in a custom stdenv to buildPython*, stdenv ? python.stdenv
, ... } @ attrs:
assert (pyproject != null) -> (format == null);
let format' = if pyproject != null then if pyproject then "pyproject" else "other" else if format != null then format else "setuptools";
withDistOutput = lib.elem format' ["pyproject" "setuptools" "wheel"];
name_ = name;
validatePythonMatches = attrName: let isPythonModule = drv: # all pythonModules have the pythonModule attribute (drv ? "pythonModule") # Some pythonModules are turned in to a pythonApplication by setting the field to false && (!builtins.isBool drv.pythonModule); isMismatchedPython = drv: drv.pythonModule != python;
optionalLocation = let pos = builtins.unsafeGetAttrPos (if attrs ? "pname" then "pname" else "name") attrs; in lib.optionalString (pos != null) " at ${pos.file}:${toString pos.line}:${toString pos.column}";
leftPadName = name: against: let len = lib.max (lib.stringLength name) (lib.stringLength against); in lib.strings.fixedWidthString len " " name;
throwMismatch = drv: let myName = "'${namePrefix}${name}'"; theirName = "'${drv.name}'"; in throw '' Python version mismatch in ${myName}:
The Python derivation ${myName} depends on a Python derivation named ${theirName}, but the two derivations use different versions of Python:
${leftPadName myName theirName} uses ${python} ${leftPadName theirName myName} uses ${toString drv.pythonModule}
Possible solutions:
* If ${theirName} is a Python library, change the reference to ${theirName} in the ${attrName} of ${myName} to use a ${theirName} built from the same version of Python
* If ${theirName} is used as a tool during the build, move the reference to ${theirName} in ${myName} from ${attrName} to nativeBuildInputs
* If ${theirName} provides executables that are called at run time, pass its bin path to makeWrapperArgs:
makeWrapperArgs = [ "--prefix PATH : ''${lib.makeBinPath [ ${lib.getName drv } ] }" ];
${optionalLocation} '';
checkDrv = drv: if (isPythonModule drv) && (isMismatchedPython drv) then throwMismatch drv else drv;
in inputs: builtins.map (checkDrv) inputs;
isBootstrapInstallPackage = builtins.elem (attrs.pname or null) [ "flit-core" "installer" ];
isBootstrapPackage = isBootstrapInstallPackage || builtins.elem (attrs.pname or null) ([ "build" "packaging" "pyproject-hooks" "wheel" ] ++ lib.optionals (python.pythonOlder "3.11") [ "tomli" ]);
isSetuptoolsDependency = builtins.elem (attrs.pname or null) [ "setuptools" "wheel" ];
# Keep extra attributes from `attrs`, e.g., `patchPhase', etc. self = toPythonModule (stdenv.mkDerivation ((builtins.removeAttrs attrs [ "disabled" "checkPhase" "checkInputs" "nativeCheckInputs" "doCheck" "doInstallCheck" "dontWrapPythonPrograms" "catchConflicts" "pyproject" "format" "disabledTestPaths" "outputs" "stdenv" ]) // {
name = namePrefix + name_;
nativeBuildInputs = [ python wrapPython ensureNewerSourcesForZipFilesHook # move to wheel installer (pip) or builder (setuptools, flit, ...)? pythonRemoveTestsDirHook ] ++ lib.optionals (catchConflicts && !isBootstrapPackage && !isSetuptoolsDependency) [ # # 1. When building a package that is also part of the bootstrap chain, we # must ignore conflicts after installation, because there will be one with # the package in the bootstrap. # # 2. When a package is a dependency of setuptools, we must ignore conflicts # because the hook that checks for conflicts uses setuptools. # pythonCatchConflictsHook ] ++ lib.optionals removeBinBytecode [ pythonRemoveBinBytecodeHook ] ++ lib.optionals (lib.hasSuffix "zip" (attrs.src.name or "")) [ unzip ] ++ lib.optionals (format' == "setuptools") [ setuptoolsBuildHook ] ++ lib.optionals (format' == "pyproject") [( if isBootstrapPackage then pypaBuildHook.override { inherit (python.pythonOnBuildForHost.pkgs.bootstrap) build; wheel = null; } else pypaBuildHook ) ( if isBootstrapPackage then pythonRuntimeDepsCheckHook.override { inherit (python.pythonOnBuildForHost.pkgs.bootstrap) packaging; } else pythonRuntimeDepsCheckHook )] ++ lib.optionals (format' == "wheel") [ wheelUnpackHook ] ++ lib.optionals (format' == "egg") [ eggUnpackHook eggBuildHook eggInstallHook ] ++ lib.optionals (format' != "other") [( if isBootstrapInstallPackage then pypaInstallHook.override { inherit (python.pythonOnBuildForHost.pkgs.bootstrap) installer; } else pypaInstallHook )] ++ lib.optionals (stdenv.buildPlatform == stdenv.hostPlatform) [ # This is a test, however, it should be ran independent of the checkPhase and checkInputs pythonImportsCheckHook ] ++ lib.optionals (python.pythonAtLeast "3.3") [ # Optionally enforce PEP420 for python3 pythonNamespacesHook ] ++ lib.optionals withDistOutput [ pythonOutputDistHook ] ++ nativeBuildInputs;
buildInputs = validatePythonMatches "buildInputs" (buildInputs ++ pythonPath);
propagatedBuildInputs = validatePythonMatches "propagatedBuildInputs" (propagatedBuildInputs ++ [ # we propagate python even for packages transformed with 'toPythonApplication' # this pollutes the PATH but avoids rebuilds # see https://github.com/NixOS/nixpkgs/issues/170887 for more context python ]);
inherit strictDeps;
LANG = "${if python.stdenv.isDarwin then "en_US" else "C"}.UTF-8";
# Python packages don't have a checkPhase, only an installCheckPhase doCheck = false; doInstallCheck = attrs.doCheck or true; nativeInstallCheckInputs = [ ] ++ lib.optionals (format' == "setuptools") [ # Longer-term we should get rid of this and require # users of this function to set the `installCheckPhase` or # pass in a hook that sets it. setuptoolsCheckHook ] ++ nativeCheckInputs; installCheckInputs = checkInputs;
postFixup = lib.optionalString (!dontWrapPythonPrograms) '' wrapPythonPrograms '' + attrs.postFixup or "";
# Python packages built through cross-compilation are always for the host platform. disallowedReferences = lib.optionals (python.stdenv.hostPlatform != python.stdenv.buildPlatform) [ python.pythonOnBuildForHost ];
outputs = outputs ++ lib.optional withDistOutput "dist";
meta = { # default to python's platforms platforms = python.meta.platforms; isBuildPythonPackage = python.meta.platforms; } // meta; } // lib.optionalAttrs (attrs?checkPhase) { # If given use the specified checkPhase, otherwise use the setup hook. # Longer-term we should get rid of `checkPhase` and use `installCheckPhase`. installCheckPhase = attrs.checkPhase; } // lib.optionalAttrs (disabledTestPaths != []) { disabledTestPaths = lib.escapeShellArgs disabledTestPaths; }));
passthru.updateScript = let filename = builtins.head (lib.splitString ":" self.meta.position); in attrs.passthru.updateScript or [ update-python-libraries filename ];in lib.extendDerivation (disabled -> throw "${name} not supported for interpreter ${python.executable}") passthru self