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