wasm単体だとできないことが多いので、wasi-libcをインストールしてみた。
まず、githubからwasi-libcをclone。中に入ってmakeするも、「diffが無い」といったエラーが出てきたので、msys2環境にdiffをインストール。
次にmsys2のbashからだとWindowsのPATHが(何故か)見えないので、コンパイラのパスを直接指定してmake
make WASM_CC=/d/Scoop/apps/llvm/current/bin/clang.exe WASM_AR=/d/Scoop/apps/llvm/current/bin/llvm-ar.exe WASM_NM=/d/Scoop/apps/llvm/current/bin/llvm-nm.exe
でビルド、libclang_rt.builtins-wasm32.aが無いと言われたので、 jedisct1/libclang_rt.builtins-wasm32.aから拾ってきてコピー。
cのプログラムでprintfで文字列を出力するように改造
#include <stdint.h>
#include <stdio.h>
__attribute__((visibility("default")))
int add(int32_t a, int32_t b) {
printf("hello wasi\n");
return a + b;
}
int main() {return 0;}
int main()がないとコンパイル時に怒られるので、何もしない関数を追加。
all: wasm.wasm
wasm.wasm: wasm.o
clang --sysroot=D:/build/wasi-libc/sysroot -L D:/build/wasi-libc/sysroot/lib/wasm32-wasi -Wl,--no-entry -Wl,--export-dynamic --target=wasm32-wasi -o wasm.wasm wasm.o
wasm.o: wasm.c
clang --sysroot=D:/build/wasi-libc/sysroot --target=wasm32-wasi -c wasm.c -o wasm.o
makefileも修正。ビルドしたwasi-libcを使うようにした。
さらにrust側も修正。wasmer-wasiをdependenciesに追加した上で
extern crate wasmer;
use wasmer::{Store, Module, Instance, Value};
use wasmer_wasi::WasiState;
fn main() {
// wasmファイル実行準備
let store = Store::default();
let module = Module::from_file(&store, "wasm.wasm").unwrap();
let mut wasi_env = WasiState::new("wasi.wasi").finalize().unwrap();
let import_object = wasi_env.import_object(&module).unwrap();
let instance = Instance::new(&module, &import_object).unwrap();
wasi_env.set_memory(instance.exports.get_memory("memory").unwrap().clone());
let add = instance.exports.get_function("add").unwrap();
// wasmの関数実行
let response = add.call(&[Value::I32(1), Value::I32(2)]).unwrap();
println!("1 + 2 = {}", response[0].to_string().parse::<i32>().unwrap());
}
wasmer-wasiを使ってwasi用のimport_objectを作るように修正。あとファイルの読み込みも修正してmoduleの作り方を変更。
実行結果は
PS wasm_rt> cargo run Compiling wasm_rt v0.1.0 (wasm_rt) Finished dev [unoptimized + debuginfo] target(s) in 5.96s Running `target\debug\wasm_rt.exe` hello wasi 1 + 2 = 3
どうやらwasmのprintfが動いたようだ。
これ、他のライブラリも–target指定してstaticライブラリにしたものをリンクすれば動くのかな。