C und C++ mit Emscripten in WebAssembly kompilieren

Webfunktionen: WebAssembly

Mit Emscripten können Sie C und C++ in leistungsstarke WebAssembly-Module (Wasm) für den Browser kompilieren.

1. Moderne Emscripten-Kompilierungs-Flags

Verwenden Sie beim Kompilieren und Verknüpfen mit emcc oder em++ immer moderne modulare Flags:

  • -sEXPORT_ES6: Gibt die standardmäßige ES6-Modulsyntax (import/export) anstelle von Legacy-globalen Objekten aus. Dadurch wird -sMODULARIZE automatisch festgelegt.
  • -sENVIRONMENT=web: Entfernt Node.js-/Shell-Laufzeitcode, um die Bundle-Größe zu minimieren.
  • -sSTRICT: Erzwingt moderne Emscripten-Standardeinstellungen und schlägt bei verworfenen Flags fehl.
  • -sALLOW_MEMORY_GROWTH: Ermöglicht die dynamische Erweiterung des linearen WebAssembly-Arbeitsspeicher-Heaps bei der Speicherzuweisung.
  • -Oz (oder -O3) + -flto: Optimiert für minimale Nutzlastgröße in Release-Builds.

2. Blockieren des Hauptthreads vermeiden

Wenn ein Aufruf von WebAssembly wahrscheinlich viel Zeit in Anspruch nimmt (d.h. mehr als ein paar Millisekunden), sollte er nicht im Haupt-Browser-Thread aufgerufen werden.

Es gibt mehrere Möglichkeiten, die Ausführung von solchem Code im Hauptthread des Browsers zu vermeiden:

  1. Führen Sie das gesamte WebAssembly-Programm in einem Web Worker aus. Das ist oft die einfachste Lösung, da Sie weder den SharedArrayBuffer-Zugriff einrichten noch die Programmquelle ändern müssen.

  2. Verwenden Sie pthreads oder Wasm-Worker. So kann die Arbeit auf viele Worker aufgeteilt werden. Es ist jedoch ein SharedArrayBuffer-Zugriff erforderlich, für den möglicherweise COOP/COEP-HTTP-Header hinzugefügt werden müssen.

  3. Refaktorieren Sie den C/C++-Code, um lang laufende Aufrufe zu vermeiden. Sie können die Arbeit beispielsweise in kleine Teile aufteilen, die von requestIdleCallback aufgerufen werden können.

3. Achten Sie auf Laufzeitwarnungen und -fehler.

Testen Sie das resultierende WebAssembly-Programm und achten Sie darauf, dass in der Konsole keine Warnungen oder Fehler generiert werden.

Erstellen Sie die Programme mit aktiviertem -sASSERTIONS und führen Sie sie aus. Beheben Sie alle Laufzeitfehler, die auftreten.

4. Vermeiden Sie nach Möglichkeit dynamische Verknüpfungen.

Emscripten funktioniert am besten mit statischen Bibliotheken (.a). Gemeinsam genutzte Bibliotheken (.so, .dylib, .dll) sind bei der Bereitstellung im Browser weniger nützlich und können die Dinge unnötig verkomplizieren.

5. Vorhandene C/C++-Bibliotheken portieren

Wenn Sie vorhandene C/C++-Bibliotheken in Standard-Build-Systeme einbinden, gilt Folgendes:

CMake-Projekte

Fügen Sie die CMake-Befehle zwischen emcmake und emmake ein:

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

Autoconf-/Make-Projekte

Verwenden Sie emconfigure, um Ziele für die Cross-Kompilierungs-Toolchain festzulegen:

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