37

I have a c++ project I would like to convert to a web application. For this purpose, I would like to use Emscripten to build the project.

The project uses some external libraries. I managed to compile or find the JavaScript version of most libraries and now I am stuck with the Boost ones. Actually I do not even know how to start for Boost: they use a boostrap script to generate the files to build the libraries. It is possible to pass the toolset to this script but Emscripten is obviously not supported.

My project uses the following parts of Boost: Thread, Regex, FileSystem, Signals, System. How can I compile these libraries using Emscripten?

Edit

按照 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;
      ~~^
4

6 回答 6

32

我终于设法用 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

于 2013-03-31T18:22:49.840 回答
10

作为记录,Boost 现在包括一个“emscripten”工具集,(根据我的经验)它使上述过程变得不必要。

使用时,像往常一样使用 boostrap boost,然后像这样使用 b2(或 bjam)编译:

b2 toolset=emscripten 
于 2017-12-11T10:47:16.077 回答
8

在较新版本的 emscripten 中,您可以简单地使用ports添加 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")

问题的更多细节

于 2020-03-05T17:06:01.077 回答
3

您可以尝试配置指定gcc为工具集的 Boost 库,因为 Emscripten 建议自己作为 gcc 的替代品。此外,我认为最好将 Boost 构建为这种情况下的静态库。请记住,大多数 Boost 库都是只有头文件的,因为它们只定义模板类/函数。

于 2013-03-30T23:08:02.430 回答
1

我不知道您是否碰巧在常见问题解答中看到了这个特定问题但如果您没有:

问:如何链接到 SDL、boost 等系统库?

A. emscripten 中包含的系统库 - libc、libc++ (C++ STL) 和 SDL - 在您编译时会自动包含(以及它们的必要部分)。与其他编译器不同,您甚至不需要 -lSDL(但 -lSDL 也不会受到伤害)。

emscripten 不包含的其他库,例如 boost,您需要自己编译并链接到您的程序,就像它们是您项目中的一个模块一样。例如,查看BananaBread 如何在 libz 中链接。(注意,在 boost 的具体情况下,如果只需要 boost 头文件,则不需要编译任何东西。)

不包含的库的另一个选择是将它们实现为 JS 库,就像 emscripten 对 libc(减去 malloc)和 SDL(但不是 libc++ 或 malloc)所做的那样。请参阅 emcc 中的 --js-library。

于 2013-03-30T23:02:34.117 回答
1

emsdk 的更新:

经过大量的试验和错误,我能够通过以下方式获得 emscripten 1.39 来编译 Boost 1.71:

如果您还没有从https://emscripten.org/docs/getting_started/downloads.html安装 emsdk

导航到 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

现在使用引导脚本创建 boost-build 可执行文件 b2

./bootstrap.sh

最后,由于您的 emsdk 已经从上述步骤激活,您可以使用 emconfigure 构建 Boost 来配置所有内容,因为它需要调用 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
于 2019-12-04T07:17:22.930 回答