Emscripten を使用して C と C++ を WebAssembly にコンパイルする

ウェブ機能: WebAssembly

Emscripten を使用して、C と C++ をブラウザ用の高パフォーマンスの WebAssembly(Wasm)モジュールにコンパイルします。

1. 最新の Emscripten コンパイル フラグ

emcc または em++ を使用してコンパイルとリンクを行う場合は、常に最新のモジュラー フラグを使用します。

  • -sEXPORT_ES6: 以前のグローバル オブジェクトではなく、標準の ES6 モジュール構文(import/export)を出力します。これにより、-sMODULARIZE が自動的に設定されます。
  • -sENVIRONMENT=web: Node.js / シェル ランタイム コードを削除して、バンドルサイズを最小限に抑えます。
  • -sSTRICT: 最新の Emscripten のデフォルトを適用し、非推奨のフラグで失敗します。
  • -sALLOW_MEMORY_GROWTH: メモリの割り当て時に WebAssembly 線形メモリヒープを動的に拡張できるようにします。
  • -Oz(または -O3)+ -flto: リリースビルドでペイロード サイズが最小になるように最適化します。

2. メインスレッドのブロックを回避する

WebAssembly への呼び出しにかなりの時間がかかる(数ミリ秒以上)可能性がある場合は、メインのブラウザ スレッドで呼び出すべきではありません。

このようなコードをメインのブラウザ スレッドで実行しないようにするには、いくつかの方法があります。

  1. WebAssembly プログラム全体をウェブワーカーで実行する。SharedArrayBuffer アクセスの設定やプログラム ソースの変更が不要なため、多くの場合、これが最も簡単なソリューションです。

  2. pthreads または Wasm ワーカーを使用します。これにより、多くのワーカー間で作業を共有できますが、SharedArrayBuffer へのアクセスが必要になります。これには、COOP / COEP HTTP ヘッダーの追加が必要になる場合があります。

  3. C/C++ コードをリファクタリングして、長時間実行される呼び出しを回避します。たとえば、requestIdleCallback から呼び出すことができる小さな部分に作業を分割します。

3. ランタイムの警告とエラーに注意する

生成された WebAssembly プログラムを実際にテストし、コンソールに警告やエラーが表示されないことを確認してください。

-sASSERTIONS を有効にしてプログラムをビルドして実行し、発生したランタイム エラーを修正します。

4. 可能な限り Dynamic Links を避ける

Emscripten は、静的ライブラリ(.a)で最適に動作します。共有ライブラリ(.so、.dylib、.dll)は、ブラウザのデプロイではあまり役に立たず、不必要に複雑になる可能性があります。

5. 既存の C / C++ ライブラリの移植

既存の C / C++ ライブラリを標準のビルドシステムと統合する場合:

CMake プロジェクト

CMake コマンドを emcmake と emmake でラップします。

mkdir build && cd build
emcmake cmake .. -DCMAKE_BUILD_TYPE=Release
emmake make

Autoconf / Make プロジェクト

emconfigure を使用して、クロスコンパイル ツールチェーンのターゲットを設定します。

emconfigure ./configure --host=wasm32-unknown-emscripten --disable-shared
emmake make