99import sys
1010import sysconfig
1111import tempfile
12+ from urllib .request import urlopen
1213from pathlib import Path
1314from textwrap import dedent
1415
2223CHECKOUT = EMSCRIPTEN_DIR .parent .parent .parent
2324
2425CROSS_BUILD_DIR = CHECKOUT / "cross-build"
25- BUILD_DIR = CROSS_BUILD_DIR / "build"
26+ NATIVE_BUILD_DIR = CROSS_BUILD_DIR / "build"
2627HOST_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"
2833
2934LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local"
3035LOCAL_SETUP_MARKER = "# Generated by Tools/wasm/emscripten.py\n " .encode ("utf-8" )
@@ -118,16 +123,16 @@ def build_platform():
118123
119124def build_python_path ():
120125 """The path to the build Python binary."""
121- binary = BUILD_DIR / "python"
126+ binary = NATIVE_BUILD_DIR / "python"
122127 if not binary .is_file ():
123128 binary = binary .with_suffix (".exe" )
124129 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 } " )
126131
127132 return binary
128133
129134
130- @subdir (BUILD_DIR , clean_ok = True )
135+ @subdir (NATIVE_BUILD_DIR , clean_ok = True )
131136def configure_build_python (context , working_dir ):
132137 """Configure the build/host Python."""
133138 if LOCAL_SETUP .exists ():
@@ -143,7 +148,7 @@ def configure_build_python(context, working_dir):
143148 call (configure , quiet = context .quiet )
144149
145150
146- @subdir (BUILD_DIR )
151+ @subdir (NATIVE_BUILD_DIR )
147152def make_build_python (context , working_dir ):
148153 """Make/build the build Python."""
149154 call (["make" , "--jobs" , str (cpu_count ()), "all" ], quiet = context .quiet )
@@ -159,6 +164,23 @@ def make_build_python(context, working_dir):
159164 print (f"🎉 { binary } { version } " )
160165
161166
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+
162184@subdir (HOST_DIR , clean_ok = True )
163185def configure_emscripten_python (context , working_dir ):
164186 """Configure the emscripten/host build."""
@@ -168,7 +190,7 @@ def configure_emscripten_python(context, working_dir):
168190
169191 emscripten_build_dir = working_dir .relative_to (CHECKOUT )
170192
171- python_build_dir = BUILD_DIR / "build"
193+ python_build_dir = NATIVE_BUILD_DIR / "build"
172194 lib_dirs = list (python_build_dir .glob ("lib.*" ))
173195 assert (
174196 len (lib_dirs ) == 1
@@ -183,12 +205,18 @@ def configure_emscripten_python(context, working_dir):
183205 sysconfig_data += "-pydebug"
184206
185207 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+ }
187214 build_python = os .fsdecode (build_python_path ())
188215 configure = [
189216 "emconfigure" ,
190217 os .path .relpath (CHECKOUT / "configure" , working_dir ),
191218 "CFLAGS=-DPY_CALL_TRAMPOLINE -sUSE_BZIP2" ,
219+ "PKG_CONFIG=pkg-config" ,
192220 f"--host={ HOST_TRIPLE } " ,
193221 f"--build={ build_platform ()} " ,
194222 f"--with-build-python={ build_python } " ,
@@ -197,7 +225,7 @@ def configure_emscripten_python(context, working_dir):
197225 "--disable-ipv6" ,
198226 "--enable-big-digits=30" ,
199227 "--enable-wasm-dynamic-linking" ,
200- f"--prefix={ HOST_DIR } " ,
228+ f"--prefix={ PREFIX_DIR } " ,
201229 ]
202230 if pydebug :
203231 configure .append ("--with-pydebug" )
@@ -264,6 +292,7 @@ def build_all(context):
264292 steps = [
265293 configure_build_python ,
266294 make_build_python ,
295+ make_emscripten_libffi ,
267296 configure_emscripten_python ,
268297 make_emscripten_python ,
269298 ]
@@ -292,18 +321,30 @@ def main():
292321 configure_build = subcommands .add_parser (
293322 "configure-build-python" , help = "Run `configure` for the " "build Python"
294323 )
324+ make_libffi_cmd = subcommands .add_parser (
325+ "make-libffi" , help = "Clone libffi repo, configure and build it for emscripten"
326+ )
295327 make_build = subcommands .add_parser (
296328 "make-build-python" , help = "Run `make` for the build Python"
297329 )
298330 configure_host = subcommands .add_parser (
299331 "configure-host" ,
300332 help = "Run `configure` for the host/emscripten (pydebug builds are inferred from the build Python)" ,
301333 )
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+ )
303337 clean = subcommands .add_parser (
304338 "clean" , help = "Delete files and directories created by this script"
305339 )
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+ ):
307348 subcommand .add_argument (
308349 "--quiet" ,
309350 action = "store_true" ,
@@ -336,6 +377,7 @@ def main():
336377 context = parser .parse_args ()
337378
338379 dispatch = {
380+ "make-libffi" : make_emscripten_libffi ,
339381 "configure-build-python" : configure_build_python ,
340382 "make-build-python" : make_build_python ,
341383 "configure-host" : configure_emscripten_python ,
0 commit comments