Компиляция C и C++ в WebAssembly с помощью Emscripten

Веб-функции: WebAssembly

Используйте Emscripten для компиляции C и C++ в высокопроизводительные модули WebAssembly (Wasm) для браузера.

1. Современные флаги компиляции Emscripten

При компиляции и связывании с помощью emcc или em++ всегда используйте современные модульные флаги:

  • -sEXPORT_ES6 – генерирует стандартный синтаксис модуля ES6 (import/export), а не устаревшие глобальные объекты. Это автоматически задает -sMODULARIZE.
  • -sENVIRONMENT=web: удаляет код среды выполнения Node.js/shell, чтобы уменьшить размер пакета.
  • -sSTRICT: применяет современные настройки Emscripten по умолчанию и выдает ошибку при использовании устаревших флагов.
  • -sALLOW_MEMORY_GROWTH – позволяет динамически расширять линейную память WebAssembly при выделении памяти.
  • -Oz (или -O3) + -flto: оптимизирует размер полезной нагрузки в конечных сборках.

2. Не блокируйте основной поток

Если вызов WebAssembly может занять значительное время (более нескольких миллисекунд), его не следует вызывать в основном потоке браузера.

Чтобы избежать выполнения такого кода в основном потоке браузера, можно использовать несколько подходов:

  1. Запустите всю программу WebAssembly в веб-воркере. Часто это самое простое решение, поскольку оно не требует настройки доступа к SharedArrayBuffer или изменения исходного кода программы.

  2. Используйте pthreads или Wasm Workers. Это позволяет распределять работу между несколькими рабочими процессами, но требует доступа к SharedArrayBuffer, что может потребовать добавления HTTP-заголовков COOP/COEP.

  3. Проведите рефакторинг кода C/C++, чтобы избежать длительных вызовов. Например, разбить работу на небольшие части, которые можно вызывать из requestIdleCallback.

3. Обращайте внимание на предупреждения и ошибки во время выполнения

Обязательно протестируйте полученную программу WebAssembly и убедитесь, что в консоли не появляются предупреждения или ошибки.

Создайте и запустите программы с включенным -sASSERTIONS и исправьте все возникающие ошибки во время выполнения.

4. По возможности избегайте динамического связывания

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