Compilazione di C e C++ in WebAssembly con Emscripten

Funzionalità web: WebAssembly

Utilizza Emscripten per compilare C e C++ in moduli WebAssembly (Wasm) ad alte prestazioni per il browser.

1. Flag di compilazione Emscripten moderni

Quando compili e colleghi con emcc o em++, utilizza sempre i flag modulari moderni:

  • -sEXPORT_ES6: genera la sintassi del modulo ES6 standard (import/export) anziché gli oggetti globali legacy. In questo modo viene impostato automaticamente -sMODULARIZE.
  • -sENVIRONMENT=web: rimuove il codice di runtime Node.js/shell per ridurre al minimo le dimensioni del bundle.
  • -sSTRICT: applica i valori predefiniti di Emscripten moderni e non va a buon fine con i flag deprecati.
  • -sALLOW_MEMORY_GROWTH: consente all'heap di memoria lineare di WebAssembly di espandersi dinamicamente durante l'allocazione della memoria.
  • -Oz (o -O3) + -flto: ottimizza per ridurre al minimo le dimensioni del payload nelle build di release.

2. Evita di bloccare il thread principale

Se è probabile che una chiamata a WebAssembly richieda molto tempo (ovvero più di qualche millisecondo), non deve essere chiamata nel thread principale del browser.

Per evitare di eseguire questo codice sul thread principale del browser, esistono diversi approcci possibili:

  1. Esegui l'intero programma WebAssembly in un web worker. Spesso questa è la soluzione più semplice, in quanto non richiede la configurazione dell'accesso a SharedArrayBuffer o la modifica del codice sorgente del programma.

  2. Utilizza pthread o worker Wasm. In questo modo, il lavoro può essere condiviso tra molti worker, ma richiede l'accesso a SharedArrayBuffer, che può comportare l'aggiunta di intestazioni HTTP COOP/COEP.

  3. Rifattorizza il codice C/C++ per evitare chiamate di lunga durata. Ad esempio, suddividendo il lavoro in piccole parti che possono essere chiamate da requestIdleCallback.

3. Presta attenzione agli avvisi e agli errori di runtime

Assicurati di testare effettivamente il programma WebAssembly risultante e che non vengano generati avvisi o errori nella console.

Crea ed esegui i programmi con -sASSERTIONS abilitato e correggi eventuali errori di runtime che si verificano.

4. Evita i Dynamic Links, se possibile

Emscripten funziona meglio con le librerie statiche (.a). Le librerie condivise (.so, .dylib, .dll) sono meno utili nel deployment del browser e possono complicare le cose inutilmente.

5. Porting di librerie C/C++ esistenti

Quando integri librerie C/C++ esistenti con sistemi di build standard:

Progetti CMake

Aggrega i comandi CMake con emcmake e emmake:

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

Progetti Autoconf/Make

Utilizza emconfigure per impostare i target della toolchain di cross-compilazione:

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