diff --git a/spine-c/tests/rust-wasm/Cargo.lock b/spine-c/tests/rust-wasm/Cargo.lock deleted file mode 100644 index 6c4f1e288..000000000 --- a/spine-c/tests/rust-wasm/Cargo.lock +++ /dev/null @@ -1,296 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "bindgen" -version = "0.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", -] - -[[package]] -name = "bitflags" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" - -[[package]] -name = "cc" -version = "1.2.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" -dependencies = [ - "shlex", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "libc" -version = "0.2.174" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" - -[[package]] -name = "libloading" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" -dependencies = [ - "cfg-if", - "windows-targets", -] - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "memchr" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "prettyplease" -version = "0.2.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "spine-c-wasm-test" -version = "0.1.0" -dependencies = [ - "bindgen", - "cc", -] - -[[package]] -name = "syn" -version = "2.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "windows-targets" -version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" diff --git a/spine-c/tests/rust-wasm/Cargo.toml b/spine-c/tests/rust-wasm/Cargo.toml deleted file mode 100644 index ecb4bfeaa..000000000 --- a/spine-c/tests/rust-wasm/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "spine-c-wasm-test" -version = "0.1.0" -edition = "2021" - -[lib] -crate-type = ["cdylib"] - -[dependencies] - -[build-dependencies] -cc = "1.0" -bindgen = "0.70" \ No newline at end of file diff --git a/spine-c/tests/rust-wasm/README.md b/spine-c/tests/rust-wasm/README.md deleted file mode 100644 index 1f97acf2e..000000000 --- a/spine-c/tests/rust-wasm/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Spine-C Rust WASM Test - -A minimal test demonstrating Rust FFI with spine-c, proving the no-cpprt workflow for WASM compilation. - -## What This Does - -This test: -1. Loads a Spine atlas with texture callbacks (`spine_atlas_load_callback`) -2. Loads binary skeleton data (`spine_skeleton_data_load_binary`) -3. Creates a skeleton instance (`spine_skeleton_create`) -4. Runs basic skeleton operations (`spine_skeleton_setup_pose`, `spine_skeleton_update_world_transform_1`) -5. Reads skeleton position (`spine_skeleton_get_x/y`) -6. Cleans up all resources including atlas disposal with texture callbacks - -## Build Process - -The build script compiles: -- spine-cpp with no-cpprt variant (eliminates C++ standard library) -- spine-c wrapper (provides C-compatible FFI) -- Generates complete Rust FFI bindings via bindgen from spine-c.h -- Links everything into a single Rust executable/library - -**Full API Coverage**: Bindgen automatically generates Rust bindings for the entire spine-c API, exposing all public functions without manual FFI maintenance. - -spine-c/spine-cpp only rely on libc for `malloc`, `free` and various math functions, which can be easily stubbed on any target platform. - -This proves Rust projects can use Spine without C++ stdlib dependencies, enabling WASM compilation via Rust toolchain instead of Emscripten. - -## Files - -- `src/lib.rs` - Rust FFI test calling spine-c functions via bindgen-generated bindings -- `build.rs` - Compiles spine-cpp-no-cpprt + spine-c via cc crate, generates FFI bindings with bindgen -- Test data: `../../../examples/spineboy/export/spineboy-*` (atlas, skeleton, texture) - -## Usage - -```bash -cargo test -- --nocapture # Run test with debug output -cargo build # Build native -cargo build --target wasm32-unknown-unknown # Build WASM -``` - -**Status**: Fully working. Test executable: 1.8 MB. All spine-c functionality operational including atlas disposal. \ No newline at end of file diff --git a/spine-c/tests/rust-wasm/build.rs b/spine-c/tests/rust-wasm/build.rs deleted file mode 100644 index af154cc36..000000000 --- a/spine-c/tests/rust-wasm/build.rs +++ /dev/null @@ -1,100 +0,0 @@ -use std::env; -use std::path::PathBuf; - -fn main() { - let target = env::var("TARGET").unwrap(); - let is_wasm = target.starts_with("wasm32"); - - // Build spine-cpp with no-cpprt variant - let spine_cpp_dir = PathBuf::from("../../../spine-cpp"); - let spine_c_dir = PathBuf::from("../.."); - - let mut cpp_build = cc::Build::new(); - cpp_build - .cpp(true) - .include(spine_cpp_dir.join("include")) - .include(spine_c_dir.join("include")) - .include(spine_c_dir.join("src")) - .flag("-std=c++11"); - - // Always avoid C++ runtime (consistent with no-cpprt approach) - cpp_build - .flag("-fno-exceptions") - .flag("-fno-rtti"); - - // Always avoid C++ runtime (consistent with no-cpprt approach) - cpp_build.flag("-nostdlib++"); - - // Tell cc crate linker to not link libc++ - cpp_build.flag_if_supported("-Wl,-undefined,dynamic_lookup"); - cpp_build.cpp_link_stdlib(None); - - if is_wasm { - // For WASM, we may need additional setup, but let's first try without extra flags - // The target is already handled by cc-rs when building for wasm32-unknown-unknown - } - - // Add spine-cpp source files (no-cpprt variant = all sources + no-cpprt.cpp) - let spine_cpp_src = spine_cpp_dir.join("src"); - for entry in std::fs::read_dir(&spine_cpp_src).unwrap() { - let entry = entry.unwrap(); - let path = entry.path(); - if path.extension().map_or(false, |ext| ext == "cpp") { - cpp_build.file(&path); - } - } - - // Add spine-cpp subdirectories - for subdir in &["spine", "spine-c", "utils"] { - let subdir_path = spine_cpp_src.join(subdir); - if subdir_path.exists() { - for entry in std::fs::read_dir(&subdir_path).unwrap() { - let entry = entry.unwrap(); - let path = entry.path(); - if path.extension().map_or(false, |ext| ext == "cpp") { - cpp_build.file(&path); - } - } - } - } - - // Add spine-c generated sources - let spine_c_generated = spine_c_dir.join("src/generated"); - for entry in std::fs::read_dir(&spine_c_generated).unwrap() { - let entry = entry.unwrap(); - let path = entry.path(); - if path.extension().map_or(false, |ext| ext == "cpp") { - cpp_build.file(&path); - } - } - - // Add spine-c extensions - cpp_build.file(spine_c_dir.join("src/extensions.cpp")); - - // Add no-cpprt.cpp for C++ runtime stubs - cpp_build.file(spine_cpp_dir.join("src/no-cpprt.cpp")); - - cpp_build.compile("spine"); - - // Generate bindings with bindgen - let bindings = bindgen::Builder::default() - .header("../../include/spine-c.h") - .clang_arg("-I../../include") - .clang_arg("-I../../../spine-cpp/include") - .clang_arg("-I../../src") - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - .generate() - .expect("Unable to generate bindings"); - - let out_path = std::path::PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); - - // Link libraries - no C++ stdlib since we're using no-cpprt variant - // The no-cpprt.cpp provides minimal runtime stubs - - println!("cargo:rerun-if-changed=../../spine-cpp/src"); - println!("cargo:rerun-if-changed=../../src"); - println!("cargo:rerun-if-changed=../../include/spine-c.h"); -} \ No newline at end of file diff --git a/spine-c/tests/rust-wasm/src/lib.rs b/spine-c/tests/rust-wasm/src/lib.rs deleted file mode 100644 index 03a9a2e64..000000000 --- a/spine-c/tests/rust-wasm/src/lib.rs +++ /dev/null @@ -1,185 +0,0 @@ -use std::ffi::{CStr, CString}; -use std::os::raw::{c_char, c_float, c_int, c_void}; - -// Include the generated bindings -include!(concat!(env!("OUT_DIR"), "/bindings.rs")); - -// Headless texture loader functions with debug prints -extern "C" fn headless_texture_loader(path: *const c_char) -> *mut c_void { - unsafe { - let path_str = if !path.is_null() { - CStr::from_ptr(path).to_string_lossy() - } else { - "NULL".into() - }; - println!("DEBUG: texture_loader called with path: {}", path_str); - - let ptr = std::alloc::alloc(std::alloc::Layout::from_size_align(8, 8).unwrap()); - println!("DEBUG: texture_loader returning: {:?}", ptr); - ptr as *mut c_void - } -} - -extern "C" fn headless_texture_unloader(texture: *mut c_void) -> () { - println!("DEBUG: texture_unloader called with texture: {:?}", texture); - - if !texture.is_null() && texture as usize > 1 { - unsafe { - println!("DEBUG: deallocating texture: {:?}", texture); - std::alloc::dealloc(texture as *mut u8, std::alloc::Layout::from_size_align(8, 8).unwrap()); - println!("DEBUG: texture deallocation completed"); - } - } else { - println!("DEBUG: skipping deallocation (null or invalid pointer)"); - } - println!("DEBUG: texture_unloader returning"); -} - -#[no_mangle] -pub extern "C" fn test_spine_basic() -> c_int { - unsafe { - println!("Starting spine test..."); - spine_bone_set_y_down(false); - println!("Set y_down..."); - - // Load real spineboy atlas data - let atlas_file = std::fs::read_to_string("../../../examples/spineboy/export/spineboy-pma.atlas") - .expect("Failed to read atlas file"); - let atlas_data = CString::new(atlas_file).unwrap(); - let atlas_dir = CString::new("../../../examples/spineboy/export/").unwrap(); - - println!("About to load atlas..."); - let atlas = spine_atlas_load_callback( - atlas_data.as_ptr(), - atlas_dir.as_ptr(), - Some(headless_texture_loader), - Some(headless_texture_unloader), - ); - println!("Atlas loaded: {:?}", atlas); - - if atlas.is_null() { - println!("Atlas is null!"); - return 1; // Failed to load atlas - } - - // Load real spineboy skeleton data (binary format like the C test) - println!("Reading skeleton file..."); - let skeleton_file = std::fs::read("../../../examples/spineboy/export/spineboy-pro.skel") - .expect("Failed to read skeleton file"); - println!("Skeleton file size: {} bytes", skeleton_file.len()); - let skeleton_path = CString::new("../../../examples/spineboy/export/spineboy-pro.skel").unwrap(); - - println!("About to call spine_skeleton_data_load_binary..."); - let result = spine_skeleton_data_load_binary(atlas, skeleton_file.as_ptr(), skeleton_file.len() as i32, skeleton_path.as_ptr()); - println!("spine_skeleton_data_load_binary returned: {:?}", result); - - if result.is_null() { - println!("Result is null!"); - return 2; - } - - println!("About to call spine_skeleton_data_result_get_data..."); - println!("Result pointer: {:?}", result); - println!("Result is null: {}", result.is_null()); - - // Try to read the error first to see if result is valid - println!("Checking if result has error..."); - let error_ptr = spine_skeleton_data_result_get_error(result); - println!("Error check completed. Error ptr: {:?}", error_ptr); - - if !error_ptr.is_null() { - let error_str = CStr::from_ptr(error_ptr); - println!("Found error: {:?}", error_str); - spine_skeleton_data_result_dispose(result); - spine_atlas_dispose(atlas); - return 2; - } - - println!("No error found, getting skeleton data..."); - let skeleton_data = spine_skeleton_data_result_get_data(result); - - if skeleton_data.is_null() { - let error = spine_skeleton_data_result_get_error(result); - if !error.is_null() { - let error_str = CStr::from_ptr(error); - eprintln!("Skeleton data error: {:?}", error_str); - } - spine_skeleton_data_result_dispose(result); - spine_atlas_dispose(atlas); - return 2; // Failed to load skeleton data - } - - println!("Skeleton data is valid: {:?}", skeleton_data); - // Test skeleton creation immediately - println!("Creating skeleton..."); - let skeleton = spine_skeleton_create(skeleton_data); - println!("Skeleton create returned: {:?}", skeleton); - if skeleton.is_null() { - spine_skeleton_data_result_dispose(result); - spine_atlas_dispose(atlas); - return 3; // Failed to create skeleton - } - - // Test basic operations - println!("Calling spine_skeleton_setup_pose..."); - spine_skeleton_setup_pose(skeleton); - println!("Setup pose completed"); - - println!("Calling spine_skeleton_update_world_transform_1..."); - spine_skeleton_update_world_transform_1(skeleton, 1); // SPINE_PHYSICS_UPDATE = 1 - println!("Update world transform completed"); - - println!("Getting skeleton position..."); - let x = spine_skeleton_get_x(skeleton); - println!("Got x: {}", x); - let y = spine_skeleton_get_y(skeleton); - println!("Got y: {}", y); - - // Cleanup - println!("Disposing skeleton..."); - spine_skeleton_dispose(skeleton); - println!("Skeleton disposed"); - - println!("Disposing skeleton data result..."); - spine_skeleton_data_result_dispose(result); - println!("Skeleton data result disposed"); - - // Test atlas disposal to get proper crash backtrace - println!("About to call spine_atlas_dispose - crash expected..."); - spine_atlas_dispose(atlas); - println!("Atlas disposal completed successfully"); - - // Verify we got reasonable values - println!("Verifying values..."); - if x.is_finite() && y.is_finite() { - println!("SUCCESS! Test completed successfully"); - 0 // Success - } else { - println!("FAILED! Invalid values"); - 4 // Invalid values - } - } -} - -// WASM export for web testing -#[cfg(target_arch = "wasm32")] -mod wasm { - use super::*; - use std::os::raw::c_int; - - #[no_mangle] - pub extern "C" fn run_spine_test() -> c_int { - test_spine_basic() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_spine_basic_works() { - let result = test_spine_basic(); - assert_eq!(result, 0, "Spine basic test should succeed"); - } -} \ No newline at end of file diff --git a/spine-c/tests/rust-wasm/test.sh b/spine-c/tests/rust-wasm/test.sh deleted file mode 100755 index ae2c714cd..000000000 --- a/spine-c/tests/rust-wasm/test.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/bash -# Spine-C WASM Test -# -# Tests spine-c + spine-cpp-no-cpprt compilation to WASM via Rust FFI - -set -e - -# Change to test directory -cd "$(dirname "$0")" - -# Source logging utilities -source ../../../formatters/logging/logging.sh - -log_title "Spine-C WASM Test" - -# Check if Rust is installed -if ! command -v cargo > /dev/null 2>&1; then - log_fail "Cargo not found - install Rust toolchain" - exit 1 -fi - -# Check if WASM target is installed -log_action "Checking WASM target" -if RUSTUP_OUTPUT=$(rustup target list --installed 2>&1); then - if echo "$RUSTUP_OUTPUT" | grep -q "wasm32-unknown-unknown"; then - log_ok - else - log_detail "Installing wasm32-unknown-unknown target" - if rustup target add wasm32-unknown-unknown > /dev/null 2>&1; then - log_ok - else - log_fail - log_detail "Failed to install WASM target" - exit 1 - fi - fi -else - log_fail - log_detail "Could not check rustup targets" - exit 1 -fi - -# Build native version first (for comparison) -log_action "Building native version" -if BUILD_OUTPUT=$(cargo build 2>&1); then - log_ok -else - log_fail - log_error_output "$BUILD_OUTPUT" - exit 1 -fi - -# Test native version -log_action "Testing native version" -if TEST_OUTPUT=$(cargo test 2>&1); then - log_ok -else - log_fail - log_error_output "$TEST_OUTPUT" - exit 1 -fi - -# Build WASM version -log_action "Building WASM version" -if WASM_BUILD_OUTPUT=$(cargo build --target wasm32-unknown-unknown 2>&1); then - log_ok -else - log_fail - log_error_output "$WASM_BUILD_OUTPUT" - exit 1 -fi - -# Check WASM output -WASM_FILE="target/wasm32-unknown-unknown/debug/spine_c_wasm_test.wasm" -if [ -f "$WASM_FILE" ]; then - log_action "Analyzing WASM output" - WASM_SIZE=$(du -h "$WASM_FILE" | cut -f1) - log_ok - log_detail "WASM file size: $WASM_SIZE" - - # Check for C++ runtime dependencies (should be minimal) - if command -v wasm-objdump > /dev/null 2>&1; then - log_detail "WASM imports:" - wasm-objdump -x "$WASM_FILE" | grep -A 20 "Import\[" | head -20 || true - fi -else - log_fail "WASM file not found: $WASM_FILE" - exit 1 -fi - -# Test with wasmtime if available -if command -v wasmtime > /dev/null 2>&1; then - log_action "Testing with wasmtime" - # Create a simple test runner - cat > test_runner.wat << 'EOF' -(module - (import "spine" "run_spine_test" (func $run_spine_test (result i32))) - (func (export "_start") - (call $run_spine_test) - (if (i32.ne (i32.const 0)) - (then unreachable)) - ) -) -EOF - - if wasmtime test_runner.wat --invoke _start 2>/dev/null; then - log_ok - else - log_detail "Wasmtime test skipped (expected - needs proper test harness)" - fi - rm -f test_runner.wat -else - log_detail "Wasmtime not available - skipping runtime test" -fi - -log_summary "✓ WASM compilation successful" -log_detail "This proves spine-cpp-no-cpprt can be used from Rust and compiled to WASM" \ No newline at end of file