diff --git a/examples/wasm-emscripten/.cargo/config.toml b/examples/wasm-emscripten/.cargo/config.toml index 7efe96ab..d8ac4727 100644 --- a/examples/wasm-emscripten/.cargo/config.toml +++ b/examples/wasm-emscripten/.cargo/config.toml @@ -9,4 +9,8 @@ target = "wasm32-unknown-emscripten" rustflags = [ "-Clink-args=-fno-rtti -pthread -msimd128 -msse4.2 -sEXPORT_ALL -sSTACK_SIZE=5MB -sUSE_PTHREADS -sDEFAULT_PTHREAD_STACK_SIZE=2MB -sPTHREAD_POOL_SIZE=20 -sINITIAL_MEMORY=1GB -sEXPORT_ES6 --no-entry", "-Ctarget-feature=+atomics,+bulk-memory,+mutable-globals" -] \ No newline at end of file +] + +# Debug build might benefit from further flags, but one cannot yet set debug-only rustflags. +# See: https://github.com/rust-lang/cargo/issues/10271 +# -fexceptions, -gsource-map, -sASSERTIONS, -sNO_DISABLE_EXCEPTION_CATCHING \ No newline at end of file diff --git a/examples/wasm-emscripten/Cargo.toml b/examples/wasm-emscripten/Cargo.toml index a46aa773..afa9d2e3 100644 --- a/examples/wasm-emscripten/Cargo.toml +++ b/examples/wasm-emscripten/Cargo.toml @@ -11,6 +11,6 @@ rust-embed = { version = "8", features = ["debug-embed"] } # Embed in debug to d image = "0.25" [build-dependencies] -data_downloader = { version = "0.2", features = ["zip"] } -hex-literal = "0.4" -glob = "0.3" \ No newline at end of file +glob = "0.3" +reqwest = { version = "0.12", features = ["blocking"] } +zip = "2" \ No newline at end of file diff --git a/examples/wasm-emscripten/README.md b/examples/wasm-emscripten/README.md index 94bbe4f1..d16d9096 100644 --- a/examples/wasm-emscripten/README.md +++ b/examples/wasm-emscripten/README.md @@ -13,7 +13,7 @@ Environment tested on Ubuntu 24.04 and macOS 14.7.1. ## Build example 1. Set local Emscripten SDK in current session via `source ./emsdk/emsdk_env.sh`. -1. Build the example via `cargo build --release`. +1. Build the example via `cargo build` for a debug build or `cargo build --release` for a release build. ## Serve example -1. Serve the example via `python3 serve.py`. Pre-installed Python 3 should be sufficient. \ No newline at end of file +1. Serve a debug build via `python3 serve.py` or a release build via `python3 serve.py --release`. Pre-installed Python 3 should be sufficient. \ No newline at end of file diff --git a/examples/wasm-emscripten/build.rs b/examples/wasm-emscripten/build.rs index 3918f6b0..886a8b25 100644 --- a/examples/wasm-emscripten/build.rs +++ b/examples/wasm-emscripten/build.rs @@ -13,50 +13,60 @@ fn copy_dir_all(src: impl AsRef, dst: impl AsRef "debug", + false => "release" + }; + // Download precompiled libonnxruntime.a. { - use std::{fs::File, io::Write}; + // Request archive. + let mut request = get("https://github.com/alfatraining/onnxruntime-wasm-builds/releases/download/v1.20.1/libonnxruntime-v1.20.1-wasm.zip") + .expect("Cannot request precompiled onnxruntime."); + let mut buf = Vec::::new(); + request.read_to_end(&mut buf).expect("Cannot read precompiled onnxruntime."); - use data_downloader::{DownloadRequest, InZipDownloadRequest, get}; + // Prepare extraction. + let reader = Cursor::new(buf); + let mut zip = ZipArchive::new(reader).expect("Cannot incept unzipper."); - let request = InZipDownloadRequest { - parent: &DownloadRequest { - url: "https://github.com/alfatraining/onnxruntime-wasm-builds/releases/download/v1.20.1/libonnxruntime-v1.20.1-wasm.zip", - sha256_hash: &hex_literal::hex!("bf22b0bf1336babf116839fa58a257aa91112e9bb2dae7fcd4c4a4dee11b70af") - }, - path: "Release/libonnxruntime.a", - sha256_hash: &hex_literal::hex!("abcf64d106168458d08905f97114f0289ebad0912ee96b92e8130670297b5c22") - }; - let bytes = get(&request).expect("Cannot request libonnxruntime.a."); - let mut file = File::create("libonnxruntime.a").expect("Cannot create libonnxruntime.a."); - file.write_all(&bytes).expect("Cannot store libonnxruntime.a."); + // Extract precompiled library. + { + let mut buf = Vec::::new(); + let mut mode_title_case = mode.to_string(); + mode_title_case = format!("{}{mode_title_case}", mode_title_case.remove(0).to_uppercase()); + zip.by_name(format!("{mode_title_case}/libonnxruntime.a").as_str()) + .expect("Cannot find precompiled onnxruntime.") + .read_to_end(&mut buf) + .expect("Cannot read precompiled onnxruntime."); + File::create("./libonnxruntime.a") + .expect("Cannot create precompiled onnxruntime.") + .write_all(&buf) + .expect("Cannot store precompiled onnxruntime."); + } } // Download model. { - use std::{ - fs::{File, create_dir_all}, - io::Write - }; - - use data_downloader::{DownloadRequest, get}; - - let request = DownloadRequest { - url: "https://parcel.pyke.io/v2/cdn/assetdelivery/ortrsv2/ex_models/yolov8m.onnx", - sha256_hash: &hex_literal::hex!("e91bd39ce15420f9623d5e3d46580f7ce4dfc85d061e4ee2e7b78ccd3e5b9453") - }; - let bytes = get(&request).expect("Cannot request model."); + let mut request = get("https://parcel.pyke.io/v2/cdn/assetdelivery/ortrsv2/ex_models/yolov8m.onnx").expect("Cannot request model."); + let mut buf = Vec::::new(); + request.read_to_end(&mut buf).expect("Cannot read model."); create_dir_all("models").expect("Cannot create models directory."); let mut file = File::create("models/yolov8m.onnx").expect("Cannot create model file."); - file.write_all(&bytes).expect("Cannot store model file."); + file.write_all(&buf).expect("Cannot store model."); } // Copy index.html and pictures to target directory. { - let mode = match cfg!(debug_assertions) { - true => "debug", - false => "release" - }; println!("cargo:rerun-if-changed=index.html"); std::fs::copy("index.html", format!("../../target/wasm32-unknown-emscripten/{mode}/index.html")).expect("Cannot copy index.html."); diff --git a/examples/wasm-emscripten/serve.py b/examples/wasm-emscripten/serve.py index 5742faa6..776ecc51 100644 --- a/examples/wasm-emscripten/serve.py +++ b/examples/wasm-emscripten/serve.py @@ -1,5 +1,15 @@ from http.server import HTTPServer, SimpleHTTPRequestHandler from os import chdir, path +from argparse import ArgumentParser + +parser = ArgumentParser() +parser.add_argument("-d", "--debug", action="store_true", help="serve debug build") +parser.add_argument("-r", "--release", action="store_true", help="serve release build") +args = parser.parse_args() +if args.release: + mode = "release" +else: + mode = "debug" # SharedArrayBuffer required for threaded execution need specific CORS headers. # See: https://rustwasm.github.io/wasm-bindgen/examples/raytrace.html#browser-requirements @@ -11,8 +21,8 @@ def end_headers (self): self.send_header("Cross-Origin-Embedder-Policy", "require-corp") SimpleHTTPRequestHandler.end_headers(self) -# Serve index.html from release build. -chdir(path.join(path.dirname(__file__), "../../target/wasm32-unknown-emscripten/release")) +# Serve index.html. +chdir(path.join(path.dirname(__file__), f"../../target/wasm32-unknown-emscripten/{mode}")) httpd = HTTPServer(("localhost", 5555), CORSRequestHandler) -print("Serving site at: http://localhost:5555") +print(f"Serving {mode} build at: http://localhost:5555") httpd.serve_forever() \ No newline at end of file