C en C++ compileren naar WebAssembly met Emscripten

Webfuncties: WebAssembly

Gebruik Emscripten om C en C++ te compileren naar krachtige WebAssembly-modules (Wasm) voor de browser.

1. Moderne Emscripten-compilatiemarkeringen

Als je compileert en koppelt met emcc of em++, gebruik je altijd moderne modulaire flags:

  • -sEXPORT_ES6: Zendt de standaard ES6-modulesyntaxis (import/export) uit in plaats van verouderde algemene objecten. Hierdoor wordt -sMODULARIZE automatisch ingesteld.
  • -sENVIRONMENT=web: Verwijdert Node.js/shell-runtimecode om de bundelgrootte te minimaliseren.
  • -sSTRICT: Dwingt moderne Emscripten-standaardinstellingen af en mislukt bij beëindigde markeringen.
  • -sALLOW_MEMORY_GROWTH: Hiermee kan de lineaire geheugenheap van WebAssembly dynamisch worden uitgebreid bij het toewijzen van geheugen.
  • -Oz (of -O3) + -flto: Optimaliseert voor minimale payloadgrootte in release-builds.

2. Voorkom dat de primaire thread wordt geblokkeerd

Als een aanroep naar WebAssembly waarschijnlijk veel tijd in beslag neemt (dat wil zeggen meer dan een paar milliseconden), mag deze niet worden aangeroepen in de hoofdthread van de browser.

Er zijn verschillende manieren om te voorkomen dat dergelijke code wordt uitgevoerd in de primaire browserthread:

  1. Voer het hele WebAssembly-programma uit in een Web Worker. Dit is vaak de eenvoudigste oplossing, omdat je geen toegang tot SharedArrayBuffer hoeft in te stellen of de programmabron hoeft te wijzigen.

  2. Gebruik pthreads of Wasm Workers. Hierdoor kan het werk worden gedeeld met veel werkers, maar is toegang tot SharedArrayBuffer vereist. Hiervoor moeten COOP/COEP HTTP-headers worden toegevoegd.

  3. Refactoreer de C/C++-code om langdurige aanroepen te voorkomen. Bijvoorbeeld door het werk op te delen in kleine stukjes die kunnen worden aangeroepen vanuit requestIdleCallback.

3. Let op runtime-waarschuwingen en -fouten

Test het resulterende WebAssembly-programma en zorg dat er geen waarschuwingen of fouten worden gegenereerd in de console.

Bouw en voer de programma's uit met -sASSERTIONS aangezet en los eventuele runtimefouten op die worden geproduceerd.

4. Vermijd dynamische koppeling indien mogelijk

Emscripten werkt het best met statische bibliotheken (.a). Gedeelde bibliotheken (.so, .dylib, .dll) zijn minder nuttig bij browserimplementatie en kunnen de zaken onnodig ingewikkeld maken.

5. Bestaande C/C++-bibliotheken overzetten

Als je bestaande C/C++-bibliotheken integreert met standaard buildsystemen, doe je het volgende:

CMake-projecten

Zet CMake-opdrachten tussen emcmake en emmake:

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

Autoconf-/Make-projecten

Gebruik emconfigure om doelen voor crosscompilatie-toolchains in te stellen:

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