Project Blackbird ================= Whatever this was before, it's currently really about creating WebAssembly Components in C using the wasi-http interface. See the stuff under: c/wasi-http/0.2.0/ They can be run under NGINX Unit with the wasm-wasi-component language module or under wasmtime (v24 works), e.g. $ wasmtime serve -Scli -Sinherit-env ./component.wasm Getting Started =============== First you'll need some tools. Firstly clang/llvm Fedora ------ # dnf install make clang llvm compiler-rt lld wasi-libc-devel wasi-libc-static Debian ------ # apt install make clang llvm lld You will also need to grab the wasi-sysroot, this is essentially a C library targeting WebAssembly (it is based partly on cloudlibc and musl libc) and is required for building server side WebAssembly modules. It's up to you where you put this. $ wget -O- https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sysroot-24.0.tar.gz | tar -xzf - Note: Debian does provide a wasi-libc package, but the way it's packaged makes it unusable in this instance as --sysroot expects the include and lib directories to both be there (whereas in the Debian package they are in different locations). libclang_rt.builtins-wasm32.a ----------------------------- For either of the above you will also need the libclang wasm32-wasi runtime library, this can be done with # wget -O- https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/libclang_rt.builtins-wasm32-wasi-24.0.tar.gz | tar --strip-components=1 -xvzf - -C $(dirname $(clang -print-runtime-dir)) That will install the following, path may vary slightly /usr/lib/clang/18/lib/wasi/libclang_rt.builtins-wasm32.a **NOTE:** If you get a major clang version update, you may need to repeat that last task. wit-bindgen & wasm-tools ------------------------ Finally you need a couple of rust based tools. You can grab the latest versions for your platform here Again, where you put these is up to you. You will need to tell make where to find these tools, you can either set the WIT_BINDGEN & WASM_TOOLS environment variables in your shell or pass these directly to make, e.g. $ make WIT_BINDGEN=/path/to/wit-bindgen WASM_TOOLS=/path/to/wasm-tools Now you are ready to try building some components! (from the project_blackbird repository root) $ cd c/wasi-http/0.2.0/echo-request $ make # or the above make command depending on how you set the above vars or for Debian you will need to specify the WASI_SYSROOT $ make WASI_SYSROOT=/path/to/wasi-sysroot If it works you should be left with (amongst others) a component.wasm file, you can test that out by using the wasmtime-serve command You can grab wasmtime from https://github.com/bytecodealliance/wasmtime/releases/download/v24.0.0/wasmtime-v24.0.0-x86_64-linux.tar.xz or pick a different version for your platform, don't take the c-api package by mistake. Untar that someplace then you can do $ /path/to/wasmtime serve ./component.wasm Then try $ curl localhost:8080 *** Welcome to WebAssembly with wasi-http / C *** [Request Info] REQUEST_PATH = / METHOD = GET QUERY = [Request Headers] accept = */* user-agent = curl/8.6.0 For the other components using the reactor adaptor you will want to use $ /path/to/wasmtime serve -Scli ./component.wasm For env-var you will want $ /path/to/wasmtime serve -Scli -Sinherit-env ./component.wasm You can of course use that last command for them all. ================================================================================ Make Fermyon Spin WebAssembly Modules run on NGINX Unit. The repository will contain some exploratory tools. Quickstart ========== Clone the spin repository $ git clone https://github.com/fermyon/spin.git Build the wasm module. $ cd spin/examples/wasi-http-rust $ cargo build --target wasm32-wasi Grab the Wasmtime C API $ wget -O- https://github.com/bytecodealliance/wasmtime/releases/download/v13.0.0/wasmtime-v13.0.0-x86_64-linux-c-api.tar.xz | tar -xvf - Clone this repository $ git clone git://git.digital-domain.net/project_blackbird.git Build it $ cd project_blackbird/c/wasmtime-wasi-http $ make WASMTIME_C_API=/path/to/wasmtime-c-api WASM_MODULE=/path/to/spin/examples/wasi-http-rust/target/wasm32-wasi/debug/wasi_http_rust.wasm Run it $ ./wasmtime-wasi-http Initializing... Loading binary... Compiling module... Setting function imports... [poll2::poll-oneoff] [streams2::read] [streams2::blocking-read] [streams2::subscribe-to-input-stream] [streams2::write] [streams2::blocking-write] [streams2::subscribe-to-output-stream] [default-outgoing-HTTP2::handle] [types2::new-fields] [types2::fields-entries] [types2::finish-incoming-stream] [types2::finish-outgoing-stream] [types2::incoming-request-method] [types2::incoming-request-path-with-query] [types2::incoming-request-headers] [types2::incoming-request-consume] [types2::new-outgoing-request] [types2::outgoing-request-write] [types2::set-response-outparam] [types2::incoming-response-status] [types2::incoming-response-headers] [types2::incoming-response-consume] [types2::new-outgoing-response] [types2::outgoing-response-write] [types2::future-incoming-response-get] [types2::listen-to-future-incoming-response] Initialising WASI... Instantiating module... Getting function exports... [HTTP#handle] [cabi_realloc] Shutting down... Done. Component Model =============== You can play with the component model under rust/hello_world This requires some new tools - https://github.com/bytecodealliance/wit-bindgen - https://github.com/bytecodealliance/wasm-tools You can use the pre-built packages, once downloaded and untar'd, edit rust/hello_world/component/Makefile and adjust the paths for the above tools. To build the component with make you may need to specify where the WASI sysroot is $ make WASI_SYSROOT=/path/to/wasi-sysroot You can then build the Rust runtime under rust/hello_world with $ cargo build after a while (sheesh) it should finish... then you can run it with $ target/debug/hello_world it won't actually print anything, but also shouldn't give an error.