1{ lib, stdenv, fetchurl, fetchpatch, fetchgit
2, bzip2
3, expat
4, libffi
5, gdbm
6, xz
7, mailcap, mimetypesSupport ? true
8, ncurses
9, openssl
10, openssl_legacy
11, readline
12, sqlite
13, tcl ? null, tk ? null, tix ? null, libX11 ? null, xorgproto ? null, x11Support ? false
14, bluez ? null, bluezSupport ? false
15, zlib
16, tzdata ? null
17, libxcrypt
18, self
19, configd
20, darwin
21, windows
22, autoreconfHook
23, autoconf-archive
24, pkg-config
25, python-setup-hook
26, nukeReferences
27# For the Python package set
28, packageOverrides ? (self: super: {})
29, pkgsBuildBuild
30, pkgsBuildHost
31, pkgsBuildTarget
32, pkgsHostHost
33, pkgsTargetTarget
34, sourceVersion
35, hash
36, passthruFun
37, bash
38, stripConfig ? false
39, stripIdlelib ? false
40, stripTests ? false
41, stripTkinter ? false
42, rebuildBytecode ? true
43, stripBytecode ? true
44, includeSiteCustomize ? true
45, static ? stdenv.hostPlatform.isStatic
46, enableFramework ? false
47, enableOptimizations ? false
48# these dont build for windows
49, withGdbm ? !stdenv.hostPlatform.isWindows
50, withReadline ? !stdenv.hostPlatform.isWindows
51# enableNoSemanticInterposition is a subset of the enableOptimizations flag that doesn't harm reproducibility.
52# clang starts supporting `-fno-sematic-interposition` with version 10
53, enableNoSemanticInterposition ? (!stdenv.cc.isClang || (stdenv.cc.isClang && lib.versionAtLeast stdenv.cc.version "10"))
54# enableLTO is a subset of the enableOptimizations flag that doesn't harm reproducibility.
55# enabling LTO on 32bit arch causes downstream packages to fail when linking
56# enabling LTO on *-darwin causes python3 to fail when linking.
57, enableLTO ? stdenv.is64bit && stdenv.isLinux
58, reproducibleBuild ? false
59, pythonAttr ? "python${sourceVersion.major}${sourceVersion.minor}"
60, noldconfigPatch ? ./. + "/${sourceVersion.major}.${sourceVersion.minor}/no-ldconfig.patch"
61, testers
62} @ inputs:
63
64# Note: this package is used for bootstrapping fetchurl, and thus
65# cannot use fetchpatch! All mutable patches (generated by GitHub or
66# cgit) that are needed here should be included directly in Nixpkgs as
67# files.
68
69assert x11Support -> tcl != null
70 && tk != null
71 && xorgproto != null
72 && libX11 != null;
73
74assert bluezSupport -> bluez != null;
75
76assert enableFramework -> stdenv.isDarwin;
77
78assert lib.assertMsg (reproducibleBuild -> stripBytecode)
79 "Deterministic builds require stripping bytecode.";
80
81assert lib.assertMsg (reproducibleBuild -> (!enableOptimizations))
82 "Deterministic builds are not achieved when optimizations are enabled.";
83
84assert lib.assertMsg (reproducibleBuild -> (!rebuildBytecode))
85 "Deterministic builds are not achieved when (default unoptimized) bytecode is created.";
86
87with lib;
88
89let
90 # some python packages need legacy ciphers, so we're using openssl 3, but with that config
91 # null check for Minimal
92 openssl' = if openssl != null then openssl_legacy else null;
93
94 buildPackages = pkgsBuildHost;
95 inherit (passthru) pythonOnBuildForHost;
96
97 inherit (darwin.apple_sdk.frameworks) Cocoa;
98
99 tzdataSupport = tzdata != null && passthru.pythonAtLeast "3.9";
100
101 passthru = let
102 # When we override the interpreter we also need to override the spliced versions of the interpreter
103 inputs' = lib.filterAttrs (n: v: ! lib.isDerivation v && n != "passthruFun") inputs;
104 override = attr: let python = attr.override (inputs' // { self = python; }); in python;
105 in passthruFun rec {
106 inherit self sourceVersion packageOverrides;
107 implementation = "cpython";
108 libPrefix = "python${pythonVersion}";
109 executable = libPrefix;
110 pythonVersion = with sourceVersion; "${major}.${minor}";
111 sitePackages = "lib/${libPrefix}/site-packages";
112 inherit hasDistutilsCxxPatch pythonAttr;
113 pythonOnBuildForBuild = override pkgsBuildBuild.${pythonAttr};
114 pythonOnBuildForHost = override pkgsBuildHost.${pythonAttr};
115 pythonOnBuildForTarget = override pkgsBuildTarget.${pythonAttr};
116 pythonOnHostForHost = override pkgsHostHost.${pythonAttr};
117 pythonOnTargetForTarget = lib.optionalAttrs (lib.hasAttr pythonAttr pkgsTargetTarget) (override pkgsTargetTarget.${pythonAttr});
118 };
119
120 version = with sourceVersion; "${major}.${minor}.${patch}${suffix}";
121
122 nativeBuildInputs = optionals (!stdenv.isDarwin) [
123 autoreconfHook
124 pkg-config
125 autoconf-archive # needed for AX_CHECK_COMPILE_FLAG
126 ] ++ [
127 nukeReferences
128 ] ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
129 buildPackages.stdenv.cc
130 pythonOnBuildForHost
131 ] ++ optionals (stdenv.cc.isClang && (!stdenv.hostPlatform.useAndroidPrebuilt or false) && (enableLTO || enableOptimizations)) [
132 stdenv.cc.cc.libllvm.out
133 ];
134
135 buildInputs = filter (p: p != null) ([
136 zlib bzip2 expat xz libffi libxcrypt ]
137 ++ optional withGdbm gdbm
138 ++ [ sqlite ]
139 ++ optional withReadline readline
140 ++ [ ncurses openssl' ]
141 ++ optionals x11Support [ tcl tk libX11 xorgproto ]
142 ++ optionals (bluezSupport && stdenv.isLinux) [ bluez ]
143 ++ optionals stdenv.isDarwin [ configd ])
144
145 ++ optionals enableFramework [ Cocoa ]
146 ++ optionals stdenv.hostPlatform.isMinGW [ windows.mingw_w64_pthreads windows.dlfcn ]
147 ++ optionals tzdataSupport [ tzdata ]; # `zoneinfo` module
148
149 hasDistutilsCxxPatch = !(stdenv.cc.isGNU or false);
150
151 pythonOnBuildForHostInterpreter = if stdenv.hostPlatform == stdenv.buildPlatform then
152 "$out/bin/python"
153 else pythonOnBuildForHost.interpreter;
154
155 src = fetchurl {
156 url = with sourceVersion; "https://www.python.org/ftp/python/${major}.${minor}.${patch}/Python-${version}.tar.xz";
157 inherit hash;
158 };
159
160 # The CPython interpreter contains a _sysconfigdata_<platform specific suffix>
161 # module that is imported by the sysconfig and distutils.sysconfig modules.
162 # The sysconfigdata module is generated at build time and contains settings
163 # required for building Python extension modules, such as include paths and
164 # other compiler flags. By default, the sysconfigdata module is loaded from
165 # the currently running interpreter (ie. the build platform interpreter), but
166 # when cross-compiling we want to load it from the host platform interpreter.
167 # This can be done using the _PYTHON_SYSCONFIGDATA_NAME environment variable.
168 # The _PYTHON_HOST_PLATFORM variable also needs to be set to get the correct
169 # platform suffix on extension modules. The correct values for these variables
170 # are not documented, and must be derived from the configure script (see links
171 # below).
172 sysconfigdataHook = with stdenv.hostPlatform; with passthru; let
173 machdep = if isWindows then "win32" else parsed.kernel.name; # win32 is added by Fedora’s patch
174
175 # https://github.com/python/cpython/blob/e488e300f5c01289c10906c2e53a8e43d6de32d8/configure.ac#L428
176 # The configure script uses "arm" as the CPU name for all 32-bit ARM
177 # variants when cross-compiling, but native builds include the version
178 # suffix, so we do the same.
179 pythonHostPlatform = let
180 cpu = {
181 # According to PEP600, Python's name for the Power PC
182 # architecture is "ppc", not "powerpc". Without the Rosetta
183 # Stone below, the PEP600 requirement that "${ARCH} matches
184 # the return value from distutils.util.get_platform()" fails.
185 # https://peps.python.org/pep-0600/
186 powerpc = "ppc";
187 powerpcle = "ppcle";
188 powerpc64 = "ppc64";
189 powerpc64le = "ppc64le";
190 }.${parsed.cpu.name} or parsed.cpu.name;
191 in "${machdep}-${cpu}";
192
193 # https://github.com/python/cpython/blob/e488e300f5c01289c10906c2e53a8e43d6de32d8/configure.ac#L724
194 multiarchCpu =
195 if isAarch32 then
196 if parsed.cpu.significantByte.name == "littleEndian" then "arm" else "armeb"
197 else if isx86_32 then "i386"
198 else parsed.cpu.name;
199
200 pythonAbiName = let
201 # python's build doesn't match the nixpkgs abi in some cases.
202 # https://github.com/python/cpython/blob/e488e300f5c01289c10906c2e53a8e43d6de32d8/configure.ac#L724
203 nixpkgsPythonAbiMappings = {
204 "gnuabielfv2" = "gnu";
205 "muslabielfv2" = "musl";
206 };
207 pythonAbi = nixpkgsPythonAbiMappings.${parsed.abi.name} or parsed.abi.name;
208 in
209 # Python <3.11 doesn't distinguish musl and glibc and always prefixes with "gnu"
210 if lib.versionOlder version "3.11" then
211 replaceStrings [ "musl" ] [ "gnu" ] pythonAbi
212 else
213 pythonAbi;
214
215 multiarch =
216 if isDarwin then "darwin"
217 else if isWindows then ""
218 else "${multiarchCpu}-${machdep}-${pythonAbiName}";
219
220 abiFlags = optionalString isPy37 "m";
221
222 # https://github.com/python/cpython/blob/e488e300f5c01289c10906c2e53a8e43d6de32d8/configure.ac#L78
223 pythonSysconfigdataName = "_sysconfigdata_${abiFlags}_${machdep}_${multiarch}";
224 in ''
225 sysconfigdataHook() {
226 if [ "$1" = '${placeholder "out"}' ]; then
227 export _PYTHON_HOST_PLATFORM='${pythonHostPlatform}'
228 export _PYTHON_SYSCONFIGDATA_NAME='${pythonSysconfigdataName}'
229 fi
230 }
231
232 addEnvHooks "$hostOffset" sysconfigdataHook
233 '';
234
235 execSuffix = stdenv.hostPlatform.extensions.executable;
236in with passthru; stdenv.mkDerivation (finalAttrs: {
237 pname = "python3";
238 inherit src version;
239
240 inherit nativeBuildInputs;
241 buildInputs = lib.optionals (!stdenv.hostPlatform.isWindows) [ bash ] ++ buildInputs; # bash is only used for patchShebangs
242
243
244 prePatch = optionalString stdenv.isDarwin ''
245 substituteInPlace configure --replace '`/usr/bin/arch`' '"i386"'
246 '' + optionalString (pythonOlder "3.9" && stdenv.isDarwin && x11Support) ''
247 # Broken on >= 3.9; replaced with ./3.9/darwin-tcl-tk.patch
248 substituteInPlace setup.py --replace /Library/Frameworks /no-such-path
249 '';
250
251 patches = optionals (version == "3.10.9") [
252 # https://github.com/python/cpython/issues/100160
253 ./3.10/asyncio-deprecation.patch
254 ] ++ optionals (version == "3.11.1") [
255 # https://github.com/python/cpython/issues/100160
256 (fetchpatch {
257 name = "asyncio-deprecation-3.11.patch";
258 url = "https://github.com/python/cpython/commit/3fae04b10e2655a20a3aadb5e0d63e87206d0c67.diff";
259 revert = true;
260 excludes = [ "Misc/NEWS.d/*" ];
261 hash = "sha256-PmkXf2D9trtW1gXZilRIWgdg2Y47JfELq1z4DuG3wJY=";
262 })
263 ] ++ [
264 # Disable the use of ldconfig in ctypes.util.find_library (since
265 # ldconfig doesn't work on NixOS), and don't use
266 # ctypes.util.find_library during the loading of the uuid module
267 # (since it will do a futile invocation of gcc (!) to find
268 # libuuid, slowing down program startup a lot).
269 noldconfigPatch
270 # Make sure that the virtualenv activation scripts are
271 # owner-writable, so venvs can be recreated without permission
272 # errors.
273 ./virtualenv-permissions.patch
274 ] ++ optionals mimetypesSupport [
275 # Make the mimetypes module refer to the right file
276 ./mimetypes.patch
277 ] ++ optionals (pythonAtLeast "3.7" && pythonOlder "3.11") [
278 # Fix darwin build https://bugs.python.org/issue34027
279 ./3.7/darwin-libutil.patch
280 ] ++ optionals (pythonAtLeast "3.11") [
281 ./3.11/darwin-libutil.patch
282 ] ++ optionals (pythonAtLeast "3.9" && pythonOlder "3.11" && stdenv.isDarwin) [
283 # Stop checking for TCL/TK in global macOS locations
284 ./3.9/darwin-tcl-tk.patch
285 ] ++ optionals (isPy3k && hasDistutilsCxxPatch && pythonOlder "3.12") [
286 # Fix for http://bugs.python.org/issue1222585
287 # Upstream distutils is calling C compiler to compile C++ code, which
288 # only works for GCC and Apple Clang. This makes distutils to call C++
289 # compiler when needed.
290 (
291 if pythonAtLeast "3.7" && pythonOlder "3.11" then
292 ./3.7/python-3.x-distutils-C++.patch
293 else if pythonAtLeast "3.11" then
294 ./3.11/python-3.x-distutils-C++.patch
295 else
296 fetchpatch {
297 url = "https://bugs.python.org/file48016/python-3.x-distutils-C++.patch";
298 sha256 = "1h18lnpx539h5lfxyk379dxwr8m2raigcjixkf133l4xy3f4bzi2";
299 }
300 )
301 ] ++ optionals (pythonAtLeast "3.7" && pythonOlder "3.12") [
302 # LDSHARED now uses $CC instead of gcc. Fixes cross-compilation of extension modules.
303 ./3.8/0001-On-all-posix-systems-not-just-Darwin-set-LDSHARED-if.patch
304 # Use sysconfigdata to find headers. Fixes cross-compilation of extension modules.
305 ./3.7/fix-finding-headers-when-cross-compiling.patch
306 ] ++ optionals (pythonOlder "3.12") [
307 # https://github.com/python/cpython/issues/90656
308 ./loongarch-support.patch
309 ] ++ optionals (pythonAtLeast "3.11" && pythonOlder "3.13") [
310 # backport fix for https://github.com/python/cpython/issues/95855
311 ./platform-triplet-detection.patch
312 ] ++ optionals (stdenv.hostPlatform.isMinGW) (let
313 # https://src.fedoraproject.org/rpms/mingw-python3
314 mingw-patch = fetchgit {
315 name = "mingw-python-patches";
316 url = "https://src.fedoraproject.org/rpms/mingw-python3.git";
317 rev = "45c45833ab9e5480ad0ae00778a05ebf35812ed4"; # for python 3.11.5 at the time of writing.
318 sha256 = "sha256-KIyNvO6MlYTrmSy9V/DbzXm5OsIuyT/BEpuo7Umm9DI=";
319 };
320 in [
321 "${mingw-patch}/*.patch"
322 ]);
323
324 postPatch = optionalString (!stdenv.hostPlatform.isWindows) ''
325 substituteInPlace Lib/subprocess.py \
326 --replace "'/bin/sh'" "'${bash}/bin/sh'"
327 '' + optionalString mimetypesSupport ''
328 substituteInPlace Lib/mimetypes.py \
329 --replace "@mime-types@" "${mailcap}"
330 '' + optionalString (pythonOlder "3.13" && x11Support && (tix != null)) ''
331 substituteInPlace "Lib/tkinter/tix.py" --replace "os.environ.get('TIX_LIBRARY')" "os.environ.get('TIX_LIBRARY') or '${tix}/lib'"
332 '';
333
334 env = {
335 CPPFLAGS = concatStringsSep " " (map (p: "-I${getDev p}/include") buildInputs);
336 LDFLAGS = concatStringsSep " " (map (p: "-L${getLib p}/lib") buildInputs);
337 LIBS = "${optionalString (!stdenv.isDarwin) "-lcrypt"}";
338 NIX_LDFLAGS = lib.optionalString (stdenv.cc.isGNU && !stdenv.hostPlatform.isStatic) ({
339 "glibc" = "-lgcc_s";
340 "musl" = "-lgcc_eh";
341 }."${stdenv.hostPlatform.libc}" or "");
342 # Determinism: We fix the hashes of str, bytes and datetime objects.
343 PYTHONHASHSEED=0;
344 };
345
346 configureFlags = [
347 "--without-ensurepip"
348 "--with-system-expat"
349 "--with-system-ffi"
350 ] ++ optionals (!static && !enableFramework) [
351 "--enable-shared"
352 ] ++ optionals enableFramework [
353 "--enable-framework=${placeholder "out"}/Library/Frameworks"
354 ] ++ optionals enableOptimizations [
355 "--enable-optimizations"
356 ] ++ optionals enableLTO [
357 "--with-lto"
358 ] ++ optionals (pythonOlder "3.7") [
359 # This is unconditionally true starting in CPython 3.7.
360 "--with-threads"
361 ] ++ optionals (sqlite != null && isPy3k) [
362 "--enable-loadable-sqlite-extensions"
363 ] ++ optionals (openssl' != null) [
364 "--with-openssl=${openssl'.dev}"
365 ] ++ optionals (libxcrypt != null) [
366 "CFLAGS=-I${libxcrypt}/include"
367 "LIBS=-L${libxcrypt}/lib"
368 ] ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
369 "ac_cv_buggy_getaddrinfo=no"
370 # Assume little-endian IEEE 754 floating point when cross compiling
371 "ac_cv_little_endian_double=yes"
372 "ac_cv_big_endian_double=no"
373 "ac_cv_mixed_endian_double=no"
374 "ac_cv_x87_double_rounding=yes"
375 "ac_cv_tanh_preserves_zero_sign=yes"
376 # Generally assume that things are present and work
377 "ac_cv_posix_semaphores_enabled=yes"
378 "ac_cv_broken_sem_getvalue=no"
379 "ac_cv_wchar_t_signed=yes"
380 "ac_cv_rshift_extends_sign=yes"
381 "ac_cv_broken_nice=no"
382 "ac_cv_broken_poll=no"
383 "ac_cv_working_tzset=yes"
384 "ac_cv_have_long_long_format=yes"
385 "ac_cv_have_size_t_format=yes"
386 "ac_cv_computed_gotos=yes"
387 # Both fail when building for windows, normally configure checks this by itself but on other platforms this is set to yes always.
388 "ac_cv_file__dev_ptmx=${if stdenv.hostPlatform.isWindows then "no" else "yes"}"
389 "ac_cv_file__dev_ptc=${if stdenv.hostPlatform.isWindows then "no" else "yes"}"
390 ] ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform && pythonAtLeast "3.11") [
391 "--with-build-python=${pythonOnBuildForHostInterpreter}"
392 ] ++ optionals stdenv.hostPlatform.isLinux [
393 # Never even try to use lchmod on linux,
394 # don't rely on detecting glibc-isms.
395 "ac_cv_func_lchmod=no"
396 ] ++ optionals tzdataSupport [
397 "--with-tzpath=${tzdata}/share/zoneinfo"
398 ] ++ optional static "LDFLAGS=-static"
399 ++ optional (execSuffix != "") "--with-suffix=${execSuffix}";
400
401 preConfigure = optionalString (pythonOlder "3.12") ''
402 for i in /usr /sw /opt /pkg; do # improve purity
403 substituteInPlace ./setup.py --replace $i /no-such-path
404 done
405 '' + optionalString stdenv.isDarwin ''
406 # Override the auto-detection in setup.py, which assumes a universal build
407 export PYTHON_DECIMAL_WITH_MACHINE=${if stdenv.isAarch64 then "uint128" else "x64"}
408 '' + optionalString (stdenv.isDarwin && x11Support && pythonAtLeast "3.11") ''
409 export TCLTK_LIBS="-L${tcl}/lib -L${tk}/lib -l${tcl.libPrefix} -l${tk.libPrefix}"
410 export TCLTK_CFLAGS="-I${tcl}/include -I${tk}/include"
411 '' + optionalString (isPy3k && pythonOlder "3.7") ''
412 # Determinism: The interpreter is patched to write null timestamps when compiling Python files
413 # so Python doesn't try to update the bytecode when seeing frozen timestamps in Nix's store.
414 export DETERMINISTIC_BUILD=1;
415 '' + optionalString stdenv.hostPlatform.isMusl ''
416 export NIX_CFLAGS_COMPILE+=" -DTHREAD_STACK_SIZE=0x100000"
417 '' +
418
419 # enableNoSemanticInterposition essentially sets that CFLAG -fno-semantic-interposition
420 # which changes how symbols are looked up. This essentially means we can't override
421 # libpython symbols via LD_PRELOAD anymore. This is common enough as every build
422 # that uses --enable-optimizations has the same "issue".
423 #
424 # The Fedora wiki has a good article about their journey towards enabling this flag:
425 # https://fedoraproject.org/wiki/Changes/PythonNoSemanticInterpositionSpeedup
426 optionalString enableNoSemanticInterposition ''
427 export CFLAGS_NODIST="-fno-semantic-interposition"
428 '';
429
430 setupHook = python-setup-hook sitePackages;
431
432 postInstall = let
433 # References *not* to nuke from (sys)config files
434 keep-references = concatMapStringsSep " " (val: "-e ${val}") ([
435 (placeholder "out") libxcrypt
436 ] ++ optionals tzdataSupport [
437 tzdata
438 ]);
439 in lib.optionalString enableFramework ''
440 for dir in include lib share; do
441 ln -s $out/Library/Frameworks/Python.framework/Versions/Current/$dir $out/$dir
442 done
443 '' + ''
444 # needed for some packages, especially packages that backport functionality
445 # to 2.x from 3.x
446 for item in $out/lib/${libPrefix}/test/*; do
447 if [[ "$item" != */test_support.py*
448 && "$item" != */test/support
449 && "$item" != */test/libregrtest
450 && "$item" != */test/regrtest.py* ]]; then
451 rm -rf "$item"
452 else
453 echo $item
454 fi
455 done
456 touch $out/lib/${libPrefix}/test/__init__.py
457
458 # Determinism: Windows installers were not deterministic.
459 # We're also not interested in building Windows installers.
460 find "$out" -name 'wininst*.exe' | xargs -r rm -f
461
462 # Use Python3 as default python
463 ln -s "$out/bin/idle3" "$out/bin/idle"
464 ln -s "$out/bin/pydoc3" "$out/bin/pydoc"
465 ln -s "$out/bin/python3${execSuffix}" "$out/bin/python${execSuffix}"
466 ln -s "$out/bin/python3-config" "$out/bin/python-config"
467 ln -s "$out/lib/pkgconfig/python3.pc" "$out/lib/pkgconfig/python.pc"
468 ln -sL "$out/share/man/man1/python3.1.gz" "$out/share/man/man1/python.1.gz"
469
470 # Get rid of retained dependencies on -dev packages, and remove
471 # some $TMPDIR references to improve binary reproducibility.
472 # Note that the .pyc file of _sysconfigdata.py should be regenerated!
473 for i in $out/lib/${libPrefix}/_sysconfigdata*.py $out/lib/${libPrefix}/config-${sourceVersion.major}${sourceVersion.minor}*/Makefile; do
474 sed -i $i -e "s|$TMPDIR|/no-such-path|g"
475 done
476
477 # Further get rid of references. https://github.com/NixOS/nixpkgs/issues/51668
478 find $out/lib/python*/config-* -type f -print -exec nuke-refs ${keep-references} '{}' +
479 find $out/lib -name '_sysconfigdata*.py*' -print -exec nuke-refs ${keep-references} '{}' +
480
481 # Make the sysconfigdata module accessible on PYTHONPATH
482 # This allows build Python to import host Python's sysconfigdata
483 mkdir -p "$out/${sitePackages}"
484 ln -s "$out/lib/${libPrefix}/"_sysconfigdata*.py "$out/${sitePackages}/"
485 '' + lib.optionalString (pythonOlder "3.8") ''
486 # This is gone in Python >= 3.8
487 ln -s "$out/include/${executable}m" "$out/include/${executable}"
488 '' + optionalString stripConfig ''
489 rm -R $out/bin/python*-config $out/lib/python*/config-*
490 '' + optionalString stripIdlelib ''
491 # Strip IDLE (and turtledemo, which uses it)
492 rm -R $out/bin/idle* $out/lib/python*/{idlelib,turtledemo}
493 '' + optionalString stripTkinter ''
494 rm -R $out/lib/python*/tkinter
495 '' + optionalString stripTests ''
496 # Strip tests
497 rm -R $out/lib/python*/test $out/lib/python*/**/test{,s}
498 '' + optionalString includeSiteCustomize ''
499 # Include a sitecustomize.py file
500 cp ${../sitecustomize.py} $out/${sitePackages}/sitecustomize.py
501
502 '' + optionalString stripBytecode ''
503 # Determinism: deterministic bytecode
504 # First we delete all old bytecode.
505 find $out -type d -name __pycache__ -print0 | xargs -0 -I {} rm -rf "{}"
506 '' + optionalString rebuildBytecode ''
507 # Python 3.7 implements PEP 552, introducing support for deterministic bytecode.
508 # compileall uses the therein introduced checked-hash method by default when
509 # `SOURCE_DATE_EPOCH` is set.
510 # We exclude lib2to3 because that's Python 2 code which fails
511 # We build 3 levels of optimized bytecode. Note the default level, without optimizations,
512 # is not reproducible yet. https://bugs.python.org/issue29708
513 # Not creating bytecode will result in a large performance loss however, so we do build it.
514 find $out -name "*.py" | ${pythonOnBuildForHostInterpreter} -m compileall -q -f -x "lib2to3" -i -
515 find $out -name "*.py" | ${pythonOnBuildForHostInterpreter} -O -m compileall -q -f -x "lib2to3" -i -
516 find $out -name "*.py" | ${pythonOnBuildForHostInterpreter} -OO -m compileall -q -f -x "lib2to3" -i -
517 '' + ''
518 # *strip* shebang from libpython gdb script - it should be dual-syntax and
519 # interpretable by whatever python the gdb in question is using, which may
520 # not even match the major version of this python. doing this after the
521 # bytecode compilations for the same reason - we don't want bytecode generated.
522 mkdir -p $out/share/gdb
523 sed '/^#!/d' Tools/gdb/libpython.py > $out/share/gdb/libpython.py
524
525 # Disable system-wide pip installation. See https://peps.python.org/pep-0668/.
526 cat <<'EXTERNALLY_MANAGED' > $out/lib/${libPrefix}/EXTERNALLY-MANAGED
527 [externally-managed]
528 Error=This command has been disabled as it tries to modify the immutable
529 `/nix/store` filesystem.
530
531 To use Python with Nix and nixpkgs, have a look at the online documentation:
532 <https://nixos.org/manual/nixpkgs/stable/#python>.
533 EXTERNALLY_MANAGED
534 '' + optionalString stdenv.hostPlatform.isWindows ''
535 # Shebang files that link against the build python. Shebang don’t work on windows
536 rm $out/bin/2to3*
537 rm $out/bin/idle*
538 rm $out/bin/pydoc*
539
540 echo linking DLLs for python’s compiled librairies
541 linkDLLsInfolder $out/lib/python*/lib-dynload/
542 '';
543
544 preFixup = lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) ''
545 # Ensure patch-shebangs uses shebangs of host interpreter.
546 export PATH=${lib.makeBinPath [ "$out" ]}:$PATH
547 '';
548
549 # Add CPython specific setup-hook that configures distutils.sysconfig to
550 # always load sysconfigdata from host Python.
551 postFixup = lib.optionalString (!stdenv.hostPlatform.isDarwin) ''
552 cat << "EOF" >> "$out/nix-support/setup-hook"
553 ${sysconfigdataHook}
554 EOF
555 '';
556
557 # Enforce that we don't have references to the OpenSSL -dev package, which we
558 # explicitly specify in our configure flags above.
559 disallowedReferences =
560 lib.optionals (openssl' != null && !static && !enableFramework) [ openssl'.dev ]
561 ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
562 # Ensure we don't have references to build-time packages.
563 # These typically end up in shebangs.
564 pythonOnBuildForHost buildPackages.bash
565 ];
566
567 separateDebugInfo = true;
568
569 passthru = passthru // {
570 doc = stdenv.mkDerivation {
571 inherit src;
572 name = "python${pythonVersion}-${version}-doc";
573
574 dontConfigure = true;
575
576 dontBuild = true;
577
578 sphinxRoot = "Doc";
579
580 postInstallSphinx = ''
581 mv $out/share/doc/* $out/share/doc/python${pythonVersion}-${version}
582 '';
583
584 nativeBuildInputs = with pkgsBuildBuild.python3.pkgs; [ sphinxHook python-docs-theme ];
585 };
586
587 tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
588 };
589
590 enableParallelBuilding = true;
591
592 meta = {
593 homepage = "https://www.python.org";
594 changelog = let
595 majorMinor = lib.versions.majorMinor version;
596 dashedVersion = lib.replaceStrings [ "." "a" ] [ "-" "-alpha-" ] version;
597 in
598 if sourceVersion.suffix == "" then
599 "https://docs.python.org/release/${version}/whatsnew/changelog.html"
600 else
601 "https://docs.python.org/${majorMinor}/whatsnew/changelog.html#python-${dashedVersion}";
602 description = "A high-level dynamically-typed programming language";
603 longDescription = ''
604 Python is a remarkably powerful dynamic programming language that
605 is used in a wide variety of application domains. Some of its key
606 distinguishing features include: clear, readable syntax; strong
607 introspection capabilities; intuitive object orientation; natural
608 expression of procedural code; full modularity, supporting
609 hierarchical packages; exception-based error handling; and very
610 high level dynamic data types.
611 '';
612 license = licenses.psfl;
613 pkgConfigModules = [ "python3" ];
614 platforms = platforms.linux ++ platforms.darwin ++ platforms.windows;
615 maintainers = with maintainers; [ fridh ];
616 mainProgram = executable;
617 };
618})