use std::env; use std::fs; use std::path::PathBuf; use std::process::Command; use wit_bindgen_gen_core::{wit_parser::Interface, Generator}; fn main() { let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap()); let mut wasms = Vec::new(); if cfg!(feature = "wasm-rust") { let mut cmd = Command::new("cargo"); cmd.arg("build") .current_dir("../test-rust-wasm") .arg("--target=wasm32-wasi") .env("CARGO_TARGET_DIR", &out_dir) .env("CARGO_PROFILE_DEV_DEBUG", "1") .env("RUSTFLAGS", "-Clink-args=--export-table") .env_remove("CARGO_ENCODED_RUSTFLAGS"); let status = cmd.status().unwrap(); assert!(status.success()); for file in out_dir.join("wasm32-wasi/debug").read_dir().unwrap() { let file = file.unwrap().path(); if file.extension().and_then(|s| s.to_str()) != Some("wasm") { continue; } wasms.push(( "rust", file.file_stem().unwrap().to_str().unwrap().to_string(), file.to_str().unwrap().to_string(), )); let dep_file = file.with_extension("d"); let deps = fs::read_to_string(&dep_file).expect("failed to read dep file"); for dep in deps .splitn(2, ":") .skip(1) .next() .unwrap() .split_whitespace() { println!("cargo:rerun-if-changed={}", dep); } } println!("cargo:rerun-if-changed=../test-rust-wasm/Cargo.toml"); } if cfg!(feature = "wasm-c") { for test_dir in fs::read_dir("../../tests/runtime").unwrap() { let test_dir = test_dir.unwrap().path(); let c_impl = test_dir.join("wasm.c"); if !c_impl.exists() { continue; } let imports = test_dir.join("imports.wit"); let exports = test_dir.join("exports.wit"); println!("cargo:rerun-if-changed={}", imports.display()); println!("cargo:rerun-if-changed={}", exports.display()); println!("cargo:rerun-if-changed={}", c_impl.display()); let import = Interface::parse_file(&test_dir.join("imports.wit")).unwrap(); let export = Interface::parse_file(&test_dir.join("exports.wit")).unwrap(); let mut files = Default::default(); // TODO: should combine this into one wit_bindgen_gen_c::Opts::default() .build() .generate_all(&[import], &[], &mut files); wit_bindgen_gen_c::Opts::default() .build() .generate_all(&[], &[export], &mut files); let out_dir = out_dir.join(format!( "c-{}", test_dir.file_name().unwrap().to_str().unwrap() )); drop(fs::remove_dir_all(&out_dir)); fs::create_dir(&out_dir).unwrap(); for (file, contents) in files.iter() { let dst = out_dir.join(file); fs::write(dst, contents).unwrap(); } let path = PathBuf::from(env::var_os("WASI_SDK_PATH").expect( "point the `WASI_SDK_PATH` environment variable to the path of your wasi-sdk", )); let mut cmd = Command::new(path.join("bin/clang")); let out_wasm = out_dir.join("c.wasm"); cmd.arg("--sysroot").arg(path.join("share/wasi-sysroot")); cmd.arg(c_impl) .arg(out_dir.join("imports.c")) .arg(out_dir.join("exports.c")) .arg("-I") .arg(&out_dir) .arg("-Wall") .arg("-Wextra") .arg("-Werror") .arg("-Wno-unused-parameter") .arg("-mexec-model=reactor") .arg("-g") .arg("-o") .arg(&out_wasm); println!("{:?}", cmd); let output = match cmd.output() { Ok(output) => output, Err(e) => panic!("failed to spawn compiler: {}", e), }; if !output.status.success() { println!("status: {}", output.status); println!("stdout: ------------------------------------------"); println!("{}", String::from_utf8_lossy(&output.stdout)); println!("stderr: ------------------------------------------"); println!("{}", String::from_utf8_lossy(&output.stderr)); panic!("failed to compile"); } wasms.push(( "c", test_dir.file_stem().unwrap().to_str().unwrap().to_string(), out_wasm.to_str().unwrap().to_string(), )); } } if cfg!(feature = "wasm-spidermonkey") { for test_dir in fs::read_dir("../../tests/runtime").unwrap() { let test_dir = test_dir.unwrap().path(); let js_impl = test_dir.join("wasm.js"); if !js_impl.exists() { continue; } let imports = test_dir.join("imports.wit"); let exports = test_dir.join("exports.wit"); println!("cargo:rerun-if-changed={}", imports.display()); println!("cargo:rerun-if-changed={}", exports.display()); println!("cargo:rerun-if-changed={}", js_impl.display()); let import = Interface::parse_file(&test_dir.join("imports.wit")).unwrap(); let export = Interface::parse_file(&test_dir.join("exports.wit")).unwrap(); let mut files = Default::default(); let js = fs::read_to_string(&js_impl).unwrap(); let mut gen = wit_bindgen_gen_spidermonkey::SpiderMonkeyWasm::new("wasm.js", &js); gen.import_spidermonkey(true); gen.generate_all(&[import], &[export], &mut files); let out_dir = out_dir.join(format!( "js-{}", test_dir.file_name().unwrap().to_str().unwrap() )); drop(fs::remove_dir_all(&out_dir)); fs::create_dir(&out_dir).unwrap(); for (file, contents) in files.iter() { let dst = out_dir.join(file); fs::write(dst, contents).unwrap(); } wasms.push(( "spidermonkey", test_dir.file_stem().unwrap().to_str().unwrap().to_string(), out_dir.join("wasm.wasm").to_str().unwrap().to_string(), )); } } let src = format!("const WASMS: &[(&str, &str, &str)] = &{:?};", wasms); std::fs::write(out_dir.join("wasms.rs"), src).unwrap(); }