wasmer 5.0.1

High-performance WebAssembly runtime
Documentation
fn main() {
    #[cfg(feature = "wamr")]
    {
        const WAMR_ZIP: &str = "https://github.com/bytecodealliance/wasm-micro-runtime/archive/refs/tags/WAMR-2.1.0.zip";
        const WAMR_DIR: &str = "wasm-micro-runtime-WAMR-2.1.0";

        use cmake::Config;
        use std::{env, path::PathBuf};

        let crate_root = env::var("CARGO_MANIFEST_DIR").unwrap();

        // Read target os from cargo env
        // Transform from cargo value to valid wasm-micro-runtime os
        let target_os = match env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() {
            "linux" => "linux",
            "windows" => "windows",
            "macos" => "darwin",
            "freebsd" => "freebsd",
            "android" => "android",
            "ios" => "ios",
            other => panic!("Unsupported CARGO_CFG_TARGET_OS: {}", other),
        };

        // Read target arch from cargo env
        // Transform from cargo value to valid wasm-micro-runtime WAMR_BUILD_TARGET
        let target_arch = match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() {
            "x86" => "X86_32",
            "x86_64" => "X86_64",
            "arm" => "ARM",
            "aarch64" => "AARCH64",
            "mips" => "MIPS",
            "powerpc" => "POWERPC",
            "powerpc64" => "POWERPC64",
            other => panic!("Unsupported CARGO_CFG_TARGET_ARCH: {}", other),
        };

        // Cleanup tmp data from prior builds
        let wamr_dir = PathBuf::from(&crate_root).join("third_party/wamr");
        let zip_dir = PathBuf::from(&crate_root).join(WAMR_DIR);
        let _ = std::fs::remove_dir_all(&wamr_dir);
        let _ = std::fs::remove_dir_all(&zip_dir);

        // Fetch & extract wasm-micro-runtime source
        let zip = ureq::get(WAMR_ZIP).call().expect("failed to download wamr");
        let mut zip_data = Vec::new();
        zip.into_reader()
            .read_to_end(&mut zip_data)
            .expect("failed to download wamr");
        zip::read::ZipArchive::new(std::io::Cursor::new(zip_data))
            .expect("failed to open wamr zip file")
            .extract(&crate_root)
            .expect("failed to extract wamr zip file");
        let _ = std::fs::remove_dir_all(&wamr_dir);
        std::fs::rename(zip_dir, &wamr_dir).expect("failed to rename wamr dir");

        let wamr_platform_dir = wamr_dir.join("product-mini/platforms").join(target_os);
        let mut dst = Config::new(wamr_platform_dir.as_path());

        dst.always_configure(true)
            .generator("Ninja")
            .no_build_target(true)
            .define(
                "CMAKE_BUILD_TYPE",
                if cfg!(debug_assertions) {
                    "RelWithDebInfo"
                } else {
                    "Release"
                },
            )
            .define("WAMR_BUILD_AOT", "0")
            //.define("WAMR_BUILD_TAIL_CALL", "1")
            //.define("WAMR_BUILD_DUMP_CALL_STACK", "1")
            // .define("WAMR_BUILD_CUSTOM_NAME_SECTION", "1")
            // .define("WAMR_BUILD_LOAD_CUSTOM_SECTION", "1")
            .define("WAMR_BUILD_BULK_MEMORY", "1")
            .define("WAMR_BUILD_REF_TYPES", "1")
            .define("WAMR_BUILD_SIMD", "1")
            .define("WAMR_BUILD_FAST_INTERP", "1")
            .define("WAMR_BUILD_LIB_PTHREAD", "1")
            .define("WAMR_BUILD_LIB_WASI_THREADS", "0")
            .define("WAMR_BUILD_LIBC_WASI", "0")
            .define("WAMR_BUILD_LIBC_BUILTIN", "0")
            .define("WAMR_BUILD_SHARED_MEMORY", "1")
            .define("WAMR_BUILD_MULTI_MODULE", "0")
            .define("WAMR_DISABLE_HW_BOUND_CHECK", "1")
            .define("WAMR_BUILD_TARGET", target_arch);

        if target_os == "windows" {
            dst.define("CMAKE_CXX_COMPILER", "cl.exe");
            dst.define("CMAKE_C_COMPILER", "cl.exe");
            dst.define("CMAKE_LINKER_TYPE", "MSVC");
            dst.define("WAMR_BUILD_PLATFORM", "windows");
            dst.define("WAMR_BUILD_LIBC_UVWASI", "0");
        }

        if target_os == "ios" {
            // XXX: Hacky
            //
            // Compiling wamr targeting `aarch64-apple-ios` results in
            //
            // ```
            //  clang: error: unsupported option '-mfloat-abi=' for target 'aarch64-apple-ios'
            // ```
            // So, here, we simply remove that setting.
            //
            // See: https://github.com/bytecodealliance/wasm-micro-runtime/pull/3889
            let mut lines = vec![];
            let cmake_file_path = wamr_platform_dir.join("CMakeLists.txt");
            for line in std::fs::read_to_string(&cmake_file_path).unwrap().lines() {
                if !line.contains("-mfloat-abi=hard") {
                    lines.push(line.to_string())
                }
            }
            std::fs::write(cmake_file_path, lines.join("\n")).unwrap();
        }

        let dst = dst.build();

        // Check output of `cargo build --verbose`, should see something like:
        // -L native=/path/runng/target/debug/build/runng-sys-abc1234/out
        // That contains output from cmake
        println!(
            "cargo:rustc-link-search=native={}",
            dst.join("build").display()
        );
        println!("cargo:rustc-link-lib=vmlib");

        let bindings = bindgen::Builder::default()
            .header(
                wamr_dir
                    .join("core/iwasm/include/wasm_c_api.h")
                    .to_str()
                    .unwrap(),
            )
            .header(
                wamr_dir
                    .join("core/iwasm/include/wasm_export.h")
                    .to_str()
                    .unwrap(),
            )
            .derive_default(true)
            .derive_debug(true)
            .generate()
            .expect("Unable to generate bindings");
        let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
        bindings
            .write_to_file(out_path.join("bindings.rs"))
            .expect("Couldn't write bindings");
    }

    #[cfg(feature = "wasmi")]
    {
        use std::{env, path::PathBuf};

        let bindings = bindgen::Builder::default()
            .header(
                PathBuf::from(std::env::var("DEP_WASMI_C_API_INCLUDE").unwrap())
                    .join("wasm.h")
                    .to_string_lossy(),
            )
            .derive_default(true)
            .derive_debug(true)
            .generate()
            .expect("Unable to generate bindings for `wasmi`!");
        let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
        bindings
            .write_to_file(out_path.join("bindings.rs"))
            .expect("Couldn't write bindings");
    }

    #[cfg(feature = "v8")]
    {
        use std::{env, path::PathBuf};

        let url = match (
            env::var("CARGO_CFG_TARGET_OS").unwrap().as_str(),
            env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str(),
            env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default().as_str(),
        ) {
            ("macos", "aarch64", _) => "https://github.com/wasmerio/wee8-custom-builds/releases/download/11.7/wee8-darwin-aarch64.tar.xz",
            ("macos", "x86_64", _) => "https://github.com/wasmerio/wee8-custom-builds/releases/download/11.7/wee8-darwin-amd64.tar.xz",
            ("linux", "x86_64", "gnu") => "https://github.com/wasmerio/wee8-custom-builds/releases/download/11.7/wee8-linux-amd64.tar.xz",
            ("linux", "x86_64", "musl") => "https://github.com/wasmerio/wee8-custom-builds/releases/download/11.7/wee8-linux-musl.tar.xz",
            ("windows", "x86_64", _) => "https://github.com/wasmerio/wee8-custom-builds/releases/download/11.7/wee8-windows-amd64.tar.xz",
            (os, arch, _) => panic!("target os + arch combination not supported: {os}, {arch}"),
        };

        let crate_root = env::var("CARGO_MANIFEST_DIR").unwrap();
        let v8_dir = PathBuf::from(&crate_root).join("third_party").join("v8");
        let out_dir = env::var("OUT_DIR").unwrap();

        let tar = ureq::get(url).call().expect("failed to download v8");

        let mut tar_data = Vec::new();
        tar.into_reader()
            .read_to_end(&mut tar_data)
            .expect("failed to download v8 lib");

        let tar = xz::read::XzDecoder::new(tar_data.as_slice());
        let mut archive = tar::Archive::new(tar);

        for entry in archive.entries().unwrap() {
            eprintln!("entry: {:?}", entry.unwrap().path());
        }

        let tar = xz::read::XzDecoder::new(tar_data.as_slice());
        let mut archive = tar::Archive::new(tar);

        archive.unpack(out_dir.clone()).unwrap();

        println!("cargo:rustc-link-search=native={}", out_dir);

        println!("cargo:rustc-link-lib=static=wee8");
        println!("cargo:rustc-link-lib=v8_initializers");
        println!("cargo:rustc-link-lib=v8_libbase");
        println!("cargo:rustc-link-lib=v8_base_without_compiler");
        println!("cargo:rustc-link-lib=v8_compiler");
        println!("cargo:rustc-link-lib=v8_libplatform");
        println!("cargo:rustc-link-lib=v8_libsampler");
        println!("cargo:rustc-link-lib=v8_snapshot");
        println!("cargo:rustc-link-lib=v8_torque_generated");

        if cfg!(any(target_os = "linux",)) {
            println!("cargo:rustc-link-lib=stdc++");
        } else if cfg!(target_os = "windows") {
            /* do nothing */
            println!("cargo:rustc-link-lib=winmm");
            println!("cargo:rustc-link-lib=dbghelp");
            println!("cargo:rustc-link-lib=shlwapi");
        } else {
            println!("cargo:rustc-link-lib=c++");
        }

        let bindings = bindgen::Builder::default()
            .header(v8_dir.join("wasm.h").to_str().unwrap())
            .derive_default(true)
            .derive_debug(true)
            .generate()
            .expect("Unable to generate bindings for `v8`!");

        let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

        bindings
            .write_to_file(out_path.join("bindings.rs"))
            .expect("Couldn't write bindings");
    }
}