Использование Boost с Emscripten

У меня есть проект C ++, который я хотел бы преобразовать в веб-приложение. Для этого я хотел бы использовать Emscripten для сборки проекта.

В проекте используются некоторые внешние библиотеки. Мне удалось скомпилировать или найти версию JavaScript для большинства библиотек, и теперь я застрял на Boost. На самом деле я даже не знаю, как начать работу с Boost: они используют сценарий boostrap для создания файлов для сборки библиотек. Этому сценарию можно передать набор инструментов, но очевидно, что Emscripten не поддерживается.

В моем проекте используются следующие части Boost: Thread, Regex, FileSystem, Signals, System. Как я могу скомпилировать эти библиотеки с помощью Emscripten?

Изменить

После ответа npclaudiu я загрузил библиотеку с помощью инструментария gcc, затем отредактировал project-config.jam для настройки компилятора, заменив:

# Compiler configuration. This definition will be used unless
# you already have defined some toolsets in your user-config.jam
# file.
if ! gcc in [ feature.values <toolset> ]
{
    using gcc ;
}

с участием

# Compiler configuration. This definition will be used unless
# you already have defined some toolsets in your user-config.jam
# file.
if ! gcc in [ feature.values <toolset> ]
{
    using gcc : : "/full/path/to/em++" ;
}

Теперь набор ./b2 эффективно создает библиотеки. Boost.Signals и Boost.System хорошо компилируются. В остальных есть ошибки.

Boost.Thread жалуется:

libs/thread/src/pthread/thread.cpp:503:27: error: use of undeclared identifier 'pthread_yield'
        BOOST_VERIFY(!pthread_yield());
                      ^

Boost.Regex много жалуется на необъявление CHAR_BIT, но, похоже, это проблема в emscripten:

In file included from libs/regex/build/../src/c_regex_traits.cpp:28:
In file included from ./boost/regex/v4/c_regex_traits.hpp:26:
In file included from ./boost/regex/v4/regex_workaround.hpp:35:
/path/to/emscripten/system/include/libcxx/vector:1989:92: error: use of undeclared identifier 'CHAR_BIT'
static const unsigned __bits_per_word = static_cast<unsigned>(sizeof(__storage_type) * CHAR_BIT);
                                                                                       ^

Boost.FileSystem, похоже, тоже не работает из-за emscripten:

In file included from libs/filesystem/src/windows_file_codecvt.cpp:21:
/path/to/emscripten/system/include/libcxx/cwchar:117:9: error: no member named 'FILE' in the global namespace
using ::FILE;
      ~~^

person Julien    schedule 30.03.2013    source источник
comment
Веб-бэкэнд или фронтенд?   -  person Alex Chamberlain    schedule 31.03.2013
comment
Это будет фронтенд. Это игра, в которую я хотел бы играть в веб-браузере.   -  person Julien    schedule 31.03.2013
comment
Интересно, сколько МБ занимает Boost при компиляции в код emscripten? : D   -  person CoffeDeveloper    schedule 27.12.2014


Ответы (6)


Наконец-то мне удалось скомпилировать необходимые библиотеки с помощью emscripten. Вот шаги, которым я следовал.

Изменения в emscripten

