@@ -272,11 +272,11 @@ fn find_python_binary(cpython_dir: &Path) -> Option<&'static str> {
272272fn maybe_make_cpython ( repo_dir : & Path , wasi_sdk : & Path ) -> Result < ( ) > {
273273 let cpython_wasi_dir = repo_dir. join ( "cpython/builddir/wasi" ) ;
274274 if !cpython_wasi_dir. join ( "libpython3.14.so" ) . exists ( ) {
275+ fs:: create_dir_all ( & cpython_wasi_dir) ?;
275276 if !cpython_wasi_dir. join ( "libpython3.14.a" ) . exists ( ) {
276277 let cpython_native_dir = repo_dir. join ( "cpython/builddir/build" ) ;
277278 if let None = find_python_binary ( & cpython_native_dir) {
278279 fs:: create_dir_all ( & cpython_native_dir) ?;
279- fs:: create_dir_all ( & cpython_wasi_dir) ?;
280280
281281 run ( Command :: new ( "../../configure" )
282282 . current_dir ( & cpython_native_dir)
@@ -288,9 +288,15 @@ fn maybe_make_cpython(repo_dir: &Path, wasi_sdk: &Path) -> Result<()> {
288288 run ( Command :: new ( "make" ) . current_dir ( & cpython_native_dir) ) ?;
289289 }
290290 let Some ( python_executable) = find_python_binary ( & cpython_native_dir) else {
291- bail ! ( "python binary not found" ) ;
291+ anyhow :: bail!( "python binary not found" ) ;
292292 } ;
293293
294+ let lib_install_dir = cpython_wasi_dir. join ( "deps" ) ;
295+ build_zlib ( wasi_sdk, & lib_install_dir) ?;
296+ build_bzip2 ( wasi_sdk, & lib_install_dir) ?;
297+ build_xz ( wasi_sdk, & lib_install_dir) ?;
298+ build_zstd ( wasi_sdk, & lib_install_dir) ?;
299+
294300 let config_guess =
295301 run ( Command :: new ( "../../config.guess" ) . current_dir ( & cpython_wasi_dir) ) ?;
296302
@@ -299,7 +305,14 @@ fn maybe_make_cpython(repo_dir: &Path, wasi_sdk: &Path) -> Result<()> {
299305 "CONFIG_SITE" ,
300306 "../../Tools/wasm/wasi/config.site-wasm32-wasi" ,
301307 )
302- . env ( "CFLAGS" , "-fPIC" )
308+ . env (
309+ "CFLAGS" ,
310+ format ! ( "-fPIC -I{}/deps/include" , cpython_wasi_dir. display( ) ) ,
311+ )
312+ . env (
313+ "LDFLAGS" ,
314+ format ! ( "-L{}/deps/lib" , cpython_wasi_dir. display( ) ) ,
315+ )
303316 . current_dir ( & cpython_wasi_dir)
304317 . args ( [
305318 "../../configure" ,
@@ -336,6 +349,10 @@ fn maybe_make_cpython(repo_dir: &Path, wasi_sdk: &Path) -> Result<()> {
336349 . arg ( cpython_wasi_dir. join ( "Modules/_hacl/libHacl_Hash_SHA3.a" ) )
337350 . arg ( cpython_wasi_dir. join ( "Modules/_decimal/libmpdec/libmpdec.a" ) )
338351 . arg ( cpython_wasi_dir. join ( "Modules/expat/libexpat.a" ) )
352+ . arg ( cpython_wasi_dir. join ( "deps/lib/libz.a" ) )
353+ . arg ( cpython_wasi_dir. join ( "deps/lib/libbz2.a" ) )
354+ . arg ( cpython_wasi_dir. join ( "deps/lib/liblzma.a" ) )
355+ . arg ( cpython_wasi_dir. join ( "deps/lib/libzstd.a" ) )
339356 . arg ( "-lwasi-emulated-signal" )
340357 . arg ( "-lwasi-emulated-getpid" )
341358 . arg ( "-lwasi-emulated-process-clocks" )
@@ -395,3 +412,142 @@ fn make_pyo3_config(repo_dir: &Path) -> Result<()> {
395412
396413 Ok ( ( ) )
397414}
415+
416+ fn fetch_extract ( url : & str , out_dir : & Path ) -> Result < ( ) > {
417+ let response = reqwest:: blocking:: get ( url) ?;
418+ let decoder = flate2:: read:: GzDecoder :: new ( response) ;
419+ let mut archive = tar:: Archive :: new ( decoder) ;
420+ archive. unpack ( out_dir) ?;
421+ Ok ( ( ) )
422+ }
423+
424+ fn add_compile_envs ( wasi_sdk : & Path , command : & mut Command ) {
425+ let sysroot = wasi_sdk. join ( "share/wasi-sysroot" ) ;
426+ let sysroot = sysroot. to_string_lossy ( ) ;
427+ command
428+ . env ( "AR" , wasi_sdk. join ( "bin/ar" ) )
429+ . env ( "CC" , wasi_sdk. join ( "bin/clang" ) )
430+ . env ( "RANLIB" , wasi_sdk. join ( "bin/ranlib" ) )
431+ . env (
432+ "CFLAGS" ,
433+ format ! ( "--target=wasm32-wasi --sysroot={sysroot} -I{sysroot}/include/wasm32-wasip1 -D_WASI_EMULATED_SIGNAL -fPIC" ) ,
434+ )
435+ . env (
436+ "LDFLAGS" ,
437+ format ! ( "--target=wasm32-wasip2 --sysroot={sysroot} -L{sysroot}/lib -lwasi-emulated-signal" )
438+ ) ;
439+ }
440+
441+ fn copy_headers ( from : & Path , to : & Path ) -> Result < ( ) > {
442+ for entry in fs:: read_dir ( from) ? {
443+ let entry = entry?;
444+ let path = entry. path ( ) ;
445+
446+ if let Some ( ext) = path. extension ( ) {
447+ if ext == "h" {
448+ let filename = path. file_name ( ) . unwrap ( ) ;
449+ fs:: copy ( & path, to. join ( filename) ) ?;
450+ }
451+ }
452+ }
453+ Ok ( ( ) )
454+ }
455+
456+ fn build_zlib ( wasi_sdk : & Path , install_dir : & Path ) -> Result < ( ) > {
457+ let out_dir = PathBuf :: from ( env:: var ( "OUT_DIR" ) ?) ;
458+ fetch_extract (
459+ "https://github.com/madler/zlib/releases/download/v1.3.1/zlib-1.3.1.tar.gz" ,
460+ & out_dir,
461+ ) ?;
462+ let src_dir = out_dir. join ( "zlib-1.3.1" ) ;
463+ let mut configure = Command :: new ( "./configure" ) ;
464+ configure
465+ . current_dir ( & src_dir)
466+ . arg ( "--static" )
467+ . arg ( format ! ( "--prefix={}" , install_dir. display( ) ) ) ;
468+ add_compile_envs ( wasi_sdk, & mut configure) ;
469+ run ( & mut configure) ?;
470+ let mut make = Command :: new ( "make" ) ;
471+ add_compile_envs ( wasi_sdk, & mut make) ;
472+ make. current_dir ( src_dir)
473+ . arg ( format ! ( "AR={}" , wasi_sdk. join( "bin/ar" ) . display( ) ) )
474+ . arg ( format ! ( "ARFLAGS=rcs" ) )
475+ . arg ( format ! ( "CC={}" , wasi_sdk. join( "bin/clang" ) . display( ) ) )
476+ . arg ( "static" )
477+ . arg ( "install" ) ;
478+ run ( & mut make) ?;
479+ Ok ( ( ) )
480+ }
481+
482+ fn build_bzip2 ( wasi_sdk : & Path , install_dir : & Path ) -> Result < ( ) > {
483+ let out_dir = PathBuf :: from ( env:: var ( "OUT_DIR" ) ?) ;
484+ fetch_extract (
485+ "https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz" ,
486+ & out_dir,
487+ ) ?;
488+ let src_dir = out_dir. join ( "bzip2-1.0.8" ) ;
489+ let mut command = Command :: new ( "make" ) ;
490+ command
491+ . current_dir ( & src_dir)
492+ . arg ( format ! ( "CC={}" , wasi_sdk. join( "bin/clang" ) . display( ) ) )
493+ . arg ( format ! ( "AR={}" , wasi_sdk. join( "bin/ar" ) . display( ) ) )
494+ . arg ( format ! ( "RANLIB={}" , wasi_sdk. join( "bin/ranlib" ) . display( ) ) )
495+ . arg ( "CFLAGS=\" -fPIC\" " )
496+ . arg ( "libbz2.a" ) ;
497+ add_compile_envs ( wasi_sdk, & mut command) ;
498+ run ( & mut command) ?;
499+ copy_headers ( & src_dir, & install_dir. join ( "include" ) ) ?;
500+ fs:: copy ( src_dir. join ( "libbz2.a" ) , install_dir. join ( "lib/libbz2.a" ) ) ?;
501+ Ok ( ( ) )
502+ }
503+
504+ fn build_xz ( wasi_sdk : & Path , install_dir : & Path ) -> Result < ( ) > {
505+ let out_dir = PathBuf :: from ( env:: var ( "OUT_DIR" ) ?) ;
506+ fetch_extract (
507+ "https://github.com/tukaani-project/xz/releases/download/v5.8.1/xz-5.8.1.tar.gz" ,
508+ & out_dir,
509+ ) ?;
510+ let src_dir = out_dir. join ( "xz-5.8.1" ) ;
511+ let mut command = Command :: new ( "./autogen.sh" ) ;
512+ command. current_dir ( & src_dir) ;
513+ add_compile_envs ( wasi_sdk, & mut command) ;
514+ run ( & mut command) ?;
515+ let mut command = Command :: new ( "./configure" ) ;
516+ command
517+ . current_dir ( & src_dir)
518+ . arg ( format ! ( "--prefix={}" , install_dir. display( ) ) )
519+ . arg ( "--host=wasm32-unknown-wasi" )
520+ . arg ( "--enable-threads=no" )
521+ . arg ( "--disable-xz" )
522+ . arg ( "--disable-xzdec" )
523+ . arg ( "--disable-lzmadec" )
524+ . arg ( "--disable-lzmainfo" )
525+ . arg ( "--disable-lzma-links" )
526+ . arg ( "--disable-scripts" )
527+ . arg ( "--disable-doc" )
528+ . arg ( "--disable-shared" )
529+ . arg ( "--enable-static" ) ;
530+ add_compile_envs ( wasi_sdk, & mut command) ;
531+ run ( & mut command) ?;
532+ let mut command = Command :: new ( "make" ) ;
533+ add_compile_envs ( wasi_sdk, & mut command) ;
534+ command. current_dir ( & src_dir) . arg ( "all" ) . arg ( "install" ) ;
535+ run ( & mut command) ?;
536+ Ok ( ( ) )
537+ }
538+
539+ fn build_zstd ( wasi_sdk : & Path , install_dir : & Path ) -> Result < ( ) > {
540+ let out_dir = PathBuf :: from ( env:: var ( "OUT_DIR" ) ?) ;
541+ fetch_extract (
542+ "https://github.com/facebook/zstd/releases/download/v1.5.7/zstd-1.5.7.tar.gz" ,
543+ & out_dir,
544+ ) ?;
545+ let src_dir = out_dir. join ( "zstd-1.5.7/lib" ) ;
546+ let mut command = Command :: new ( "make" ) ;
547+ add_compile_envs ( wasi_sdk, & mut command) ;
548+ command. current_dir ( & src_dir) . arg ( "libzstd.a" ) ;
549+ run ( & mut command) ?;
550+ copy_headers ( & src_dir, & install_dir. join ( "include" ) ) ?;
551+ fs:: copy ( src_dir. join ( "libzstd.a" ) , install_dir. join ( "lib/libzstd.a" ) ) ?;
552+ Ok ( ( ) )
553+ }
0 commit comments