9
9
import sys
10
10
import sysconfig
11
11
import tempfile
12
+ from urllib .request import urlopen
12
13
from pathlib import Path
13
14
from textwrap import dedent
14
15
22
23
CHECKOUT = EMSCRIPTEN_DIR .parent .parent .parent
23
24
24
25
CROSS_BUILD_DIR = CHECKOUT / "cross-build"
25
- BUILD_DIR = CROSS_BUILD_DIR / "build"
26
+ NATIVE_BUILD_DIR = CROSS_BUILD_DIR / "build"
26
27
HOST_TRIPLE = "wasm32-emscripten"
27
- HOST_DIR = CROSS_BUILD_DIR / HOST_TRIPLE
28
+
29
+ DOWNLOAD_DIR = CROSS_BUILD_DIR / HOST_TRIPLE / "build"
30
+ HOST_BUILD_DIR = CROSS_BUILD_DIR / HOST_TRIPLE / "build"
31
+ HOST_DIR = HOST_BUILD_DIR / "python"
32
+ PREFIX_DIR = CROSS_BUILD_DIR / HOST_TRIPLE / "prefix"
28
33
29
34
LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local"
30
35
LOCAL_SETUP_MARKER = "# Generated by Tools/wasm/emscripten.py\n " .encode ("utf-8" )
@@ -118,16 +123,16 @@ def build_platform():
118
123
119
124
def build_python_path ():
120
125
"""The path to the build Python binary."""
121
- binary = BUILD_DIR / "python"
126
+ binary = NATIVE_BUILD_DIR / "python"
122
127
if not binary .is_file ():
123
128
binary = binary .with_suffix (".exe" )
124
129
if not binary .is_file ():
125
- raise FileNotFoundError ("Unable to find `python(.exe)` in " f"{ BUILD_DIR } " )
130
+ raise FileNotFoundError ("Unable to find `python(.exe)` in " f"{ NATIVE_BUILD_DIR } " )
126
131
127
132
return binary
128
133
129
134
130
- @subdir (BUILD_DIR , clean_ok = True )
135
+ @subdir (NATIVE_BUILD_DIR , clean_ok = True )
131
136
def configure_build_python (context , working_dir ):
132
137
"""Configure the build/host Python."""
133
138
if LOCAL_SETUP .exists ():
@@ -143,7 +148,7 @@ def configure_build_python(context, working_dir):
143
148
call (configure , quiet = context .quiet )
144
149
145
150
146
- @subdir (BUILD_DIR )
151
+ @subdir (NATIVE_BUILD_DIR )
147
152
def make_build_python (context , working_dir ):
148
153
"""Make/build the build Python."""
149
154
call (["make" , "--jobs" , str (cpu_count ()), "all" ], quiet = context .quiet )
@@ -159,6 +164,23 @@ def make_build_python(context, working_dir):
159
164
print (f"🎉 { binary } { version } " )
160
165
161
166
167
+ @subdir (HOST_BUILD_DIR , clean_ok = True )
168
+ def make_emscripten_libffi (context , working_dir ):
169
+ shutil .rmtree (working_dir / "libffi-3.4.6" , ignore_errors = True )
170
+ with tempfile .NamedTemporaryFile (suffix = ".tar.gz" ) as tmp_file :
171
+ with urlopen (
172
+ "https://github.com/libffi/libffi/releases/download/v3.4.6/libffi-3.4.6.tar.gz"
173
+ ) as response :
174
+ shutil .copyfileobj (response , tmp_file )
175
+ shutil .unpack_archive (tmp_file .name , working_dir )
176
+ call (
177
+ [EMSCRIPTEN_DIR / "make_libffi.sh" ],
178
+ env = updated_env ({"PREFIX" : PREFIX_DIR }),
179
+ cwd = working_dir / "libffi-3.4.6" ,
180
+ quiet = context .quiet ,
181
+ )
182
+
183
+
162
184
@subdir (HOST_DIR , clean_ok = True )
163
185
def configure_emscripten_python (context , working_dir ):
164
186
"""Configure the emscripten/host build."""
@@ -168,7 +190,7 @@ def configure_emscripten_python(context, working_dir):
168
190
169
191
emscripten_build_dir = working_dir .relative_to (CHECKOUT )
170
192
171
- python_build_dir = BUILD_DIR / "build"
193
+ python_build_dir = NATIVE_BUILD_DIR / "build"
172
194
lib_dirs = list (python_build_dir .glob ("lib.*" ))
173
195
assert (
174
196
len (lib_dirs ) == 1
@@ -183,12 +205,18 @@ def configure_emscripten_python(context, working_dir):
183
205
sysconfig_data += "-pydebug"
184
206
185
207
host_runner = context .host_runner
186
- env_additions = {"CONFIG_SITE" : config_site , "HOSTRUNNER" : host_runner }
208
+ pkg_config_path_dir = (PREFIX_DIR / "lib/pkgconfig/" ).resolve ()
209
+ env_additions = {
210
+ "CONFIG_SITE" : config_site ,
211
+ "HOSTRUNNER" : host_runner ,
212
+ "EM_PKG_CONFIG_PATH" : str (pkg_config_path_dir ),
213
+ }
187
214
build_python = os .fsdecode (build_python_path ())
188
215
configure = [
189
216
"emconfigure" ,
190
217
os .path .relpath (CHECKOUT / "configure" , working_dir ),
191
218
"CFLAGS=-DPY_CALL_TRAMPOLINE -sUSE_BZIP2" ,
219
+ "PKG_CONFIG=pkg-config" ,
192
220
f"--host={ HOST_TRIPLE } " ,
193
221
f"--build={ build_platform ()} " ,
194
222
f"--with-build-python={ build_python } " ,
@@ -197,7 +225,7 @@ def configure_emscripten_python(context, working_dir):
197
225
"--disable-ipv6" ,
198
226
"--enable-big-digits=30" ,
199
227
"--enable-wasm-dynamic-linking" ,
200
- f"--prefix={ HOST_DIR } " ,
228
+ f"--prefix={ PREFIX_DIR } " ,
201
229
]
202
230
if pydebug :
203
231
configure .append ("--with-pydebug" )
@@ -264,6 +292,7 @@ def build_all(context):
264
292
steps = [
265
293
configure_build_python ,
266
294
make_build_python ,
295
+ make_emscripten_libffi ,
267
296
configure_emscripten_python ,
268
297
make_emscripten_python ,
269
298
]
@@ -292,18 +321,30 @@ def main():
292
321
configure_build = subcommands .add_parser (
293
322
"configure-build-python" , help = "Run `configure` for the " "build Python"
294
323
)
324
+ make_libffi_cmd = subcommands .add_parser (
325
+ "make-libffi" , help = "Clone libffi repo, configure and build it for emscripten"
326
+ )
295
327
make_build = subcommands .add_parser (
296
328
"make-build-python" , help = "Run `make` for the build Python"
297
329
)
298
330
configure_host = subcommands .add_parser (
299
331
"configure-host" ,
300
332
help = "Run `configure` for the host/emscripten (pydebug builds are inferred from the build Python)" ,
301
333
)
302
- make_host = subcommands .add_parser ("make-host" , help = "Run `make` for the host/emscripten" )
334
+ make_host = subcommands .add_parser (
335
+ "make-host" , help = "Run `make` for the host/emscripten"
336
+ )
303
337
clean = subcommands .add_parser (
304
338
"clean" , help = "Delete files and directories created by this script"
305
339
)
306
- for subcommand in build , configure_build , make_build , configure_host , make_host :
340
+ for subcommand in (
341
+ build ,
342
+ configure_build ,
343
+ make_libffi_cmd ,
344
+ make_build ,
345
+ configure_host ,
346
+ make_host ,
347
+ ):
307
348
subcommand .add_argument (
308
349
"--quiet" ,
309
350
action = "store_true" ,
@@ -336,6 +377,7 @@ def main():
336
377
context = parser .parse_args ()
337
378
338
379
dispatch = {
380
+ "make-libffi" : make_emscripten_libffi ,
339
381
"configure-build-python" : configure_build_python ,
340
382
"make-build-python" : make_build_python ,
341
383
"configure-host" : configure_emscripten_python ,
0 commit comments