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