nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 stdenv,
4 fetchurl,
5 fetchpatch,
6 fetchgit,
7
8 # build dependencies
9 autoconf-archive,
10 autoreconfHook,
11 nukeReferences,
12 pkg-config,
13 python-setup-hook,
14
15 # high level switches
16 withMinimalDeps ? false,
17
18 # runtime dependencies
19 bzip2,
20 withExpat ? !withMinimalDeps,
21 expat,
22 libffi,
23 libuuid,
24 libxcrypt,
25 withMpdecimal ? !withMinimalDeps,
26 mpdecimal,
27 ncurses,
28 withOpenssl ? !withMinimalDeps,
29 openssl,
30 withSqlite ? !withMinimalDeps,
31 sqlite,
32 xz,
33 zlib,
34 zstd,
35
36 # platform-specific dependencies
37 bashNonInteractive,
38 windows,
39
40 # optional dependencies
41 bluezSupport ? !withMinimalDeps && stdenv.hostPlatform.isLinux,
42 bluez-headers,
43 mimetypesSupport ? !withMinimalDeps,
44 mailcap,
45 tzdata,
46 withGdbm ? !withMinimalDeps && !stdenv.hostPlatform.isWindows,
47 gdbm,
48 withReadline ? !withMinimalDeps && !stdenv.hostPlatform.isWindows,
49 readline,
50
51 # splicing/cross
52 pythonAttr ? "python${sourceVersion.major}${sourceVersion.minor}",
53 self,
54 pkgsBuildBuild,
55 pkgsBuildHost,
56 pkgsBuildTarget,
57 pkgsHostHost,
58 pkgsTargetTarget,
59 __splices ? { },
60
61 # build customization
62 sourceVersion,
63 hash,
64 passthruFun,
65 stripConfig ? withMinimalDeps,
66 stripIdlelib ? withMinimalDeps,
67 stripTests ? withMinimalDeps,
68 stripTkinter ? withMinimalDeps,
69 rebuildBytecode ? !withMinimalDeps,
70 stripBytecode ? true,
71 includeSiteCustomize ? !withMinimalDeps,
72 static ? stdenv.hostPlatform.isStatic,
73 enableFramework ? false,
74 noldconfigPatch ? ./. + "/${sourceVersion.major}.${sourceVersion.minor}/no-ldconfig.patch",
75 enableGIL ? true,
76 enableDebug ? false,
77
78 # pgo (not reproducible) + -fno-semantic-interposition
79 # https://docs.python.org/3/using/configure.html#cmdoption-enable-optimizations
80 enableOptimizations ? false,
81
82 # improves performance, but remains reproducible
83 enableNoSemanticInterposition ? true,
84
85 # enabling LTO on 32bit arch causes downstream packages to fail when linking
86 enableLTO ?
87 !withMinimalDeps
88 && (stdenv.hostPlatform.isDarwin || (stdenv.hostPlatform.is64bit && stdenv.hostPlatform.isLinux)),
89
90 # enable asserts to ensure the build remains reproducible
91 reproducibleBuild ? false,
92
93 # for the Python package set
94 packageOverrides ? (self: super: { }),
95
96 # tests
97 testers,
98
99 # allow pythonMinimal to prevent accidental dependencies it doesn't want
100 # Having this as an option is useful to allow overriding, eg. adding things to
101 # python3Minimal
102 allowedReferenceNames ? if withMinimalDeps then [ "bashNonInteractive" ] else [ ],
103
104}@inputs:
105
106# Note: this package is used for bootstrapping fetchurl, and thus
107# cannot use fetchpatch! All mutable patches (generated by GitHub or
108# cgit) that are needed here should be included directly in Nixpkgs as
109# files.
110
111assert lib.assertMsg (
112 enableFramework -> stdenv.hostPlatform.isDarwin
113) "Framework builds are only supported on Darwin.";
114
115assert lib.assertMsg (
116 reproducibleBuild -> stripBytecode
117) "Deterministic builds require stripping bytecode.";
118
119assert lib.assertMsg (
120 reproducibleBuild -> (!enableOptimizations)
121) "Deterministic builds are not achieved when optimizations are enabled.";
122
123assert lib.assertMsg (
124 reproducibleBuild -> (!rebuildBytecode)
125) "Deterministic builds are not achieved when (default unoptimized) bytecode is created.";
126
127let
128 inherit (lib)
129 concatMapStringsSep
130 concatStringsSep
131 enableFeature
132 getDev
133 getLib
134 optionals
135 optionalString
136 replaceStrings
137 ;
138
139 withLibxcrypt =
140 (!withMinimalDeps)
141 &&
142 # mixes libc and libxcrypt headers and libs and causes segfaults on importing crypt
143 (!stdenv.hostPlatform.isFreeBSD)
144 &&
145 # crypt module was removed in 3.13
146 passthru.pythonOlder "3.13";
147
148 buildPackages = pkgsBuildHost;
149 inherit (passthru) pythonOnBuildForHost;
150
151 tzdataSupport = !withMinimalDeps && tzdata != null && passthru.pythonAtLeast "3.9";
152
153 passthru =
154 let
155 # When we override the interpreter we also need to override the spliced versions of the interpreter
156 inputs' = lib.filterAttrs (n: v: n != "passthruFun" && !lib.isDerivation v) inputs;
157 # Memoization of the splices to avoid re-evaluating this function for all combinations of splices e.g.
158 # python3.pythonOnBuildForHost.pythonOnBuildForTarget == python3.pythonOnBuildForTarget by consuming
159 # __splices as an arg and using the cache if populated.
160 splices = {
161 pythonOnBuildForBuild = override pkgsBuildBuild.${pythonAttr};
162 pythonOnBuildForHost = override pkgsBuildHost.${pythonAttr};
163 pythonOnBuildForTarget = override pkgsBuildTarget.${pythonAttr};
164 pythonOnHostForHost = override pkgsHostHost.${pythonAttr};
165 pythonOnTargetForTarget = lib.optionalAttrs (lib.hasAttr pythonAttr pkgsTargetTarget) (
166 override pkgsTargetTarget.${pythonAttr}
167 );
168 }
169 // __splices;
170 override =
171 attr:
172 let
173 python = attr.override (
174 inputs'
175 // {
176 self = python;
177 __splices = splices;
178 }
179 );
180 in
181 python;
182 in
183 passthruFun rec {
184 inherit self sourceVersion packageOverrides;
185 implementation = "cpython";
186 libPrefix = "python${pythonVersion}${lib.optionalString (!enableGIL) "t"}";
187 executable = libPrefix;
188 pythonVersion = with sourceVersion; "${major}.${minor}";
189 sitePackages = "lib/${libPrefix}/site-packages";
190 inherit hasDistutilsCxxPatch pythonAttr;
191 inherit (splices)
192 pythonOnBuildForBuild
193 pythonOnBuildForHost
194 pythonOnBuildForTarget
195 pythonOnHostForHost
196 pythonOnTargetForTarget
197 ;
198
199 pythonABITags = [
200 "abi3"
201 "none"
202 "cp${sourceVersion.major}${sourceVersion.minor}${lib.optionalString (!enableGIL) "t"}"
203 ];
204 };
205
206 version = with sourceVersion; "${major}.${minor}.${patch}${suffix}";
207
208 nativeBuildInputs = [
209 nukeReferences
210 ]
211 ++
212 optionals
213 (
214 (!stdenv.hostPlatform.isDarwin && !withMinimalDeps)
215 || (stdenv.hostPlatform != stdenv.buildPlatform && stdenv.hostPlatform.isFreeBSD)
216 )
217 [
218 autoconf-archive # needed for AX_CHECK_COMPILE_FLAG
219 autoreconfHook
220 ]
221 ++
222 optionals ((!stdenv.hostPlatform.isDarwin || passthru.pythonAtLeast "3.14") && !withMinimalDeps)
223 [
224 pkg-config
225 ]
226 ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
227 buildPackages.stdenv.cc
228 pythonOnBuildForHost
229 ]
230 ++
231 optionals
232 (
233 stdenv.cc.isClang
234 && (!stdenv.hostPlatform.useAndroidPrebuilt or false)
235 && (enableLTO || enableOptimizations)
236 )
237 [
238 stdenv.cc.cc.libllvm.out
239 ];
240
241 buildInputs = lib.filter (p: p != null) (
242 optionals (!withMinimalDeps) [
243 bzip2
244 libffi
245 libuuid
246 ncurses
247 xz
248 zlib
249 ]
250 ++ optionals withLibxcrypt [
251 libxcrypt
252 ]
253 ++ optionals withOpenssl [
254 openssl
255 ]
256 ++ optionals withSqlite [
257 sqlite
258 ]
259 ++ optionals withMpdecimal [
260 mpdecimal
261 ]
262 ++ optionals withExpat [
263 expat
264 ]
265 ++ optionals (passthru.pythonAtLeast "3.14") [
266 zstd
267 ]
268 ++ optionals bluezSupport [
269 bluez-headers
270 ]
271 ++ optionals stdenv.hostPlatform.isMinGW [
272 windows.dlfcn
273 windows.pthreads
274 ]
275 ++ optionals tzdataSupport [
276 tzdata
277 ]
278 ++ optionals withGdbm [
279 gdbm
280 ]
281 ++ optionals withReadline [
282 readline
283 ]
284 );
285
286 hasDistutilsCxxPatch = !(stdenv.cc.isGNU or false);
287
288 pythonOnBuildForHostInterpreter =
289 if stdenv.hostPlatform == stdenv.buildPlatform then
290 "$out/bin/python"
291 else
292 pythonOnBuildForHost.interpreter;
293
294 src = fetchurl {
295 url =
296 with sourceVersion;
297 "https://www.python.org/ftp/python/${major}.${minor}.${patch}/Python-${version}.tar.xz";
298 inherit hash;
299 };
300
301 # win32 is added by Fedora’s patch
302 machdep = if stdenv.hostPlatform.isWindows then "win32" else stdenv.hostPlatform.parsed.kernel.name;
303
304 # https://github.com/python/cpython/blob/e488e300f5c01289c10906c2e53a8e43d6de32d8/configure.ac#L428
305 # The configure script uses "arm" as the CPU name for all 32-bit ARM
306 # variants when cross-compiling, but native builds include the version
307 # suffix, so we do the same.
308 pythonHostPlatform =
309 let
310 cpu =
311 {
312 # According to PEP600, Python's name for the Power PC
313 # architecture is "ppc", not "powerpc". Without the Rosetta
314 # Stone below, the PEP600 requirement that "${ARCH} matches
315 # the return value from distutils.util.get_platform()" fails.
316 # https://peps.python.org/pep-0600/
317 powerpc = "ppc";
318 powerpcle = "ppcle";
319 powerpc64 = "ppc64";
320 powerpc64le = "ppc64le";
321 }
322 .${stdenv.hostPlatform.parsed.cpu.name} or stdenv.hostPlatform.parsed.cpu.name;
323 in
324 "${machdep}-${cpu}";
325
326 execSuffix = stdenv.hostPlatform.extensions.executable;
327in
328with passthru;
329stdenv.mkDerivation (finalAttrs: {
330 pname = "python3";
331 inherit src version;
332
333 inherit nativeBuildInputs;
334 buildInputs =
335 lib.optionals (!stdenv.hostPlatform.isWindows) [
336 bashNonInteractive # only required for patchShebangs
337 ]
338 ++ buildInputs;
339
340 prePatch = optionalString stdenv.hostPlatform.isDarwin ''
341 substituteInPlace configure --replace-fail '`/usr/bin/arch`' '"i386"'
342 '';
343
344 patches = [
345 # Disable the use of ldconfig in ctypes.util.find_library (since
346 # ldconfig doesn't work on NixOS), and don't use
347 # ctypes.util.find_library during the loading of the uuid module
348 # (since it will do a futile invocation of gcc (!) to find
349 # libuuid, slowing down program startup a lot).
350 noldconfigPatch
351 ]
352 ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform && stdenv.hostPlatform.isFreeBSD) [
353 # Cross compilation only supports a limited number of "known good"
354 # configurations. If you're reading this and it's been a long time
355 # since this diff, consider submitting this patch upstream!
356 ./freebsd-cross.patch
357 ]
358 ++ optionals (pythonOlder "3.13") [
359 # Make sure that the virtualenv activation scripts are
360 # owner-writable, so venvs can be recreated without permission
361 # errors.
362 ./virtualenv-permissions.patch
363 ]
364 ++ optionals (pythonAtLeast "3.13") [
365 ./3.13/virtualenv-permissions.patch
366 ]
367 ++ optionals mimetypesSupport [
368 # Make the mimetypes module refer to the right file
369 ./mimetypes.patch
370 ]
371 ++ optionals (pythonAtLeast "3.9" && pythonOlder "3.11" && stdenv.hostPlatform.isDarwin) [
372 # Stop checking for TCL/TK in global macOS locations
373 ./3.9/darwin-tcl-tk.patch
374 ]
375 ++ optionals (hasDistutilsCxxPatch && pythonOlder "3.12") [
376 # Fix for http://bugs.python.org/issue1222585
377 # Upstream distutils is calling C compiler to compile C++ code, which
378 # only works for GCC and Apple Clang. This makes distutils to call C++
379 # compiler when needed.
380 (
381 if pythonAtLeast "3.7" && pythonOlder "3.11" then
382 ./3.7/python-3.x-distutils-C++.patch
383 else if pythonAtLeast "3.11" then
384 ./3.11/python-3.x-distutils-C++.patch
385 else
386 fetchpatch {
387 url = "https://bugs.python.org/file48016/python-3.x-distutils-C++.patch";
388 sha256 = "1h18lnpx539h5lfxyk379dxwr8m2raigcjixkf133l4xy3f4bzi2";
389 }
390 )
391 ]
392 ++ optionals (pythonAtLeast "3.7" && pythonOlder "3.12") [
393 # LDSHARED now uses $CC instead of gcc. Fixes cross-compilation of extension modules.
394 ./3.8/0001-On-all-posix-systems-not-just-Darwin-set-LDSHARED-if.patch
395 # Use sysconfigdata to find headers. Fixes cross-compilation of extension modules.
396 ./3.7/fix-finding-headers-when-cross-compiling.patch
397 ]
398 ++ optionals (pythonOlder "3.12") [
399 # https://github.com/python/cpython/issues/90656
400 ./loongarch-support.patch
401 # fix failing tests with openssl >= 3.4
402 # https://github.com/python/cpython/pull/127361
403 ]
404 ++ optionals (pythonAtLeast "3.11" && pythonOlder "3.13") [
405 # backport fix for https://github.com/python/cpython/issues/95855
406 ./platform-triplet-detection.patch
407 ]
408 ++ optionals (version == "3.13.10" || version == "3.14.1") [
409 # https://github.com/python/cpython/issues/142218
410 ./${lib.versions.majorMinor version}/gh-142218.patch
411 ]
412 ++ optionals (stdenv.hostPlatform.isMinGW) (
413 let
414 # https://src.fedoraproject.org/rpms/mingw-python3
415 mingw-patch = fetchgit {
416 name = "mingw-python-patches";
417 url = "https://src.fedoraproject.org/rpms/mingw-python3.git";
418 rev = "3edecdbfb4bbf1276d09cd5e80e9fb3dd88c9511"; # for python 3.11.9 at the time of writing.
419 hash = "sha256-kpXoIHlz53+0FAm/fK99ZBdNUg0u13erOr1XP2FSkQY=";
420 };
421 in
422 (map (f: "${mingw-patch}/${f}") [
423 # The other patches in that repo are already applied to 3.11.10
424 "mingw-python3_distutils.patch"
425 "mingw-python3_frozenmain.patch"
426 "mingw-python3_make-sysconfigdata.py-relocatable.patch"
427 "mingw-python3_mods-failed.patch"
428 "mingw-python3_module-select.patch"
429 "mingw-python3_module-socket.patch"
430 "mingw-python3_modules.patch"
431 "mingw-python3_platform-mingw.patch"
432 "mingw-python3_posix-layout.patch"
433 "mingw-python3_pthread_threadid.patch"
434 "mingw-python3_pythonw.patch"
435 "mingw-python3_setenv.patch"
436 "mingw-python3_win-modules.patch"
437 ])
438 );
439
440 postPatch =
441 optionalString (!stdenv.hostPlatform.isWindows) ''
442 substituteInPlace Lib/subprocess.py \
443 --replace-fail "'/bin/sh'" "'${bashNonInteractive}/bin/sh'"
444 ''
445 + optionalString mimetypesSupport ''
446 substituteInPlace Lib/mimetypes.py \
447 --replace-fail "@mime-types@" "${mailcap}"
448 '';
449
450 env = {
451 CPPFLAGS = concatStringsSep " " (map (p: "-I${getDev p}/include") buildInputs);
452 LDFLAGS = concatStringsSep " " (map (p: "-L${getLib p}/lib") buildInputs);
453 LIBS = "${optionalString (!stdenv.hostPlatform.isDarwin && withLibxcrypt) "-lcrypt"}";
454 NIX_LDFLAGS = lib.optionalString (stdenv.cc.isGNU && !stdenv.hostPlatform.isStatic) (
455 {
456 "glibc" = "-lgcc_s";
457 "musl" = "-lgcc_eh";
458 }
459 ."${stdenv.hostPlatform.libc}" or ""
460 );
461 # Determinism: We fix the hashes of str, bytes and datetime objects.
462 PYTHONHASHSEED = 0;
463 };
464
465 # https://docs.python.org/3/using/configure.html
466 configureFlags = [
467 "--without-ensurepip"
468 ]
469 ++ optionals withExpat [
470 "--with-system-expat"
471 ]
472 ++ optionals withMpdecimal [
473 "--with-system-libmpdec"
474 ]
475 ++ optionals withOpenssl [
476 "--with-openssl=${openssl.dev}"
477 ]
478 ++ optionals tzdataSupport [
479 "--with-tzpath=${tzdata}/share/zoneinfo"
480 ]
481 ++ optionals (execSuffix != "") [
482 "--with-suffix=${execSuffix}"
483 ]
484 ++ optionals enableLTO [
485 "--with-lto"
486 ]
487 ++ optionals (!static && !enableFramework) [
488 "--enable-shared"
489 ]
490 ++ optionals enableFramework [
491 "--enable-framework=${placeholder "out"}/Library/Frameworks"
492 ]
493 ++ optionals (pythonAtLeast "3.13") [
494 (enableFeature enableGIL "gil")
495 ]
496 ++ optionals enableOptimizations [
497 "--enable-optimizations"
498 ]
499 ++ optionals enableDebug [
500 "--with-pydebug"
501 ]
502 ++ optionals withSqlite [
503 "--enable-loadable-sqlite-extensions"
504 ]
505 ++ optionals withLibxcrypt [
506 "CFLAGS=-I${libxcrypt}/include"
507 "LIBS=-L${libxcrypt}/lib"
508 ]
509 ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
510 "ac_cv_buggy_getaddrinfo=no"
511 # Assume little-endian IEEE 754 floating point when cross compiling
512 "ac_cv_little_endian_double=yes"
513 "ac_cv_big_endian_double=no"
514 "ac_cv_mixed_endian_double=no"
515 "ac_cv_x87_double_rounding=yes"
516 "ac_cv_tanh_preserves_zero_sign=yes"
517 # Generally assume that things are present and work
518 "ac_cv_posix_semaphores_enabled=yes"
519 "ac_cv_broken_sem_getvalue=no"
520 "ac_cv_wchar_t_signed=yes"
521 "ac_cv_rshift_extends_sign=yes"
522 "ac_cv_broken_nice=no"
523 "ac_cv_broken_poll=no"
524 "ac_cv_working_tzset=yes"
525 "ac_cv_have_long_long_format=yes"
526 "ac_cv_have_size_t_format=yes"
527 "ac_cv_computed_gotos=yes"
528 # Both fail when building for windows, normally configure checks this by itself but on other platforms this is set to yes always.
529 "ac_cv_file__dev_ptmx=${lib.boolToYesNo (!stdenv.hostPlatform.isWindows)}"
530 "ac_cv_file__dev_ptc=${lib.boolToYesNo (!stdenv.hostPlatform.isWindows)}"
531 ]
532 ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform && pythonAtLeast "3.11") [
533 "--with-build-python=${pythonOnBuildForHostInterpreter}"
534 ]
535 ++ optionals stdenv.hostPlatform.isLinux [
536 # Never even try to use lchmod on linux,
537 # don't rely on detecting glibc-isms.
538 "ac_cv_func_lchmod=no"
539 ]
540 ++ optionals static [
541 "--disable-test-modules"
542 "LDFLAGS=-static"
543 "MODULE_BUILDTYPE=static"
544 ]
545 ++ optionals (stdenv.hostPlatform.isStatic && stdenv.hostPlatform.isMusl) [
546 # dlopen is a no-op in static musl builds, and since we build everything without -fPIC it's better not to pretend.
547 "ac_cv_func_dlopen=no"
548 ];
549
550 preConfigure = ''
551 # Attempt to purify some of the host info collection
552 sed -E -i -e 's/uname -r/echo/g' -e 's/uname -n/echo nixpkgs/g' config.guess
553 sed -E -i -e 's/uname -r/echo/g' -e 's/uname -n/echo nixpkgs/g' configure
554 ''
555 + optionalString (pythonOlder "3.12") ''
556 # Improve purity
557 for path in /usr /sw /opt /pkg; do
558 substituteInPlace ./setup.py --replace-warn $path /no-such-path
559 done
560 ''
561 + optionalString (stdenv.hostPlatform.isDarwin && pythonOlder "3.12") ''
562 # Fix _ctypes module compilation
563 export NIX_CFLAGS_COMPILE+=" -DUSING_APPLE_OS_LIBFFI=1"
564 ''
565 + optionalString stdenv.hostPlatform.isDarwin ''
566 # Override the auto-detection in setup.py, which assumes a universal build
567 export PYTHON_DECIMAL_WITH_MACHINE=${if stdenv.hostPlatform.isAarch64 then "uint128" else "x64"}
568 # Ensure that modern platform features are enabled on Darwin in spite of having no version suffix.
569 sed -E -i -e 's|Darwin/\[12\]\[0-9\]\.\*|Darwin/*|' configure
570 ''
571 + optionalString (pythonAtLeast "3.11") ''
572 # Also override the auto-detection in `configure`.
573 substituteInPlace configure \
574 --replace-fail 'libmpdec_machine=universal' 'libmpdec_machine=${
575 if stdenv.hostPlatform.isAarch64 then "uint128" else "x64"
576 }'
577 ''
578 + optionalString stdenv.hostPlatform.isWindows ''
579 export NIX_CFLAGS_COMPILE+=" -Wno-error=incompatible-pointer-types"
580 ''
581 + optionalString stdenv.hostPlatform.isMusl ''
582 export NIX_CFLAGS_COMPILE+=" -DTHREAD_STACK_SIZE=0x100000"
583 ''
584 +
585
586 # enableNoSemanticInterposition essentially sets that CFLAG -fno-semantic-interposition
587 # which changes how symbols are looked up. This essentially means we can't override
588 # libpython symbols via LD_PRELOAD anymore. This is common enough as every build
589 # that uses --enable-optimizations has the same "issue".
590 #
591 # The Fedora wiki has a good article about their journey towards enabling this flag:
592 # https://fedoraproject.org/wiki/Changes/PythonNoSemanticInterpositionSpeedup
593 optionalString enableNoSemanticInterposition ''
594 export CFLAGS_NODIST="-fno-semantic-interposition"
595 '';
596
597 setupHook = python-setup-hook sitePackages;
598
599 postInstall =
600 let
601 # References *not* to nuke from (sys)config files
602 keep-references = concatMapStringsSep " " (val: "-e ${val}") (
603 [
604 (placeholder "out")
605 ]
606 ++ lib.optional withLibxcrypt libxcrypt
607 ++ lib.optional tzdataSupport tzdata
608 );
609 in
610 lib.optionalString enableFramework ''
611 for dir in include lib share; do
612 ln -s $out/Library/Frameworks/Python.framework/Versions/Current/$dir $out/$dir
613 done
614 ''
615 + ''
616 # needed for some packages, especially packages that backport functionality
617 # to 2.x from 3.x
618 for item in $out/lib/${libPrefix}/test/*; do
619 if [[ "$item" != */test_support.py*
620 && "$item" != */test/support
621 && "$item" != */test/libregrtest
622 && "$item" != */test/regrtest.py* ]]; then
623 rm -rf "$item"
624 else
625 echo $item
626 fi
627 done
628 ''
629 + lib.optionalString (!static) ''
630 touch $out/lib/${libPrefix}/test/__init__.py
631 ''
632 + ''
633
634 # Determinism: Windows installers were not deterministic.
635 # We're also not interested in building Windows installers.
636 find "$out" -name 'wininst*.exe' | xargs -r rm -f
637
638 # Use Python3 as default python
639 ln -s "$out/bin/idle3" "$out/bin/idle"
640 ln -s "$out/bin/pydoc3" "$out/bin/pydoc"
641 ln -s "$out/bin/python3${execSuffix}" "$out/bin/python${execSuffix}"
642 ln -s "$out/bin/python3-config" "$out/bin/python-config"
643 ln -s "$out/lib/pkgconfig/python3.pc" "$out/lib/pkgconfig/python.pc"
644 ln -sL "$out/share/man/man1/python3.1.gz" "$out/share/man/man1/python.1.gz"
645
646 # Get rid of retained dependencies on -dev packages, and remove
647 # some $TMPDIR references to improve binary reproducibility.
648 # Note that the .pyc file of _sysconfigdata.py should be regenerated!
649 for i in $out/lib/${libPrefix}/_sysconfigdata*.py $out/lib/${libPrefix}/config-${sourceVersion.major}.${sourceVersion.minor}*/Makefile; do
650 sed -i $i -e "s|$TMPDIR|/no-such-path|g"
651 done
652
653 # Further get rid of references. https://github.com/NixOS/nixpkgs/issues/51668
654 find $out/lib/python*/config-* -type f -print -exec nuke-refs ${keep-references} '{}' +
655 find $out/lib -name '_sysconfigdata*.py*' -print -exec nuke-refs ${keep-references} '{}' +
656
657 # Make the sysconfigdata module accessible on PYTHONPATH
658 # This allows build Python to import host Python's sysconfigdata
659 mkdir -p "$out/${sitePackages}"
660 ln -s "$out/lib/${libPrefix}/"_sysconfigdata*.py "$out/${sitePackages}/"
661 ''
662 + optionalString (pythonAtLeast "3.14") ''
663 # Get rid of retained dependencies on -dev packages, and remove from _sysconfig_vars*.json introduced with Python3.14
664 for i in $out/lib/${libPrefix}/_sysconfig_vars*.json; do
665 sed -i $i -e "s|$TMPDIR|/no-such-path|g"
666 done
667 find $out/lib -name '_sysconfig_vars*.json*' -print -exec nuke-refs ${keep-references} '{}' +
668 ln -s "$out/lib/${libPrefix}/"_sysconfig_vars*.json "$out/${sitePackages}/"
669 ''
670 + optionalString stripConfig ''
671 rm -R $out/bin/python*-config $out/lib/python*/config-*
672 ''
673 + optionalString stripIdlelib ''
674 # Strip IDLE (and turtledemo, which uses it)
675 rm -R $out/bin/idle* $out/lib/python*/{idlelib,turtledemo}
676 ''
677 + optionalString stripTkinter ''
678 rm -R $out/lib/python*/tkinter
679 ''
680 + optionalString stripTests ''
681 # Strip tests
682 rm -R $out/lib/python*/test $out/lib/python*/**/test{,s}
683 ''
684 + optionalString includeSiteCustomize ''
685 # Include a sitecustomize.py file
686 cp ${../sitecustomize.py} $out/${sitePackages}/sitecustomize.py
687 ''
688 + optionalString stripBytecode ''
689 # Determinism: deterministic bytecode
690 # First we delete all old bytecode.
691 find $out -type d -name __pycache__ -print0 | xargs -0 -I {} rm -rf "{}"
692 ''
693 + optionalString rebuildBytecode ''
694 # Python 3.7 implements PEP 552, introducing support for deterministic bytecode.
695 # compileall uses the therein introduced checked-hash method by default when
696 # `SOURCE_DATE_EPOCH` is set.
697 # We exclude lib2to3 because that's Python 2 code which fails
698 # We build 3 levels of optimized bytecode. Note the default level, without optimizations,
699 # is not reproducible yet. https://bugs.python.org/issue29708
700 # Not creating bytecode will result in a large performance loss however, so we do build it.
701 find $out -name "*.py" | ${pythonOnBuildForHostInterpreter} -m compileall -q -f -x "lib2to3" -i -
702 find $out -name "*.py" | ${pythonOnBuildForHostInterpreter} -O -m compileall -q -f -x "lib2to3" -i -
703 find $out -name "*.py" | ${pythonOnBuildForHostInterpreter} -OO -m compileall -q -f -x "lib2to3" -i -
704 ''
705 + ''
706 # *strip* shebang from libpython gdb script - it should be dual-syntax and
707 # interpretable by whatever python the gdb in question is using, which may
708 # not even match the major version of this python. doing this after the
709 # bytecode compilations for the same reason - we don't want bytecode generated.
710 mkdir -p $out/share/gdb
711 sed '/^#!/d' Tools/gdb/libpython.py > $out/share/gdb/libpython.py
712
713 # Disable system-wide pip installation. See https://peps.python.org/pep-0668/.
714 cat <<'EXTERNALLY_MANAGED' > $out/lib/${libPrefix}/EXTERNALLY-MANAGED
715 [externally-managed]
716 Error=This command has been disabled as it tries to modify the immutable
717 `/nix/store` filesystem.
718
719 To use Python with Nix and nixpkgs, have a look at the online documentation:
720 <https://nixos.org/manual/nixpkgs/stable/#python>.
721 EXTERNALLY_MANAGED
722 ''
723 + optionalString stdenv.hostPlatform.isWindows ''
724 # Shebang files that link against the build python. Shebang don’t work on windows
725 rm $out/bin/2to3*
726 rm $out/bin/idle*
727 rm $out/bin/pydoc*
728
729 echo linking DLLs for python’s compiled librairies
730 linkDLLsInfolder $out/lib/python*/lib-dynload/
731 '';
732
733 preFixup = lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) ''
734 # Ensure patch-shebangs uses shebangs of host interpreter.
735 export PATH=${lib.makeBinPath [ "$out" ]}:$PATH
736 '';
737
738 # Add CPython specific setup-hook that configures distutils.sysconfig to
739 # always load sysconfigdata from host Python.
740 postFixup = lib.optionalString (!stdenv.hostPlatform.isDarwin) ''
741 # https://github.com/python/cpython/blob/e488e300f5c01289c10906c2e53a8e43d6de32d8/configure.ac#L78
742 sysconfigdataName="$(make --eval $'print-sysconfigdata-name:
743 \t@echo _sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) ' print-sysconfigdata-name)"
744
745 # The CPython interpreter contains a _sysconfigdata_<platform specific suffix>
746 # module that is imported by the sysconfig and distutils.sysconfig modules.
747 # The sysconfigdata module is generated at build time and contains settings
748 # required for building Python extension modules, such as include paths and
749 # other compiler flags. By default, the sysconfigdata module is loaded from
750 # the currently running interpreter (ie. the build platform interpreter), but
751 # when cross-compiling we want to load it from the host platform interpreter.
752 # This can be done using the _PYTHON_SYSCONFIGDATA_NAME environment variable.
753 # The _PYTHON_HOST_PLATFORM variable also needs to be set to get the correct
754 # platform suffix on extension modules. The correct values for these variables
755 # are not documented, and must be derived from the configure script (see links
756 # below).
757 cat <<EOF >> "$out/nix-support/setup-hook"
758 sysconfigdataHook() {
759 if [ "\$1" = '$out' ]; then
760 export _PYTHON_HOST_PLATFORM='${pythonHostPlatform}'
761 export _PYTHON_SYSCONFIGDATA_NAME='$sysconfigdataName'
762 fi
763 }
764
765 addEnvHooks "\$hostOffset" sysconfigdataHook
766 EOF
767 '';
768
769 # Enforce that we don't have references to the OpenSSL -dev package, which we
770 # explicitly specify in our configure flags above.
771 disallowedReferences =
772 lib.optionals (withOpenssl && !static && !enableFramework) [
773 openssl.dev
774 ]
775 ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
776 # Ensure we don't have references to build-time packages.
777 # These typically end up in shebangs.
778 pythonOnBuildForHost
779 buildPackages.bashNonInteractive
780 ];
781
782 # Optionally set allowedReferences to guarantee minimal dependencies
783 # Allows python3Minimal to stay minimal and not have deps added by accident
784 # Doesn't do anything if allowedReferenceNames is empty (was not set)
785 ${if allowedReferenceNames != [ ] then "allowedReferences" else null} =
786 # map allowed names to their derivations
787 (map (name: inputs.${name}) allowedReferenceNames) ++ [
788 # any version of python depends on libc and libgcc
789 stdenv.cc.cc.lib
790 stdenv.cc.libc
791 # allows python referring to its own store path
792 "out"
793 ];
794
795 separateDebugInfo = true;
796 __structuredAttrs = true;
797
798 passthru = passthru // {
799 doc = stdenv.mkDerivation {
800 inherit src;
801 name = "python${pythonVersion}-${version}-doc";
802
803 postPatch = lib.optionalString (pythonAtLeast "3.9" && pythonOlder "3.11") ''
804 substituteInPlace Doc/tools/extensions/pyspecific.py \
805 --replace-fail "from sphinx.util import status_iterator" "from sphinx.util.display import status_iterator"
806 '';
807
808 dontConfigure = true;
809
810 dontBuild = true;
811
812 sphinxRoot = "Doc";
813
814 postInstallSphinx = ''
815 mv $out/share/doc/* $out/share/doc/python${pythonVersion}-${version}
816 '';
817
818 nativeBuildInputs = with pkgsBuildBuild.python3.pkgs; [
819 sphinxHook
820 python-docs-theme
821 ];
822 };
823
824 tests = passthru.tests // {
825 pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
826 };
827 };
828
829 enableParallelBuilding = true;
830
831 meta = {
832 homepage = "https://www.python.org";
833 changelog =
834 let
835 majorMinor = lib.versions.majorMinor version;
836 dashedVersion = lib.replaceStrings [ "." "a" "b" ] [ "-" "-alpha-" "-beta-" ] version;
837 in
838 if sourceVersion.suffix == "" then
839 "https://docs.python.org/release/${version}/whatsnew/changelog.html"
840 else
841 "https://docs.python.org/${majorMinor}/whatsnew/changelog.html#python-${dashedVersion}";
842 description = "High-level dynamically-typed programming language";
843 longDescription = ''
844 Python is a remarkably powerful dynamic programming language that
845 is used in a wide variety of application domains. Some of its key
846 distinguishing features include: clear, readable syntax; strong
847 introspection capabilities; intuitive object orientation; natural
848 expression of procedural code; full modularity, supporting
849 hierarchical packages; exception-based error handling; and very
850 high level dynamic data types.
851 '';
852 license = lib.licenses.psfl;
853 pkgConfigModules = [ "python3" ];
854 platforms =
855 lib.platforms.linux ++ lib.platforms.darwin ++ lib.platforms.windows ++ lib.platforms.freebsd;
856 mainProgram = executable;
857 teams = [ lib.teams.python ];
858 # static build on x86_64-darwin/aarch64-darwin breaks with:
859 # configure: error: C compiler cannot create executables
860
861 # mingw patches only apply to Python 3.11 currently
862 broken =
863 (lib.versions.minor version != "11" && stdenv.hostPlatform.isWindows)
864 || (stdenv.hostPlatform.isStatic && stdenv.hostPlatform.isDarwin);
865 };
866})