@@ -11,22 +11,47 @@ fn main() -> Result<(), Box<dyn Error>> {
1111 let include = vendor_rbs. join ( "include" ) ;
1212 let c_src = vendor_rbs. join ( "src" ) ;
1313
14- build ( & include, & c_src) ?;
14+ let target = env:: var ( "TARGET" ) . unwrap_or_default ( ) ;
15+ let is_wasi = target. contains ( "wasm32" ) && target. contains ( "wasi" ) ;
1516
16- let bindings = generate_bindings ( & include) ?;
17+ build ( & include, & c_src, is_wasi) ?;
18+
19+ let bindings = generate_bindings ( & include, is_wasi) ?;
1720 write_bindings ( & bindings) ?;
1821
1922 Ok ( ( ) )
2023}
2124
22- fn build ( include_dir : & Path , src_dir : & Path ) -> Result < ( ) , Box < dyn Error > > {
25+ fn build ( include_dir : & Path , src_dir : & Path , is_wasi : bool ) -> Result < ( ) , Box < dyn Error > > {
2326 let mut build = cc:: Build :: new ( ) ;
2427
2528 build. include ( include_dir) ;
2629
2730 // Suppress unused parameter warnings from C code
2831 build. flag_if_supported ( "-Wno-unused-parameter" ) ;
2932
33+ if is_wasi {
34+ // Compile the C parser with the WASI SDK so that its headers and
35+ // runtime support match the target platform.
36+ println ! ( "cargo:rerun-if-env-changed=WASI_SDK_PATH" ) ;
37+
38+ let wasi_sdk = PathBuf :: from (
39+ env:: var ( "WASI_SDK_PATH" ) . expect ( "WASI_SDK_PATH must be set for wasm builds" ) ,
40+ ) ;
41+ build. compiler ( wasi_sdk. join ( "bin" ) . join ( "clang" ) ) ;
42+
43+ let sysroot = wasi_sdk. join ( "share" ) . join ( "wasi-sysroot" ) ;
44+ build. flag ( format ! ( "--sysroot={}" , sysroot. display( ) ) ) ;
45+ build. include ( sysroot. join ( "include" ) ) ;
46+
47+ println ! (
48+ "cargo:rustc-link-search=native={}" ,
49+ sysroot. join( "lib/wasm32-wasi" ) . display( )
50+ ) ;
51+ build. define ( "_WASI_EMULATED_MMAN" , "1" ) ;
52+ println ! ( "cargo:rustc-link-lib=wasi-emulated-mman" ) ;
53+ }
54+
3055 build. files ( source_files ( src_dir) ?) ;
3156 build. try_compile ( "rbs" ) ?;
3257
@@ -64,8 +89,11 @@ fn source_files<P: AsRef<Path>>(root_dir: P) -> Result<Vec<String>, Box<dyn Erro
6489 Ok ( files)
6590}
6691
67- fn generate_bindings ( include_path : & Path ) -> Result < bindgen:: Bindings , Box < dyn Error > > {
68- let bindings = bindgen:: Builder :: default ( )
92+ fn generate_bindings (
93+ include_path : & Path ,
94+ is_wasi : bool ,
95+ ) -> Result < bindgen:: Bindings , Box < dyn Error > > {
96+ let mut builder = bindgen:: Builder :: default ( )
6997 . header ( "wrapper.h" )
7098 . clang_arg ( format ! ( "-I{}" , include_path. display( ) ) )
7199 . parse_callbacks ( Box :: new ( bindgen:: CargoCallbacks :: new ( ) ) )
@@ -172,7 +200,20 @@ fn generate_bindings(include_path: &Path) -> Result<bindgen::Bindings, Box<dyn E
172200 // Constant pool functions
173201 . allowlist_function ( "rbs_constant_pool_free" )
174202 . allowlist_function ( "rbs_constant_pool_id_to_constant" )
175- . allowlist_function ( "rbs_constant_pool_init" )
203+ . allowlist_function ( "rbs_constant_pool_init" ) ;
204+
205+ if is_wasi {
206+ // wasm-target bindgen output depends on the libclang implementation
207+ // and may drop declarations or make structs opaque. Generate the
208+ // ABI declarations with the host target instead; rustc will compile
209+ // them for the actual target. Host layout tests are not valid here.
210+ let host = env:: var ( "HOST" ) . expect ( "HOST is not set" ) ;
211+ builder = builder
212+ . clang_arg ( format ! ( "--target={host}" ) )
213+ . layout_tests ( false ) ;
214+ }
215+
216+ let bindings = builder
176217 . generate ( )
177218 . map_err ( |_| "Unable to generate rbs bindings" ) ?;
178219
0 commit comments