Отредактируйте system/include/libcxx/climits, чтобы добавить следующие определения (см. http://github.com/kripken/emscripten/issues/531):

#ifndef CHAR_BIT
# define CHAR_BIT __CHAR_BIT__
#endif

#ifndef CHAR_MIN
# define CHAR_MIN (-128)
#endif

#ifndef CHAR_MAX
# define CHAR_MAX 127
#endif

#ifndef SCHAR_MIN
# define SCHAR_MIN (-128)
#endif

#ifndef SCHAR_MAX
# define SCHAR_MAX 127
#endif

#ifndef UCHAR_MAX

# define UCHAR_MAX 255
#endif

#ifndef SHRT_MIN
# define SHRT_MIN (-32767-1)
#endif

#ifndef SHRT_MAX
# define SHRT_MAX 32767
#endif

#ifndef USHRT_MAX
# define USHRT_MAX 65535
#endif

#ifndef INT_MAX
# define INT_MAX __INT_MAX__
#endif

#ifndef INT_MIN
# define INT_MIN (-INT_MAX-1)
# define INT_MIN (-INT_MAX-1)
#endif

#ifndef UINT_MAX
# define UINT_MAX (INT_MAX * 2U + 1)
#endif

#ifndef LONG_MAX
# define LONG_MAX __LONG_MAX__
#endif

#ifndef LONG_MIN
# define LONG_MIN (-LONG_MAX-1)
#endif

#ifndef ULONG_MAX
# define ULONG_MAX (LONG_MAX * 2UL + 1)
#endif

Добавьте следующую строку в system/include/libcxx/cwchar

#include <cstdio>

Компиляция Boost как разделяемых библиотек

Как предлагает npclaudiu, загрузите библиотеку с помощью инструментария gcc. Затем отредактируйте project-config.jam, чтобы настроить компилятор, и замените:

# Compiler configuration. This definition will be used unless
# you already have defined some toolsets in your user-config.jam
# file.
if ! gcc in [ feature.values <toolset> ]
{
    using gcc ;
}

с участием

# Compiler configuration. This definition will be used unless
# you already have defined some toolsets in your user-config.jam
# file.
if ! gcc in [ feature.values <toolset> ]
{
    using gcc : : "/full/path/to/emscripten/em++" ;
}

Вставьте BOOST_HAS_SCHER_YIELD в boost/config/posix_features.hpp вокруг линии 67.

Затем скомпилируйте библиотеки: ./b2 thread regex filesystem signals system

Компиляция Boost как статических библиотек

Выполните все указанные выше действия, затем отредактируйте tools/build/v2/tools/gcc.jam и замените:

toolset.flags gcc.archive .AR $(condition) : $(archiver[1]) ;

с участием

toolset.flags gcc.archive .AR $(condition) : "/full/path/to/emscripten/emar" ;

и

toolset.flags gcc.archive .RANLIB $(condition) : $(ranlib[1]) ;

с участием

toolset.flags gcc.archive .RANLIB $(condition) :
  "/full/path/to/emscripten/emranlib" ;

Скомпилируйте библиотеки: ./b2 link=static variant=release threading=single runtime-link=static thread signals system filesystem regex

person Julien    schedule 31.03.2013
comment
Отличная работа @julien. Вы пытались использовать user-config.jam вместо жесткого кодирования путей? - person abergmeier; 26.04.2013
comment
@LCIDFire Я недостаточно был знаком с файлами конфигурации Boost, поэтому не пробовал user-config.jam. Это было действительно прогрессирование методом проб и ошибок, и мне еще нужно поработать до запуска игры. - person Julien; 26.04.2013
comment
@Julien, спасибо за пост, я работаю над проектом в похожей ситуации, я получил импульс, следуя вашему совету. Один вопрос, как вы обрабатываете те классы / функции, которые находятся только в файлах заголовков? они не встроены в статическую или общую библиотеку - person jerry; 15.11.2016

К слову, Boost теперь включает набор инструментов emscripten, который (по моему опыту) делает процесс, описанный выше, ненужным.

Чтобы использовать, ускорьте ускорение как обычно, затем скомпилируйте с помощью b2 (или bjam) следующим образом:

b2 toolset=emscripten 
person Mike_L    schedule 11.12.2017
comment
это действительно многообещающе, но я сталкиваюсь с такими проблемами, как Error: ambiguity found when searching for best transformation Trying to produce type 'SEARCHED_LIB' from: ... удалось ли вам создать Boost с Emscripten на OSX? - person ofloveandhate; 20.07.2018
comment
Похоже, что эта ошибка вызвана тем, как b2 ищет внешние библиотеки (например, zlib, icu, bzip2 и т. Д.). Мне удалось обойти проблему, изменив boost_1_67_0/tools/build/src/build/generators.jam, чтобы явно игнорировать генератор searched-lib-generator - person JoshS; 07.12.2018

В более новых версиях emscripten вы можете просто добавить библиотеки Boost, используя порты . Теперь это так же просто, как добавить этот флаг к компилятору и компоновщику: -s USE_BOOST_HEADERS=1

Если вы используете CMake, вы можете добавить флаг следующим образом:

set_target_properties(your_targets_name_here PROPERTIES COMPILE_FLAGS "-s USE_BOOST_HEADERS=1" LINK_FLAGS "-s USE_BOOST_HEADERS=1")

Подробнее о проблеме

person askuri    schedule 05.03.2020
comment
Есть ли какое-то решение при использовании только emcc, а не emcc? Я все еще получаю ошибку ссылки при использовании -s USE_BOOST_HEADERS = 1. Спасибо! - person Dani P.; 20.02.2021

Вы можете попробовать настроить библиотеки Boost, указав gcc в качестве набора инструментов, поскольку Emscripten рекомендует себя как выпадающее. взамен gcc. Кроме того, я думаю, что для этого случая будет лучше, если вы создадите Boost как статические библиотеки. Имейте в виду, что большинство библиотек Boost предназначены только для заголовков, потому что они определяют только классы / функции шаблонов.

person npclaudiu    schedule 30.03.2013
comment
Библиотеки Boost, перечисленные в моем вопросе, относятся не только к заголовку, иначе это было бы слишком просто :) Я собираюсь попробовать ваше решение, мне просто нужно найти, как сообщить Boost о компиляции с emcc вместо gcc. - person Julien; 31.03.2013
comment
Та же проблема, библиотеки только для заголовков из Boost отлично работают с -s USE_BOOST_HEADERS = 1, но другие требуют компиляции и компоновки вручную, и у меня проблемы с этим, либо с emcc, либо с emcmake, см. Связанный stackoverflow.com/questions/66292106/ - person Dani P.; 22.02.2021

