diff --git a/rust/ruby-rbs-sys/build.rs b/rust/ruby-rbs-sys/build.rs index c4ff9d13c..30db55f40 100644 --- a/rust/ruby-rbs-sys/build.rs +++ b/rust/ruby-rbs-sys/build.rs @@ -11,15 +11,18 @@ fn main() -> Result<(), Box> { let include = vendor_rbs.join("include"); let c_src = vendor_rbs.join("src"); - build(&include, &c_src)?; + let target = env::var("TARGET").unwrap_or_default(); + let is_wasm = target.contains("wasm32"); - let bindings = generate_bindings(&include)?; + build(&include, &c_src, is_wasm)?; + + let bindings = generate_bindings(&include, is_wasm)?; write_bindings(&bindings)?; Ok(()) } -fn build(include_dir: &Path, src_dir: &Path) -> Result<(), Box> { +fn build(include_dir: &Path, src_dir: &Path, is_wasm: bool) -> Result<(), Box> { let mut build = cc::Build::new(); build.include(include_dir); @@ -27,6 +30,27 @@ fn build(include_dir: &Path, src_dir: &Path) -> Result<(), Box> { // Suppress unused parameter warnings from C code build.flag_if_supported("-Wno-unused-parameter"); + // Cross-compile the C parser to wasm with the WASI SDK's clang. Only the C + // compile targets wasm; bindgen (below) still runs against the host, since + // the resulting #[repr(C)] declarations are layout-portable. + if is_wasm { + let wasi_sdk = PathBuf::from( + env::var("WASI_SDK_PATH").expect("WASI_SDK_PATH must be set for wasm builds"), + ); + build.compiler(wasi_sdk.join("bin").join("clang")); + + let sysroot = wasi_sdk.join("share").join("wasi-sysroot"); + build.flag(&format!("--sysroot={}", sysroot.display())); + build.include(sysroot.join("include")); + + println!( + "cargo:rustc-link-search=native={}", + sysroot.join("lib/wasm32-wasi").display() + ); + build.define("_WASI_EMULATED_MMAN", "1"); + println!("cargo:rustc-link-lib=wasi-emulated-mman"); + } + build.files(source_files(src_dir)?); build.try_compile("rbs")?; @@ -64,8 +88,11 @@ fn source_files>(root_dir: P) -> Result, Box Result> { - let bindings = bindgen::Builder::default() +fn generate_bindings( + include_path: &Path, + is_wasm: bool, +) -> Result> { + let mut builder = bindgen::Builder::default() .header("wrapper.h") .clang_arg(format!("-I{}", include_path.display())) .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) @@ -170,7 +197,22 @@ fn generate_bindings(include_path: &Path) -> Result