kubo39's blog

ただの雑記です。

D言語もくもく会第17回

(追記: なんやかんやでWASI Tutorialまでできるようになった: https://github.com/kubo39/ldc-wasi-tutorial )

はじめて記事書くな、17です(威圧)。

これにだいたい参加しています。

雑にWASIをwasmtimeで動かせないかな、と試すやつをやりました。

まずWASI対応してるっぽいLDCのビルドからやる。skoppe氏がいろいろやっているはずなのでそこから持ってくる。

$ git submodule add -b wasm https://github.com/skoppe/ldc
$ cd ldc
$ git rev-parse HEAD
828926064c52eba905d9bbbf9d4d57f64a2cd267
$ git submodule init
$ git submodule update --recursive
$ cd ..
$ mkdir build-ldc && cd build-ldc
$ cmake -G Ninja ../ldc \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_INSTALL_PREFIX=$PWD/../install-ldc
$ ninja -j$(nproc)

動かすにはCのランタイムとか必要なので、wasi-sdkをダウンロードする。ここではバージョン10をダウンロードしている。

$ wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-10/wasi-sdk-10.0-linux.tar.gz

WASIでコンパイル、やってみた!(プリチャン風)

import core.stdc.stdio;

extern(C) int main()
{
    printf("Hello, WASI!\n");
    return 0;
}

コンパイルオプションは勘ですがたぶんこんな感じになるはず。

$ ./build-ldc/bin/ldc2 -mtriple=wasm32-unknown-wasi -betterC --gcc=./wasi-sdk-10.0/bin/clang --linker=./wasi-sdk-10.0/bin/wasm-ld main.d
emit _start
/home/kubo39/dev/dlang/ldc-wasi-tutorial/ldc/runtime/druntime/src/core/internal/entrypoint.d(32): Error: only one `main` function allowed

はいエントリポイントまわりがいい感じになっていないぽいですね。

しゃあないのでパッチ書きます。

$ git diff
diff --git a/src/core/internal/entrypoint.d b/src/core/internal/entrypoint.d
index eb00b156..be3b204c 100644
--- a/src/core/internal/entrypoint.d
+++ b/src/core/internal/entrypoint.d
@@ -45,7 +45,8 @@ template _d_cmain()
                 return main(argc, argv);
             }
         }
-        version (WebAssembly)
+        version (WASI) {}
+        else version (WebAssembly)
           {
             pragma(msg, "emit _start");
             import ldc.attributes;

で、まあこのままだといろいろシンボル定義違うとか_startないよとかprintfないよとか怒られるのでコードも修正します。

import core.stdc.stdio;

extern(C):

void __prepare_for_exit() {}
void __wasi_proc_exit(int i) {}

pragma(mangle, "__original_main")
extern(C) int main()
{
    printf("Hello, WASI!\n");
    return 0;
}

動くとこまでいきました。やったぜ。

$ ./build-ldc/bin/ldc2 -mtriple=wasm32-unknown-wasi -betterC -L./wasi-sdk-10.0/share/wasi-sysroot/lib/wasm32-wasi/crt1.o -L./wasi-sdk-10.0/share/wasi-sysroot/lib/wasm32-wasi/libc.a --linker=./wasi-sdk-10.0/bin/wasm-ld main.d
$ wasmtime main.wasm
Hello, WASI!