Я не знаю, видели ли вы именно этот вопрос в FAQ , но если у вас нет:

В. Как связать системные библиотеки, такие как SDL, boost и т. Д.?

A. Системные библиотеки, которые включены в emscripten - libc, libc ++ (C ++ STL) и SDL - автоматически включаются при компиляции (и только необходимые их части). Вам даже не понадобится -lSDL, в отличие от других компиляторов (но -lSDL тоже не повредит).

Другие библиотеки, не включенные в emscripten, например boost, вам нужно будет скомпилировать самостоятельно и связать с вашей программой, как если бы они были модулем в вашем проекте. Например, посмотрите, как BananaBread ссылается в libz. (Обратите внимание, что в конкретном случае повышения, если вам нужны только заголовки повышения, вам не нужно ничего компилировать.)

Другой вариант для библиотек, которые не включены, - реализовать их как библиотеку JS, как emscripten делает для libc (без malloc) и SDL (но не libc ++ или malloc). См. --Js-library в emcc.

person Jorge Israel Peña    schedule 30.03.2013
comment
Я видел этот вопрос и поэтому пытаюсь скомпилировать Boost с помощью emscripten. - person Julien; 31.03.2013

ОБНОВЛЕНИЕ для emsdk:

После множества проб и ошибок мне удалось получить emscripten 1.39 для компиляции Boost 1.71 следующим образом:

Установите emsdk, если вы еще этого не сделали, из https://emscripten.org/docs/getting_started/downloads.html

Перейдите в папку установки emsdk и выполните

./emsdk install latest && ./emsdk activate latest && source ./emsdk_env.sh

Перейдите в каталог, в котором вы хотите клонировать репозиторий Boost, и запустите

git clone --recursive https://github.com/boostorg/boost.git

Вы можете добавить аргумент --jobs N, где N - количество процессов для клонирования подмодулей (если вы это сделаете, это будет происходить намного быстрее).

cd boost

Теперь используйте сценарий начальной загрузки, чтобы создать исполняемый файл b2 для ускоренной сборки.

./bootstrap.sh

Наконец, поскольку ваш emsdk уже активирован на шаге выше, вы можете создать Boost с помощью emconfigure, чтобы настроить все, как это необходимо для вызовов gcc, чтобы вместо этого использовать emscripten.

emconfigure ./b2 toolset=gcc --prefix=<directory_to_install_to> --build-dir=<directory_for_intermediate_build_files>

Теперь, чтобы установить включения и библиотеки в выбранный вами каталог префиксов, запустите

emconfigure ./b2 toolset=gcc --prefix=<directory_to_install_to> --build-dir=<directory_for_intermediate_build_files> install
person Scott Butler    schedule 04.12.2019