前回とは違って、コンソールでビルドしてみました。WebAssembly System Interface のTurtorial を使います。
https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-tutorial.md
とても重要なコードなので、CとRustそれぞれ引用させていただきました。
demo.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> int main(int argc, char **argv) { ssize_t n, m; char buf[BUFSIZ]; if (argc != 3) { fprintf(stderr, "usage: %s <from> <to>\n", argv[0]); exit(1); } int in = open(argv[1], O_RDONLY); if (in < 0) { fprintf(stderr, "error opening input %s: %s\n", argv[1], strerror(errno)); exit(1); } int out = open(argv[2], O_WRONLY | O_CREAT, 0660); if (out < 0) { fprintf(stderr, "error opening output %s: %s\n", argv[2], strerror(errno)); exit(1); } while ((n = read(in, buf, BUFSIZ)) > 0) { char *ptr = buf; while (n > 0) { m = write(out, ptr, (size_t)n); if (m < 0) { fprintf(stderr, "write error: %s\n", strerror(errno)); exit(1); } n -= m; ptr += m; } } if (n < 0) { fprintf(stderr, "read error: %s\n", strerror(errno)); exit(1); } return EXIT_SUCCESS; } |
main.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
use std::env; use std::fs; use std::io::{Read, Write}; fn process(input_fname: &str, output_fname: &str) -> Result<(), String> { let mut input_file = fs::File::open(input_fname).map_err(|err| format!("error opening input {}: {}", input_fname, err))?; let mut contents = Vec::new(); input_file .read_to_end(&mut contents) .map_err(|err| format!("read error: {}", err))?; let mut output_file = fs::File::create(output_fname) .map_err(|err| format!("error opening output {}: {}", output_fname, err))?; output_file .write_all(&contents) .map_err(|err| format!("write error: {}", err)) } fn main() { let args: Vec<String> = env::args().collect(); let program = args[0].clone(); if args.len() < 3 { eprintln!("usage: {} <from> <to>", program); return; } if let Err(err) = process(&args[1], &args[2]) { eprintln!("{}", err) } } |
Cのビルド
https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-14
よりSDKをダウンロードしてビルド
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-14/wasi-sdk-14.0-linux.tar.gz
tar zxvf wasi-sdk-14.0-linux.tar.gz
./wasi-sdk-14.0/bin/clang –sysroot=./wasi-sdk-14.0/share/wasi-sysroot demo.c -o demo.wasm
file demo.wasm
demo.wasm: WebAssembly (wasm) binary module version 0x1 (MVP)
cppの場合は、clang++ を使用
Rustのビルド
rustup target add wasm32-wasi
cargo build –target wasm32-wasi
target/wasm32-wasi/debug にdemo.wasmが出力される
wasmtimeインストール(sourceコマンドでパス有効化)
curl http://wasmtime.dev/install.sh -sSf | bash
実行結果
$ echo hello > hello.txt
$ wasmtime demo.wasm
usage: demo.wasm [from] [to]
$ wasmtime –dir=. –dir=. demo.wasm hello.txt out.txt
$ cat out.txt
hello
wasmtimeはWASIのランタイムで、wasmファイルを直接実行できます。一見普通のコードとWasmは区別がつかないくらいです。
Cの場合、環境がきちんと通っていないと間違えて通常のバイナリを作ってしまいます。
wasmは一つのバイナリをいろいろなところで使うことができます。下記動画が参考になります。
(しかし古いせいか作ったモジュールが不正となってしまい動作確認がとれませんでした)
“WebAssembly Interface Types: Interoperate with All The Things!”