summaryrefslogtreecommitdiff
path: root/pkgs/os-specific/linux/minimal-bootstrap/python/default.nix
blob: bc12245fd9db3c433fabafb4e4d0c97744ae3004 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
{
  lib,
  buildPlatform,
  hostPlatform,
  fetchurl,
  bash,
  gcc,
  musl,
  binutils,
  gnumake,
  gnupatch,
  gnused,
  gnugrep,
  gawk,
  diffutils,
  findutils,
  gnutar,
  xz,
  zlib,
}:
let
  pname = "python";
  version = "3.14.4";

  src = fetchurl {
    url = "https://www.python.org/ftp/python/${version}/Python-${version}.tar.xz";
    hash = "sha256-2SPFEwPjjiSRNvwb3zVo1W7LAyFO/e9IUWF209f6rvg=";
  };

  patches = [
    # Disable the use of ldconfig in ctypes.util.find_library (since
    # ldconfig doesn't work on NixOS), and don't use
    # ctypes.util.find_library during the loading of the uuid module
    # (since it will do a futile invocation of gcc (!) to find
    # libuuid, slowing down program startup a lot).
    ./no-ldconfig.patch
  ];
in
bash.runCommand "${pname}-${version}"
  {
    inherit pname version;

    nativeBuildInputs = [
      gcc
      musl
      binutils
      gnumake
      gnupatch
      gnused
      gnugrep
      gawk
      diffutils
      findutils
      gnutar
      xz
    ];

    passthru.tests.get-version =
      result:
      bash.runCommand "${pname}-get-version-${version}" { } ''
        ${result}/bin/python3 --version
        mkdir $out
      '';

    meta = {
      description = "A high-level dynamically-typed programming language";
      homepage = "https://www.python.org";
      license = lib.licenses.psfl;
      mainProgram = "python3";
      platforms = lib.platforms.linux;
      teams = [ lib.teams.minimal-bootstrap ];
    };
  }
  ''
    # Unpack
    tar xf ${src}
    cd Python-${version}

    # Patch
    ${lib.concatMapStringsSep "\n" (f: "patch -Np1 -i ${f}") patches}

    # Configure
    export CC=musl-gcc
    export C_INCLUDE_PATH="${zlib}/include"
    export LIBRARY_PATH="${zlib}/lib"
    export LDFLAGS="-Wl,-rpath,${zlib}/lib -L${zlib}/lib"
    export LD_LIBRARY_PATH="$LIBRARY_PATH"
    bash ./configure \
      --prefix=$out \
      --build=${buildPlatform.config} \
      --host=${hostPlatform.config} \
      --disable-test-modules \
      --without-ensurepip \
      --without-static-libpython

    # Build
    make -j $NIX_BUILD_CORES

    # Install
    make -j $NIX_BUILD_CORES install

    # Remove lib-dynload extension modules not needed for glibc's build scripts.
    # glibc uses Python only for scripts that import: os, re, subprocess, argparse,
    # pathlib, collections, tempfile.  Following the import chain:
    #   subprocess -> selectors -> math, select, fcntl, _posixsubprocess
    #   pathlib -> grp
    #   tempfile -> random -> _random, bisect -> _bisect
    # Everything else in lib-dynload is dead weight in the bootstrap context.
    find $out/lib/python*/lib-dynload -name '*.so' \
      ! -name '_bisect*' \
      ! -name '_posixsubprocess*' \
      ! -name '_random*' \
      ! -name 'fcntl*' \
      ! -name 'grp*' \
      ! -name 'math*' \
      ! -name 'select*' \
      -delete

    rm -rf \
      $out/lib/python*/ensurepip \
      $out/lib/python*/idlelib \
      $out/lib/python*/site-packages \
      $out/lib/python*/test \
      $out/lib/python*/tkinter \
      $out/lib/python*/turtledemo \
      $out/share/man

    rm -f $out/bin/idle* $out/bin/pip*
    find $out/lib/python* -type d -name __pycache__ -prune -exec rm -rf {} +
    strip --strip-unneeded $out/bin/python${lib.versions.majorMinor version} $out/lib/python*/lib-dynload/*.so || true
  ''