コンパイルするには
WebAssemblyが含まれているのは Qt5.13 から
動画 WebAssemblyについて - YouTube.mkv より
Download and install — Emscripten 3.1.26-git (dev) documentation
~/opt/ に解凍したのでインストール先は ~/opt/emsdk-main/ になり、そこで作業する。
~/opt/emsdk-main$ ./emsdk install latest Resolving SDK alias 'latest' to '3.1.27' Resolving SDK version '3.1.27' to 'sdk-releases-upstream-48ce0b44015d0182fc8c27aa9fbc0a4474b55982- 64bit' Installing SDK 'sdk-releases-upstream-48ce0b44015d0182fc8c27aa9fbc0a4474b55982-64bit'.. Installing tool 'node-14.18.2-64bit'.. Downloading: ***/opt/emsdk-main/zips/node-v14.18.2-linux-x64.tar.xz from https://storage. googleapis.com/webassembly/emscripten-releases-builds/deps/node-v14.18.2-linux-x64.tar.xz, 2184841 6 Bytes Unpacking '***/opt/emsdk-main/zips/node-v14.18.2-linux-x64.tar.xz' to '***/opt/e msdk-main/node/14.18.2_64bit' Done installing tool 'node-14.18.2-64bit'. Installing tool 'releases-upstream-48ce0b44015d0182fc8c27aa9fbc0a4474b55982-64bit'.. Downloading: ***/opt/emsdk-main/zips/48ce0b44015d0182fc8c27aa9fbc0a4474b55982-wasm-binari es.tbz2 from https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/48ce0b440 15d0182fc8c27aa9fbc0a4474b55982/wasm-binaries.tbz2, 371163051 Bytes Unpacking '***/opt/emsdk-main/zips/48ce0b44015d0182fc8c27aa9fbc0a4474b55982-wasm-binaries .tbz2' to '***/opt/emsdk-main/upstream' Done installing tool 'releases-upstream-48ce0b44015d0182fc8c27aa9fbc0a4474b55982-64bit'. Done installing SDK 'sdk-releases-upstream-48ce0b44015d0182fc8c27aa9fbc0a4474b55982-64bit'.
~/opt/emsdk-main$ ./emsdk activate latest Resolving SDK alias 'latest' to '3.1.27' Resolving SDK version '3.1.27' to 'sdk-releases-upstream-48ce0b44015d0182fc8c27aa9fbc0a4474b55982-64bit' Setting the following tools as active: node-14.18.2-64bit releases-upstream-48ce0b44015d0182fc8c27aa9fbc0a4474b55982-64bit Next steps: - To conveniently access emsdk tools from the command line, consider adding the following directories to your PATH: ***/opt/emsdk-main ***/opt/emsdk-main/node/14.18.2_64bit/bin ***/opt/emsdk-main/upstream/emscripten - This can be done for the current shell by running: source "***/opt/emsdk-main/emsdk_env.sh" - Configure emsdk in your shell startup scripts by running: echo 'source "***/opt/emsdk-main/emsdk_env.sh"' >> $HOME/.bash_profile
上記の終わりに有るように shell 起動スクリプトへ追記させる。
~/opt/emsdk-main$ source "***/opt/emsdk-main/emsdk_env.sh"' >> $HOME/.bash_profile
因みに emsdk_env.sh を実行しただけの場合の表示は次の通り。
~/opt/emsdk-main$ source "./emsdk_env.sh" Setting up EMSDK environment (suppress these messages with EMSDK_QUIET=1) Adding directories to PATH: PATH += ***/opt/emsdk-main PATH += ***/opt/emsdk-main/upstream/emscripten PATH += ***/opt/emsdk-main/node/14.18.2_64bit/bin Setting environment variables: PATH = ***/opt/emsdk-main:***/opt/emsdk-main/upstream/emscripten:***/opt/emsdk-main/node/14.18.2_64bit/bin:***/opt/flutter/bin/:***/.config/nvm/versions/node/v14.17.1/bin:***/usr/bin:***/.tfenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin EMSDK = ***/opt/emsdk-main EMSDK_NODE = ***/opt/emsdk-main/node/14.18.2_64bit/bin/node
働くかどうか確認には $ bash --login とすれば、上記と同じ内容が表示されるはず。
因みに某の環境 PATH は次のようになったので node は emsdk の v14.18.2 が使われる(nvm は flutter で入った物か…)。
$ printenv PATH|awk 'BEGIN{RS=":"}{print}' /home/usskim/opt/emsdk-main /home/usskim/opt/emsdk-main/upstream/emscripten /home/usskim/opt/emsdk-main/node/14.18.2_64bit/bin /home/usskim/opt/flutter/bin/ /home/usskim/.config/nvm/versions/node/v14.17.1/bin /home/usskim/usr/bin /home/usskim/.tfenv/bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /usr/games /usr/local/games /snap/bin
~/opt/emsdk-main$ emsdk list The *recommended* precompiled SDK download is 3.1.27 (48ce0b44015d0182fc8c27aa9fbc0a4474b55982). To install/activate it, use one of: latest [default (llvm) backend] latest-fastcomp [legacy (fastcomp) backend] Those are equivalent to installing/activating the following: 3.1.27 INSTALLED 3.1.27-fastcomp All recent (non-legacy) installable versions are: 3.1.27 INSTALLED 3.1.26 3.1.25 3.1.24 3.1.23 3.1.22 3.1.21 3.1.20 3.1.19 3.1.18 3.1.17 3.1.16 3.1.15 3.1.14 3.1.13 3.1.12 3.1.11 3.1.10 3.1.9 3.1.8 3.1.7 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.1.27-asserts 3.1.26-asserts 3.1.25-asserts 3.1.24-asserts 3.1.23-asserts 3.1.22-asserts 3.1.21-asserts 3.1.20-asserts 3.1.19-asserts 3.1.18-asserts 3.1.17-asserts 3.1.16-asserts 3.1.15-asserts 3.1.14-asserts 3.1.13-asserts 3.1.12-asserts 3.1.11-asserts 3.1.10-asserts 3.1.9-asserts 3.1.8-asserts 3.1.7-asserts 3.1.6-asserts 3.1.5-asserts 3.1.4-asserts 3.1.3-asserts 3.1.2-asserts 3.1.1-asserts 3.1.0-asserts 3.0.1 3.0.0 3.0.1-asserts 3.0.0-asserts 2.0.34 2.0.33 2.0.32 2.0.31 2.0.30 2.0.29 2.0.28 2.0.27 2.0.26 2.0.25 2.0.24 2.0.23 2.0.22 2.0.21 2.0.20 2.0.19 2.0.18 2.0.17 2.0.16 2.0.15 2.0.14 2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 2.0.8 2.0.7 2.0.6 2.0.5 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 2.0.31-asserts 2.0.30-asserts 2.0.29-lto 2.0.28-lto 2.0.27-lto 2.0.26-lto 2.0.23-lto 2.0.20-lto 2.0.19-lto 1.40.1 1.40.0 1.39.20 1.39.19 1.39.18 1.39.17 1.39.16 1.39.15 1.39.14 1.39.13 1.39.12 1.39.11 1.39.10 1.39.9 1.39.8 1.39.7 1.39.6 1.39.5 1.39.4 1.39.3 1.39.2 1.39.1 1.39.0 1.38.48 1.38.47 1.38.46 1.38.45 1.38.44 1.38.43 1.38.42 1.38.41 1.38.40 1.38.39 1.38.38 1.38.37 1.38.36 1.38.35 1.38.34 1.38.33 The additional following precompiled SDKs are also available for download: * sdk-releases-upstream-48ce0b44015d0182fc8c27aa9fbc0a4474b55982-64bit INSTALLED sdk-releases-upstream-630810e5a312f57d17efbe384ed7e4299f796bc1-64bit sdk-releases-fastcomp-edf24e7233e0def312a08cc8dcec63a461155da1-64bit sdk-releases-fastcomp-536568644fd67d53778f6111fdd5f64ad3f4c539-64bit sdk-fastcomp-1.38.30-64bit sdk-fastcomp-1.38.31-64bit The following SDKs can be compiled from source: sdk-upstream-main-64bit sdk-upstream-main-32bit sdk-fastcomp-tag-1.38.30-64bit sdk-fastcomp-tag-1.38.31-64bit The following precompiled tool packages are available for download: (*) releases-upstream-48ce0b44015d0182fc8c27aa9fbc0a4474b55982-64bit INSTALLED releases-upstream-630810e5a312f57d17efbe384ed7e4299f796bc1-64bit releases-fastcomp-edf24e7233e0def312a08cc8dcec63a461155da1-64bit releases-fastcomp-536568644fd67d53778f6111fdd5f64ad3f4c539-64bit fastcomp-clang-e1.38.30-64bit fastcomp-clang-e1.38.31-64bit (*) node-14.18.2-64bit INSTALLED node-14.15.5-64bit emscripten-1.38.30 emscripten-1.38.31 The following tools can be compiled from source: llvm-git-main-32bit llvm-git-main-64bit clang-tag-e1.38.30-32bit clang-tag-e1.38.31-32bit fastcomp-clang-tag-e1.38.30-64bit fastcomp-clang-tag-e1.38.31-64bit fastcomp-clang-master-32bit fastcomp-clang-master-64bit emscripten-tag-1.38.30-32bit emscripten-tag-1.38.31-32bit emscripten-tag-1.38.30-64bit emscripten-tag-1.38.31-64bit binaryen-tag-1.38.30-32bit binaryen-tag-1.38.31-32bit binaryen-tag-1.38.30-64bit binaryen-tag-1.38.31-64bit emscripten-main-32bit emscripten-main-64bit binaryen-main-32bit binaryen-main-64bit ninja-git-release-64bit ccache-git-emscripten-64bit Items marked with * are activated for the current user. Items marked with (*) are selected for use, but your current shell environment is not configured to use them. Type "source ./emsdk_env.sh" to set up your current shell to use them. To access the historical archived versions, type 'emsdk list --old' Run "./emsdk update" to pull in the latest list.
Emscripten は固有の識別子 __EMSCRIPTEN__
を持つようだ。従って
#ifdef __EMSCRIPTEN__ #include <emscripten.h> #endif
書籍中のサンプルコード: oreilly-japan/WebAssembly: 『ハンズオンWebAssembly』のコードリポジトリ
createWasm() instantiateAsync() fetch(...) WebAssembly.instantiateStreaming()
なお、MDN にはカスタム HTML テンプレートの使い方も述べてある。
--shell-file に続けて指定するもよう。テンプレートの中身は高度で解らない。
emcc calculate_primes.c -O3 -o calculate_primes.html --shell-file shell_minimal.html
3.5章では -o ***.html ではなく ***.js を指定する。 すると .wasm と .js のみ生成される(.html は生成されない)。 .js は同じ物が生成されるが、例ではファイル名を変えてあるので、.wasm の名前の部分だけが異なるようだ。
diff -y で見比べると判る。
1050 var wasmBinaryFile; var wasmBinaryFile; 1051 wasmBinaryFile = 'html_template.wasm'; | wasmBinaryFile = 'js_plumbing.wasm'; 1052 if (!isDataURI(wasmBinaryFile)) { if (!isDataURI(wasmBinaryFile)) { 1053 wasmBinaryFile = locateFile(wasmBinaryFile); wasmBinaryFile = locateFile(wasmBinaryFile); 1054 } }
この場合の .html は scriptタグに .js を指定するだけで良い。生成された .js が WebAssembly モジュールのロードとインスタンス化をやってくれるらしい。さらに main関数を書いているので Startセクションに登録されるそうな。
<body> HTML page I created for my WebAssembly module. <script src="js_plumbing.js"></script> </body>
お待ちかね、JavaScript から関数を呼び出す例。
ソースファイル side_module.c は本当にこれだけ↓。
int Increment(int value) { return (value + 1); }
EMSCRIPTEN_KEEPALIVE
を関数定義に含める場合には必要でない。emcc side_module.c -O1 --no-entry -s "EXPORTED_FUNCTIONS=['_Increment']" -o side_module.wasm
グルーコードは無いので、自分でダウンロードとインスタンス化を書かねばならない。
最小限のコードらしく、呼び出し部(と結果)は次の通り。
3.6章の方法と違っている。
Emscripten の仕組みを使った方法なようだ。
まず、この例では main関数を含んではいるが、呼び出すのは別の関数となっている。
従って --no-entry は指定しない。
その場合の Emscripten は既定で main()を呼び出し、他のデッドコードは削除するそうな。
それでは困るので EMSCRIPTEN_KEEPALIVE
修飾子(キーワード?)を加えるそうな。(識別子 __EMSCRIPTEN__
で見分けるのが作法か…)
#ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif void myFunction(int argc, char ** argv) { printf("MyFunction Called\n"); }
コンパイルは次の通り。
-s NO_EXIT_RUNTIME=1
....... main()関数が終了したときにランタイムがシャットダウンされないように。-s "EXPORTED_RUNTIME_METHODS=['ccall']"
... ccall を呼べるように。emcc -o hello3.html hello3.c -O3 --shell-file html_template/shell_minimal.html -s NO_EXIT_RUNTIME=1 -s "EXPORTED_RUNTIME_METHODS=['ccall']"
Module.ccall() を使うらしい。これが fetch やらインスタンス化をやってくれる、と推測。
document .getElementById("mybutton") .addEventListener("click", () => { alert("check console"); const result = Module.ccall( "myFunction", // name of C function null, // return type null, // argument types null, // arguments ); });
この辺の説明は Emscripten に書かれているもよう。
ccall/cwrap を使用して JavaScript からコンパイル済みの C 関数を呼び出す
検証ロジックをブラウザとサーバとで同じコードを使う例。
理に適っており素晴らしい。が、呼び出し周りは少々手間が入る。
.cpp のコードでは(必要なら)エラーメッセージを引数のポインタに strcpy で書き込んで返す。その為、領域を malloc/free しないといけない模様。
ならばポインタのポインタ、或いはポインタの参照を渡せば良さそうだが、その構文が JavaScript に無いのだろう…
何れにしても JavaScript の文字列として扱うには UTF8ToString() で変換しないといけないようだ。
此方の方法は関数を直接呼び出せる。しかし、js の文字列を C文字列に理解させるにはメモリコピー、エンコードの必要が生じ、ややこしくなる。
但し、パラメータの受け渡しが無い場合は、この方法も悪く無さそうだ(混在するのはどうかと思うが…)。
インストール関係の補足
これは Python に追加されているか否かを調べるもの。
$ grep 'wasm' /etc/mime.types application/wasm wasm
$ node --version v14.17.1 ... OK!
なお、Emscripten のインストールと共に node-14.18.2-64bit がインストールされ、そちらの Path が優先される点に注意。
キャンバスに描く例題が有る!