1{ stdenv, fetchurl, self, callPackage, python27Packages
2, bzip2, openssl, gettext
3, less
4
5, includeModules ? false
6
7, db, gdbm, ncurses, sqlite, readline
8
9, tcl ? null, tk ? null, xlibsWrapper ? null, libX11 ? null, x11Support ? !stdenv.isCygwin
10, zlib ? null, zlibSupport ? true
11, expat, libffi
12
13, CF, configd
14}:
15
16assert zlibSupport -> zlib != null;
17assert x11Support -> tcl != null
18 && tk != null
19 && xlibsWrapper != null
20 && libX11 != null;
21
22with stdenv.lib;
23
24let
25 majorVersion = "2.7";
26 version = "${majorVersion}.12";
27
28 src = fetchurl {
29 url = "http://www.python.org/ftp/python/${version}/Python-${version}.tar.xz";
30 sha256 = "0y7rl603vmwlxm6ilkhc51rx2mfj14ckcz40xxgs0ljnvlhp30yp";
31 };
32
33 patches =
34 [ # Look in C_INCLUDE_PATH and LIBRARY_PATH for stuff.
35 ./search-path.patch
36
37 # Python recompiles a Python if the mtime stored *in* the
38 # pyc/pyo file differs from the mtime of the source file. This
39 # doesn't work in Nix because Nix changes the mtime of files in
40 # the Nix store to 1. So treat that as a special case.
41 ./nix-store-mtime.patch
42
43 # patch python to put zero timestamp into pyc
44 # if DETERMINISTIC_BUILD env var is set
45 ./deterministic-build.patch
46
47 ./properly-detect-curses.patch
48 ] ++ optionals stdenv.isLinux [
49
50 # Disable the use of ldconfig in ctypes.util.find_library (since
51 # ldconfig doesn't work on NixOS), and don't use
52 # ctypes.util.find_library during the loading of the uuid module
53 # (since it will do a futile invocation of gcc (!) to find
54 # libuuid, slowing down program startup a lot).
55 ./no-ldconfig.patch
56
57 ] ++ optionals stdenv.isCygwin [
58 ./2.5.2-ctypes-util-find_library.patch
59 ./2.5.2-tkinter-x11.patch
60 ./2.6.2-ssl-threads.patch
61 ./2.6.5-export-PySignal_SetWakeupFd.patch
62 ./2.6.5-FD_SETSIZE.patch
63 ./2.6.5-ncurses-abi6.patch
64 ./2.7.3-dbm.patch
65 ./2.7.3-dylib.patch
66 ./2.7.3-getpath-exe-extension.patch
67 ./2.7.3-no-libm.patch
68 ];
69
70 preConfigure = ''
71 # Purity.
72 for i in /usr /sw /opt /pkg; do
73 substituteInPlace ./setup.py --replace $i /no-such-path
74 done
75 '' + optionalString (stdenv ? cc && stdenv.cc.libc != null) ''
76 for i in Lib/plat-*/regen; do
77 substituteInPlace $i --replace /usr/include/ ${stdenv.cc.libc}/include/
78 done
79 '' + optionalString stdenv.isDarwin ''
80 substituteInPlace configure --replace '`/usr/bin/arch`' '"i386"'
81 substituteInPlace Lib/multiprocessing/__init__.py \
82 --replace 'os.popen(comm)' 'os.popen("nproc")'
83 '';
84
85 configureFlags = [
86 "--enable-shared"
87 "--with-threads"
88 "--enable-unicode=ucs4"
89 ] ++ optionals stdenv.isCygwin [
90 "--with-system-ffi"
91 "--with-system-expat"
92 "ac_cv_func_bind_textdomain_codeset=yes"
93 ] ++ optionals stdenv.isDarwin [
94 "--disable-toolbox-glue"
95 ];
96
97 postConfigure = if stdenv.isCygwin then ''
98 sed -i Makefile -e 's,PYTHONPATH="$(srcdir),PYTHONPATH="$(abs_srcdir),'
99 '' else null;
100
101 buildInputs =
102 optional (stdenv ? cc && stdenv.cc.libc != null) stdenv.cc.libc ++
103 [ bzip2 openssl ]
104 ++ optionals stdenv.isCygwin [ expat libffi ]
105 ++ optionals includeModules (
106 [ db gdbm ncurses sqlite readline
107 ] ++ optionals x11Support [ tcl tk xlibsWrapper libX11 ]
108 )
109 ++ optional zlibSupport zlib
110 ++ optional stdenv.isDarwin CF;
111
112 propagatedBuildInputs = [ less ] ++ optional stdenv.isDarwin configd;
113
114 mkPaths = paths: {
115 C_INCLUDE_PATH = makeSearchPathOutput "dev" "include" paths;
116 LIBRARY_PATH = makeLibraryPath paths;
117 };
118
119 # Build the basic Python interpreter without modules that have
120 # external dependencies.
121 python = stdenv.mkDerivation {
122 name = "python-${version}";
123 pythonVersion = majorVersion;
124
125 inherit majorVersion version src patches buildInputs propagatedBuildInputs
126 preConfigure configureFlags;
127
128 LDFLAGS = stdenv.lib.optionalString (!stdenv.isDarwin) "-lgcc_s";
129 inherit (mkPaths buildInputs) C_INCLUDE_PATH LIBRARY_PATH;
130
131 NIX_CFLAGS_COMPILE = optionalString stdenv.isDarwin "-msse2";
132 DETERMINISTIC_BUILD = 1;
133
134 setupHook = ./setup-hook.sh;
135
136 postInstall =
137 ''
138 # needed for some packages, especially packages that backport
139 # functionality to 2.x from 3.x
140 for item in $out/lib/python${majorVersion}/test/*; do
141 if [[ "$item" != */test_support.py* ]]; then
142 rm -rf "$item"
143 else
144 echo $item
145 fi
146 done
147 touch $out/lib/python${majorVersion}/test/__init__.py
148 ln -s $out/lib/python${majorVersion}/pdb.py $out/bin/pdb
149 ln -s $out/lib/python${majorVersion}/pdb.py $out/bin/pdb${majorVersion}
150 ln -s $out/share/man/man1/{python2.7.1.gz,python.1.gz}
151
152 paxmark E $out/bin/python${majorVersion}
153
154 ${optionalString includeModules "$out/bin/python ./setup.py build_ext"}
155
156 rm "$out"/lib/python*/plat-*/regen # refers to glibc.dev
157 '';
158
159 passthru = rec {
160 inherit zlibSupport;
161 isPy2 = true;
162 isPy27 = true;
163 buildEnv = callPackage ../../wrapper.nix { python = self; };
164 withPackages = import ../../with-packages.nix { inherit buildEnv; pythonPackages = python27Packages; };
165 libPrefix = "python${majorVersion}";
166 executable = libPrefix;
167 sitePackages = "lib/${libPrefix}/site-packages";
168 interpreter = "${self}/bin/${executable}";
169 };
170
171 enableParallelBuilding = true;
172
173 meta = {
174 homepage = "http://python.org";
175 description = "A high-level dynamically-typed programming language";
176 longDescription = ''
177 Python is a remarkably powerful dynamic programming language that
178 is used in a wide variety of application domains. Some of its key
179 distinguishing features include: clear, readable syntax; strong
180 introspection capabilities; intuitive object orientation; natural
181 expression of procedural code; full modularity, supporting
182 hierarchical packages; exception-based error handling; and very
183 high level dynamic data types.
184 '';
185 license = stdenv.lib.licenses.psfl;
186 platforms = stdenv.lib.platforms.all;
187 maintainers = with stdenv.lib.maintainers; [ chaoflow domenkozar ];
188 };
189 };
190
191
192 # This function builds a Python module included in the main Python
193 # distribution in a separate derivation.
194 buildInternalPythonModule =
195 { moduleName
196 , internalName ? "_" + moduleName
197 , deps
198 }:
199 if includeModules then null else stdenv.mkDerivation rec {
200 name = "python-${moduleName}-${python.version}";
201
202 inherit src patches preConfigure postConfigure configureFlags;
203
204 buildInputs = [ python ] ++ deps;
205
206 # We need to set this for python.buildEnv
207 pythonPath = [];
208
209 inherit (mkPaths buildInputs) C_INCLUDE_PATH LIBRARY_PATH;
210
211 # non-python gdbm has a libintl dependency on i686-cygwin, not on x86_64-cygwin
212 buildPhase = (if (stdenv.system == "i686-cygwin" && moduleName == "gdbm") then ''
213 sed -i setup.py -e "s:libraries = \['gdbm'\]:libraries = ['gdbm', 'intl']:"
214 '' else '''') + ''
215 substituteInPlace setup.py --replace 'self.extensions = extensions' \
216 'self.extensions = [ext for ext in self.extensions if ext.name in ["${internalName}"]]'
217
218 python ./setup.py build_ext
219 [ -z "$(find build -name '*_failed.so' -print)" ]
220 '';
221
222 installPhase =
223 ''
224 dest=$out/lib/${python.libPrefix}/site-packages
225 mkdir -p $dest
226 cp -p $(find . -name "*.${if stdenv.isCygwin then "dll" else "so"}") $dest/
227 '';
228 };
229
230
231 # The Python modules included in the main Python distribution, built
232 # as separate derivations.
233 modules = {
234
235 bsddb = buildInternalPythonModule {
236 moduleName = "bsddb";
237 deps = [ db ];
238 };
239
240 curses = buildInternalPythonModule {
241 moduleName = "curses";
242 deps = [ ncurses ];
243 };
244
245 curses_panel = buildInternalPythonModule {
246 moduleName = "curses_panel";
247 deps = [ ncurses modules.curses ];
248 };
249
250 crypt = buildInternalPythonModule {
251 moduleName = "crypt";
252 internalName = "crypt";
253 deps = optional (stdenv ? glibc) stdenv.glibc;
254 };
255
256 gdbm = buildInternalPythonModule {
257 moduleName = "gdbm";
258 internalName = "gdbm";
259 deps = [ gdbm ] ++ stdenv.lib.optional stdenv.isCygwin gettext;
260 };
261
262 sqlite3 = buildInternalPythonModule {
263 moduleName = "sqlite3";
264 deps = [ sqlite ];
265 };
266
267 } // optionalAttrs x11Support {
268
269 tkinter = if stdenv.isCygwin then null else (buildInternalPythonModule {
270 moduleName = "tkinter";
271 deps = [ tcl tk xlibsWrapper libX11 ];
272 });
273
274 } // {
275
276 readline = buildInternalPythonModule {
277 moduleName = "readline";
278 internalName = "readline";
279 deps = [ readline ];
280 };
281
282 };
283
284in python // { inherit modules; }