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