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