Fortran で WebAssembly
昨日 twitter で LFortran 公式が LFortran が吐いた WASM での Web 利用についてつぶやいていたので、再現してみます。
LFortran は、WASM を吐き出すオプションをつけてソースからコンパイルする必要があります。
How to use LFortran to compile Fortran codes to WebAssembly via LLVM and host on static web pages.https://t.co/wQ3exnHBd2
— LFortran (@lfortranorg) 2024年5月2日
元々は以下のページの llvm flang による試みに刺激されたようです。
手順メモ
はじめ M1 Mac でやってみたのですが、assert のエラーをどうしても乗り越えられないので放棄しました。河岸を変えて WSL 上の Ubuntu 22.04 でやって再現できました。
基本的には LFortran 公式の Build from Git on Windows with WSL の項目に従い、conda 環境を準備します。そうしないと意味不明なエラーに襲われ続けます。
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
また、以下の行も足しておきます。これをしないと 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 に必要
以下のページに従ってスルスル行けます
# 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 をすることにします。
実際の再現
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 で出るはず。
結果の再現ができたので、いずれ何かやってみたいと思います。