Como compilar C e C++ para WebAssembly com o Emscripten

Recursos da Web: WebAssembly

Use o Emscripten para compilar C e C++ em módulos WebAssembly (Wasm) de alto desempenho para o navegador.

1. Flags de compilação modernas do Emscripten

Ao compilar e vincular com emcc ou em++, sempre use flags modulares modernas:

  • -sEXPORT_ES6: emite a sintaxe padrão do módulo ES6 (import/export) em vez de objetos globais legados. Isso define -sMODULARIZE automaticamente.
  • -sENVIRONMENT=web: remove o código do ambiente de execução do Node.js/shell para minimizar o tamanho do pacote.
  • -sSTRICT: aplica os padrões modernos do Emscripten e falha em flags descontinuadas.
  • -sALLOW_MEMORY_GROWTH: permite que o heap de memória linear do WebAssembly se expanda dinamicamente ao alocar memória.
  • -Oz (ou -O3) + -flto: otimiza para o tamanho mínimo de payload em builds de lançamento.

2. Evitar o bloqueio da linha de execução principal

Se uma chamada para o WebAssembly provavelmente levará um tempo significativo (ou seja, mais do que alguns milissegundos), ela não deve ser chamada na linha de execução principal do navegador.

Para evitar a execução desse código na linha de execução principal do navegador, há várias abordagens possíveis:

  1. Execute todo o programa WebAssembly em um Web Worker. Essa costuma ser a solução mais simples, porque não envolve a configuração do acesso ao SharedArrayBuffer nem a alteração da origem do programa.

  2. Use pthreads ou workers do Wasm. Isso permite que o trabalho seja compartilhado entre vários workers, mas requer acesso ao SharedArrayBuffer, o que pode envolver a adição de cabeçalhos HTTP COOP/COEP.

  3. Refatore o código C/C++ para evitar chamadas de longa duração. Por exemplo, dividindo o trabalho em pequenos pedaços que podem ser chamados de requestIdleCallback.

3. Preste atenção aos avisos e erros de ambiente de execução

Teste o programa WebAssembly resultante e verifique se nenhum aviso ou erro é gerado no console.

Crie e execute os programas com o -sASSERTIONS ativado e corrija as falhas de execução produzidas.

4. Evite a vinculação dinâmica, se possível

O Emscripten funciona melhor com bibliotecas estáticas (.a). Bibliotecas compartilhadas (.so, .dylib, .dll) são menos úteis na implantação do navegador e podem complicar as coisas desnecessariamente.

5. Portabilidade de bibliotecas C/C++ atuais

Ao integrar bibliotecas C/C++ atuais com sistemas de build padrão:

Projetos do CMake

Encapsule os comandos do CMake com emcmake e emmake:

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

Projetos Autoconf / Make

Use emconfigure para definir destinos de conjunto de ferramentas de compilação cruzada:

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