1{ stdenv, buildPackages, fetchurl
2, bzip2
3, gdbm
4, fetchpatch
5, ncurses
6, openssl
7, readline
8, sqlite
9, tcl ? null, tk ? null, tix ? null, xlibsWrapper ? null, libX11 ? null, x11Support ? false
10, zlib
11, callPackage
12, self
13, db
14, expat
15, libffi
16, CF, configd, coreutils
17, python-setup-hook
18# Some proprietary libs assume UCS2 unicode, especially on darwin :(
19, ucsEncoding ? 4
20# For the Python package set
21, packageOverrides ? (self: super: {})
22}:
23
24assert x11Support -> tcl != null
25 && tk != null
26 && xlibsWrapper != null
27 && libX11 != null;
28
29with stdenv.lib;
30
31let
32 majorVersion = "2.7";
33 minorVersion = "15";
34 minorVersionSuffix = "";
35 version = "${majorVersion}.${minorVersion}${minorVersionSuffix}";
36 libPrefix = "python${majorVersion}";
37 sitePackages = "lib/${libPrefix}/site-packages";
38
39 src = fetchurl {
40 url = "https://www.python.org/ftp/python/${majorVersion}.${minorVersion}/Python-${version}.tar.xz";
41 sha256 = "0x2mvz9dp11wj7p5ccvmk9s0hzjk2fa1m462p395l4r6bfnb3n92";
42 };
43
44 hasDistutilsCxxPatch = !(stdenv.cc.isGNU or false);
45 patches =
46 [ # Look in C_INCLUDE_PATH and LIBRARY_PATH for stuff.
47 ./search-path.patch
48
49 # Python recompiles a Python if the mtime stored *in* the
50 # pyc/pyo file differs from the mtime of the source file. This
51 # doesn't work in Nix because Nix changes the mtime of files in
52 # the Nix store to 1. So treat that as a special case.
53 ./nix-store-mtime.patch
54
55 # patch python to put zero timestamp into pyc
56 # if DETERMINISTIC_BUILD env var is set
57 ./deterministic-build.patch
58
59 # Fix python bug #27177 (https://bugs.python.org/issue27177)
60 # The issue is that `match.group` only recognizes python integers
61 # instead of everything that has `__index__`.
62 # This bug was fixed upstream, but not backported to 2.7
63 (fetchpatch {
64 name = "re_match_index.patch";
65 url = "https://bugs.python.org/file43084/re_match_index.patch";
66 sha256 = "0l9rw6r5r90iybdkp3hhl2pf0h0s1izc68h5d3ywrm92pq32wz57";
67 })
68
69 # "`type_getattro()` calls `tp_descr_get(self, obj, type)` without actually owning a reference to "self".
70 # In very rare cases, this can cause a segmentation fault if "self" is deleted by the descriptor."
71 # https://github.com/python/cpython/pull/6118
72 (fetchpatch {
73 name = "type_getattro.patch";
74 url = "file://${./type_getattro.patch}";
75 sha256 = "11v9yx20hs3jmw0wggzvmw39qs4mxay4kb8iq2qjydwy9ya61nrd";
76 })
77 ] ++ optionals (x11Support && stdenv.isDarwin) [
78 ./use-correct-tcl-tk-on-darwin.patch
79 ] ++ optionals stdenv.isLinux [
80
81 # Disable the use of ldconfig in ctypes.util.find_library (since
82 # ldconfig doesn't work on NixOS), and don't use
83 # ctypes.util.find_library during the loading of the uuid module
84 # (since it will do a futile invocation of gcc (!) to find
85 # libuuid, slowing down program startup a lot).
86 ./no-ldconfig.patch
87
88 ] ++ optionals stdenv.hostPlatform.isCygwin [
89 ./2.5.2-ctypes-util-find_library.patch
90 ./2.5.2-tkinter-x11.patch
91 ./2.6.2-ssl-threads.patch
92 ./2.6.5-export-PySignal_SetWakeupFd.patch
93 ./2.6.5-FD_SETSIZE.patch
94 ./2.6.5-ncurses-abi6.patch
95 ./2.7.3-dbm.patch
96 ./2.7.3-dylib.patch
97 ./2.7.3-getpath-exe-extension.patch
98 ./2.7.3-no-libm.patch
99 ] ++ optionals hasDistutilsCxxPatch [
100
101 # Patch from http://bugs.python.org/issue1222585 adapted to work with
102 # `patch -p1' and with a last hunk removed
103 # Upstream distutils is calling C compiler to compile C++ code, which
104 # only works for GCC and Apple Clang. This makes distutils to call C++
105 # compiler when needed.
106 ./python-2.7-distutils-C++.patch
107 ];
108
109 preConfigure = ''
110 # Purity.
111 for i in /usr /sw /opt /pkg; do
112 substituteInPlace ./setup.py --replace $i /no-such-path
113 done
114 '' + optionalString (stdenv ? cc && stdenv.cc.libc != null) ''
115 for i in Lib/plat-*/regen; do
116 substituteInPlace $i --replace /usr/include/ ${stdenv.cc.libc}/include/
117 done
118 '' + optionalString stdenv.isDarwin ''
119 substituteInPlace configure --replace '`/usr/bin/arch`' '"i386"'
120 substituteInPlace Lib/multiprocessing/__init__.py \
121 --replace 'os.popen(comm)' 'os.popen("${coreutils}/bin/nproc")'
122 '';
123
124 configureFlags = [
125 "--enable-shared"
126 "--with-threads"
127 "--enable-unicode=ucs${toString ucsEncoding}"
128 ] ++ optionals (stdenv.hostPlatform.isCygwin || stdenv.hostPlatform.isAarch64) [
129 "--with-system-ffi"
130 ] ++ optionals stdenv.hostPlatform.isCygwin [
131 "--with-system-expat"
132 "ac_cv_func_bind_textdomain_codeset=yes"
133 ] ++ optionals stdenv.isDarwin [
134 "--disable-toolbox-glue"
135 ] ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
136 "PYTHON_FOR_BUILD=${getBin buildPackages.python}/bin/python"
137 "ac_cv_buggy_getaddrinfo=no"
138 # Assume little-endian IEEE 754 floating point when cross compiling
139 "ac_cv_little_endian_double=yes"
140 "ac_cv_big_endian_double=no"
141 "ac_cv_mixed_endian_double=no"
142 "ac_cv_x87_double_rounding=yes"
143 "ac_cv_tanh_preserves_zero_sign=yes"
144 # Generally assume that things are present and work
145 "ac_cv_posix_semaphores_enabled=yes"
146 "ac_cv_broken_sem_getvalue=no"
147 "ac_cv_wchar_t_signed=yes"
148 "ac_cv_rshift_extends_sign=yes"
149 "ac_cv_broken_nice=no"
150 "ac_cv_broken_poll=no"
151 "ac_cv_working_tzset=yes"
152 "ac_cv_have_long_long_format=yes"
153 "ac_cv_have_size_t_format=yes"
154 "ac_cv_computed_gotos=yes"
155 "ac_cv_file__dev_ptmx=yes"
156 "ac_cv_file__dev_ptc=yes"
157 ]
158 # Never even try to use lchmod on linux,
159 # don't rely on detecting glibc-isms.
160 ++ optional stdenv.hostPlatform.isLinux "ac_cv_func_lchmod=no";
161
162 buildInputs =
163 optional (stdenv ? cc && stdenv.cc.libc != null) stdenv.cc.libc ++
164 [ bzip2 openssl zlib ]
165 ++ optional (stdenv.hostPlatform.isCygwin || stdenv.hostPlatform.isAarch64) libffi
166 ++ optional stdenv.hostPlatform.isCygwin expat
167 ++ [ db gdbm ncurses sqlite readline ]
168 ++ optionals x11Support [ tcl tk xlibsWrapper libX11 ]
169 ++ optionals stdenv.isDarwin ([ CF ] ++ optional (configd != null) configd);
170 nativeBuildInputs =
171 optionals (stdenv.hostPlatform != stdenv.buildPlatform)
172 [ buildPackages.stdenv.cc buildPackages.python ];
173
174 mkPaths = paths: {
175 C_INCLUDE_PATH = makeSearchPathOutput "dev" "include" paths;
176 LIBRARY_PATH = makeLibraryPath paths;
177 };
178
179 # Build the basic Python interpreter without modules that have
180 # external dependencies.
181
182in stdenv.mkDerivation {
183 name = "python-${version}";
184 pythonVersion = majorVersion;
185
186 inherit majorVersion version src patches buildInputs nativeBuildInputs
187 preConfigure configureFlags;
188
189 LDFLAGS = stdenv.lib.optionalString (!stdenv.isDarwin) "-lgcc_s";
190 inherit (mkPaths buildInputs) C_INCLUDE_PATH LIBRARY_PATH;
191
192 NIX_CFLAGS_COMPILE = optionalString stdenv.isDarwin "-msse2"
193 + optionalString stdenv.hostPlatform.isMusl " -DTHREAD_STACK_SIZE=0x100000";
194 DETERMINISTIC_BUILD = 1;
195
196 setupHook = python-setup-hook sitePackages;
197
198 postPatch = optionalString (x11Support && (tix != null)) ''
199 substituteInPlace "Lib/lib-tk/Tix.py" --replace "os.environ.get('TIX_LIBRARY')" "os.environ.get('TIX_LIBRARY') or '${tix}/lib'"
200 '';
201
202 postInstall =
203 ''
204 # needed for some packages, especially packages that backport
205 # functionality to 2.x from 3.x
206 for item in $out/lib/python${majorVersion}/test/*; do
207 if [[ "$item" != */test_support.py*
208 && "$item" != */test/support
209 && "$item" != */test/regrtest.py* ]]; then
210 rm -rf "$item"
211 else
212 echo $item
213 fi
214 done
215 touch $out/lib/python${majorVersion}/test/__init__.py
216 ln -s $out/lib/python${majorVersion}/pdb.py $out/bin/pdb
217 ln -s $out/lib/python${majorVersion}/pdb.py $out/bin/pdb${majorVersion}
218 ln -s $out/share/man/man1/{python2.7.1.gz,python.1.gz}
219
220 paxmark E $out/bin/python${majorVersion}
221
222 # Python on Nix is not manylinux1 compatible. https://github.com/NixOS/nixpkgs/issues/18484
223 echo "manylinux1_compatible=False" >> $out/lib/${libPrefix}/_manylinux.py
224
225 rm "$out"/lib/python*/plat-*/regen # refers to glibc.dev
226
227 # Determinism: Windows installers were not deterministic.
228 # We're also not interested in building Windows installers.
229 find "$out" -name 'wininst*.exe' | xargs -r rm -f
230 '' + optionalString (stdenv.hostPlatform == stdenv.buildPlatform)
231 ''
232 # Determinism: rebuild all bytecode
233 # We exclude lib2to3 because that's Python 2 code which fails
234 # We rebuild three times, once for each optimization level
235 find $out -name "*.py" | $out/bin/python -m compileall -q -f -x "lib2to3" -i -
236 find $out -name "*.py" | $out/bin/python -O -m compileall -q -f -x "lib2to3" -i -
237 find $out -name "*.py" | $out/bin/python -OO -m compileall -q -f -x "lib2to3" -i -
238 '' + optionalString stdenv.hostPlatform.isCygwin ''
239 cp libpython2.7.dll.a $out/lib
240 '';
241
242 passthru = let
243 pythonPackages = callPackage ../../../../../top-level/python-packages.nix {python=self; overrides=packageOverrides;};
244 in rec {
245 inherit libPrefix sitePackages x11Support hasDistutilsCxxPatch ucsEncoding;
246 executable = libPrefix;
247 buildEnv = callPackage ../../wrapper.nix { python = self; inherit (pythonPackages) requiredPythonModules; };
248 withPackages = import ../../with-packages.nix { inherit buildEnv pythonPackages;};
249 pkgs = pythonPackages;
250 isPy2 = true;
251 isPy27 = true;
252 interpreter = "${self}/bin/${executable}";
253 };
254
255 enableParallelBuilding = true;
256
257 doCheck = false; # expensive, and fails
258
259 meta = {
260 homepage = http://python.org;
261 description = "A high-level dynamically-typed programming language";
262 longDescription = ''
263 Python is a remarkably powerful dynamic programming language that
264 is used in a wide variety of application domains. Some of its key
265 distinguishing features include: clear, readable syntax; strong
266 introspection capabilities; intuitive object orientation; natural
267 expression of procedural code; full modularity, supporting
268 hierarchical packages; exception-based error handling; and very
269 high level dynamic data types.
270 '';
271 license = stdenv.lib.licenses.psfl;
272 platforms = stdenv.lib.platforms.all;
273 maintainers = with stdenv.lib.maintainers; [ fridh ];
274 # Higher priority than Python 3.x so that `/bin/python` points to `/bin/python2`
275 # in case both 2 and 3 are installed.
276 priority = -100;
277 };
278 }