fortran66のブログ

fortran について書きます。

【メモ帳】LFortran で WebAssembly

Fortran で WebAssembly

昨日 twitter で LFortran 公式が LFortran が吐いた WASM での Web 利用についてつぶやいていたので、再現してみます。

LFortran は、WASM を吐き出すオプションをつけてソースからコンパイルする必要があります。

lfortran.org

元々は以下のページの llvm flang による試みに刺激されたようです。

gws.phd

手順メモ

はじめ M1 Mac でやってみたのですが、assert のエラーをどうしても乗り越えられないので放棄しました。河岸を変えて WSL 上の Ubuntu 22.04 でやって再現できました。

基本的には LFortran 公式の Build from Git on Windows with WSL の項目に従い、conda 環境を準備します。そうしないと意味不明なエラーに襲われ続けます。

docs.lfortran.org

conda create -n lf -c conda-forge llvmdev=11.0.1 bison=3.4 re2c python cmake make toml
conda init bash

conda activate lf
sudo apt update
sudo apt-get install build-essential
sudo apt-get install zlib1g-dev libzstd-dev
sudo apt install clang
git clone https://github.com/lfortran/lfortran.git
cd lfortran

./build0.sh

cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_LLVM=yes -DCMAKE_INSTALL_PREFIX=`pwd`/inst - DWITH_RUNTIME_STACKTRACE=yes -DWITH_TARGET_WASM=yes -DWITH_TARGET_X86=yes -DWITH_TARGET_AARCH64=yes .

make -j 8
make install

ここで cmake の引数に、wasm を吐き出すように、コンパイラのターゲットを与えます。

-DWITH_TARGET_WASM=yes -DWITH_TARGET_X86=yes -DWITH_TARGET_AARCH64=yes

fortran-lang.discourse.group

また、以下の行も足しておきます。これをしないと test を通りません。 

DWITH_RUNTIME_STACKTRACE=yes

cmake のところで zlib が無いとかエラーメッセージが出ましたが、それをググって必要なものをインストールすれば何とかなります。

ctest
./run_tests.py

出力例

~/lfortran/src/bin/lfortran --version
LFortran version: 0.35.0-106-gda0a07acb
Platform: Linux
Default target: x86_64-unknown-linux-gnu


~/lfortran/src/bin/lfortran --print-targets

  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_32 - AArch64 (little endian ILP32)
    aarch64_be - AArch64 (big endian)
    arm64      - ARM64 (little endian)
    arm64_32   - ARM64 (little endian ILP32)
    wasm32     - WebAssembly 32-bit
    wasm64     - WebAssembly 64-bit
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64

emscripten :WASM に必要

以下のページに従ってスルスル行けます

emscripten.org

# Get the emsdk repo
git clone https://github.com/emscripten-core/emsdk.git

# Enter that directory
cd emsdk

# Download and install the latest SDK tools.
./emsdk install latest

# Make the "latest" SDK "active" for the current user. (writes .emscripten file)
./emsdk activate latest

# Activate PATH and other environment variables in the current terminal
source ./emsdk_env.sh

注意:ここで起動時に自動で読み込むようにするにはこうしろ!と画面に出るのですが、それをやると .bash_profile に書き込みをします、しかし副作用で conda のパスがくるってにっちもさっちも行かなくなるので、やらない方が身のためです。その代わり毎回起動後 source ./emsdk_env.sh をすることにします。 

実際の再現

github.com

git clone https://github.com/lfortran/mnist-classifier-blas-wasm.git
cd mnist-classifier-blas-wasm

(ランタイムのオブジェクトファイルの位置は ~/lfortran/src/runtime/lfortran_runtime_wasm_emcc.o です。)

 ~/lfortran/src/bin/lfortran  -c classifier.f90 --generate-object-code --rtlib --target=wasm32-unknown-emscripten
 
emcc --target=wasm32-unknown-emscripten -sSTACK_SIZE=50mb -sINITIAL_MEMORY=256mb -o www/mnist.js classifier.o ~/lfortran/src/runtime/lfortran_runtime_wasm_emcc.o --no-entry -sEXPORTED_FUNCTIONS=_classifier,_malloc,_free

色々メッセージが出ますが無視で。 出力は ./www の中身の一部を置き換える形で出ます。

cd www
python -m http.server 8000

ブラウザから http://localhost:8000 で出るはず。

結果の再現ができたので、いずれ何かやってみたいと思います。