1{
2 lib,
3 stdenv,
4 fetchurl,
5 autoPatchelfHook,
6 python-setup-hook,
7 self,
8 # Dependencies
9 bzip2,
10 expat,
11 gdbm,
12 ncurses6,
13 sqlite,
14 tcl-8_5,
15 tk-8_5,
16 tcl-8_6,
17 tk-8_6,
18 zlib,
19 # For the Python package set
20 packageOverrides ? (self: super: { }),
21 sourceVersion,
22 pythonVersion,
23 hash,
24 passthruFun,
25}:
26
27# This version of PyPy is primarily added to speed-up translation of
28# our PyPy source build when developing that expression.
29
30let
31 isPy3k = majorVersion == "3";
32 passthru = passthruFun rec {
33 inherit
34 self
35 sourceVersion
36 pythonVersion
37 packageOverrides
38 ;
39 implementation = "pypy";
40 libPrefix = "pypy${pythonVersion}";
41 executable = "pypy${lib.optionalString isPy3k "3"}";
42 sitePackages = "lib/${libPrefix}/site-packages";
43 hasDistutilsCxxPatch = false;
44
45 # Not possible to cross-compile with.
46 pythonOnBuildForBuild = throw "${pname} does not support cross compilation";
47 pythonOnBuildForHost = self;
48 pythonOnBuildForTarget = throw "${pname} does not support cross compilation";
49 pythonOnHostForHost = throw "${pname} does not support cross compilation";
50 pythonOnTargetForTarget = throw "${pname} does not support cross compilation";
51 };
52 pname = "${passthru.executable}_prebuilt";
53 version = with sourceVersion; "${major}.${minor}.${patch}";
54
55 majorVersion = lib.versions.major pythonVersion;
56
57 downloadUrls = {
58 aarch64-linux = "https://downloads.python.org/pypy/pypy${pythonVersion}-v${version}-aarch64.tar.bz2";
59 x86_64-linux = "https://downloads.python.org/pypy/pypy${pythonVersion}-v${version}-linux64.tar.bz2";
60 aarch64-darwin = "https://downloads.python.org/pypy/pypy${pythonVersion}-v${version}-macos_arm64.tar.bz2";
61 x86_64-darwin = "https://downloads.python.org/pypy/pypy${pythonVersion}-v${version}-macos_x86_64.tar.bz2";
62 };
63
64in
65with passthru;
66stdenv.mkDerivation {
67 inherit pname version;
68
69 src = fetchurl {
70 url = downloadUrls.${stdenv.system} or (throw "Unsupported system: ${stdenv.system}");
71 inherit hash;
72 };
73
74 buildInputs =
75 [
76 bzip2
77 expat
78 gdbm
79 ncurses6
80 sqlite
81 zlib
82 stdenv.cc.cc.libgcc or null
83 ]
84 ++ lib.optionals stdenv.hostPlatform.isLinux [
85 tcl-8_5
86 tk-8_5
87 ]
88 ++ lib.optionals stdenv.hostPlatform.isDarwin [
89 tcl-8_6
90 tk-8_6
91 ];
92
93 nativeBuildInputs = lib.optionals stdenv.hostPlatform.isLinux [ autoPatchelfHook ];
94
95 installPhase = ''
96 runHook preInstall
97
98 mkdir -p $out
99 echo "Moving files to $out"
100 mv -t $out bin include lib
101 mv $out/bin/libpypy*-c${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/
102 ${lib.optionalString stdenv.hostPlatform.isLinux ''
103 rm $out/bin/*.debug
104 ''}
105
106 echo "Removing bytecode"
107 find . -name "__pycache__" -type d -depth -delete
108
109 # Include a sitecustomize.py file
110 cp ${../sitecustomize.py} $out/${sitePackages}/sitecustomize.py
111
112 runHook postInstall
113 '';
114
115 preFixup =
116 lib.optionalString stdenv.hostPlatform.isLinux ''
117 find $out/{lib,lib_pypy*} -name "*.so" \
118 -exec patchelf \
119 --replace-needed libtinfow.so.6 libncursesw.so.6 \
120 --replace-needed libgdbm.so.4 libgdbm_compat.so.4 {} \;
121 ''
122 + lib.optionalString stdenv.hostPlatform.isDarwin ''
123 install_name_tool \
124 -change \
125 @rpath/lib${libPrefix}-c.dylib \
126 $out/lib/lib${libPrefix}-c.dylib \
127 $out/bin/${executable}
128 install_name_tool \
129 -change \
130 @rpath/lib${libPrefix}-c.dylib \
131 $out/lib/lib${libPrefix}-c.dylib \
132 $out/bin/${libPrefix}
133 install_name_tool \
134 -change \
135 /opt/homebrew${lib.optionalString stdenv.hostPlatform.isx86_64 "_x86_64"}/opt/tcl-tk/lib/libtcl8.6.dylib \
136 ${tcl-8_6}/lib/libtcl8.6.dylib \
137 $out/lib/${libPrefix}/_tkinter/*.so
138 install_name_tool \
139 -change \
140 /opt/homebrew${lib.optionalString stdenv.hostPlatform.isx86_64 "_x86_64"}/opt/tcl-tk/lib/libtk8.6.dylib \
141 ${tk-8_6}/lib/libtk8.6.dylib \
142 $out/lib/${libPrefix}/_tkinter/*.so
143 '';
144
145 doInstallCheck = true;
146
147 # Check whether importing of (extension) modules functions
148 installCheckPhase =
149 let
150 modules =
151 [
152 "ssl"
153 "sys"
154 "curses"
155 ]
156 ++ lib.optionals (!isPy3k) [
157 "Tkinter"
158 ]
159 ++ lib.optionals isPy3k [
160 "tkinter"
161 ];
162 imports = lib.concatMapStringsSep "; " (x: "import ${x}") modules;
163 in
164 ''
165 echo "Testing whether we can import modules"
166 $out/bin/${executable} -c '${imports}'
167 '';
168
169 setupHook = python-setup-hook sitePackages;
170
171 donPatchElf = true;
172 dontStrip = true;
173
174 inherit passthru;
175
176 meta = with lib; {
177 homepage = "http://pypy.org/";
178 description = "Fast, compliant alternative implementation of the Python language (${pythonVersion})";
179 license = licenses.mit;
180 platforms = lib.mapAttrsToList (arch: _: arch) downloadUrls;
181 };
182
183}