1# Generic builder.
2
3{ lib
4, config
5, python
6, wrapPython
7, setuptools
8, unzip
9, ensureNewerSourcesForZipFilesHook
10# Whether the derivation provides a Python module or not.
11, toPythonModule
12, namePrefix
13, writeScript
14, update-python-libraries
15}:
16
17{ name ? "${attrs.pname}-${attrs.version}"
18
19# Build-time dependencies for the package
20, nativeBuildInputs ? []
21
22# Run-time dependencies for the package
23, buildInputs ? []
24
25# Dependencies needed for running the checkPhase.
26# These are added to buildInputs when doCheck = true.
27, checkInputs ? []
28
29# propagate build dependencies so in case we have A -> B -> C,
30# C can import package A propagated by B
31, propagatedBuildInputs ? []
32
33# DEPRECATED: use propagatedBuildInputs
34, pythonPath ? []
35
36# Enabled to detect some (native)BuildInputs mistakes
37, strictDeps ? true
38
39# used to disable derivation, useful for specific python versions
40, disabled ? false
41
42# Raise an error if two packages are installed with the same name
43, catchConflicts ? true
44
45# Additional arguments to pass to the makeWrapper function, which wraps
46# generated binaries.
47, makeWrapperArgs ? []
48
49# Skip wrapping of python programs altogether
50, dontWrapPythonPrograms ? false
51
52# Remove bytecode from bin folder.
53# When a Python script has the extension `.py`, bytecode is generated
54# Typically, executables in bin have no extension, so no bytecode is generated.
55# However, some packages do provide executables with extensions, and thus bytecode is generated.
56, removeBinBytecode ? true
57
58, meta ? {}
59
60, passthru ? {}
61
62, doCheck ? config.doCheckByDefault or false
63
64, ... } @ attrs:
65
66
67# Keep extra attributes from `attrs`, e.g., `patchPhase', etc.
68if disabled
69then throw "${name} not supported for interpreter ${python.executable}"
70else
71
72let self = toPythonModule (python.stdenv.mkDerivation (builtins.removeAttrs attrs [
73 "disabled" "checkInputs" "doCheck" "doInstallCheck" "dontWrapPythonPrograms" "catchConflicts"
74 ] // {
75
76 name = namePrefix + name;
77
78 nativeBuildInputs = [
79 python
80 wrapPython
81 ensureNewerSourcesForZipFilesHook
82 setuptools
83# ++ lib.optional catchConflicts setuptools # If we no longer propagate setuptools
84 ] ++ lib.optionals (lib.hasSuffix "zip" (attrs.src.name or "")) [
85 unzip
86 ] ++ nativeBuildInputs;
87
88 buildInputs = buildInputs ++ pythonPath;
89
90 # Propagate python and setuptools. We should stop propagating setuptools.
91 propagatedBuildInputs = propagatedBuildInputs ++ [ python setuptools ];
92
93 inherit strictDeps;
94
95 LANG = "${if python.stdenv.isDarwin then "en_US" else "C"}.UTF-8";
96
97 # Python packages don't have a checkPhase, only an installCheckPhase
98 doCheck = false;
99 doInstallCheck = doCheck;
100 installCheckInputs = checkInputs;
101
102 postFixup = lib.optionalString (!dontWrapPythonPrograms) ''
103 wrapPythonPrograms
104 '' + lib.optionalString removeBinBytecode ''
105 if [ -d "$out/bin" ]; then
106 rm -rf "$out/bin/__pycache__" # Python 3
107 find "$out/bin" -type f -name "*.pyc" -delete # Python 2
108 fi
109 '' + lib.optionalString catchConflicts ''
110 # Check if we have two packages with the same name in the closure and fail.
111 # If this happens, something went wrong with the dependencies specs.
112 # Intentionally kept in a subdirectory, see catch_conflicts/README.md.
113 ${python.pythonForBuild.interpreter} ${./catch_conflicts}/catch_conflicts.py
114 '' + attrs.postFixup or '''';
115
116 # Python packages built through cross-compilation are always for the host platform.
117 disallowedReferences = lib.optionals (python.stdenv.hostPlatform != python.stdenv.buildPlatform) [ python.pythonForBuild ];
118
119 meta = {
120 # default to python's platforms
121 platforms = python.meta.platforms;
122 isBuildPythonPackage = python.meta.platforms;
123 } // meta;
124}));
125
126passthru.updateScript = let
127 filename = builtins.head (lib.splitString ":" self.meta.position);
128 in attrs.passthru.updateScript or [ update-python-libraries filename ];
129in lib.extendDerivation true passthru self