【问题标题】:Using Boost with Emscripten在 Emscripten 中使用 Boost
【发布时间】:2013-03-21 09:37:09
【问题描述】:

我有一个想要转换为 Web 应用程序的 c++ 项目。为此,我想使用 Emscripten 来构建项目。

该项目使用了一些外部库。我设法编译或找到了大多数库的 JavaScript 版本,现在我被 Boost 困住了。实际上我什至不知道如何开始使用 Boost:他们使用 boostrap 脚本来生成文件来构建库。可以将工具集传递给此脚本,但显然不支持 Emscripten。

我的项目使用 Boost 的以下部分:线程、正则表达式、文件系统、信号、系统。如何使用 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;
      ~~^

【问题讨论】:

  • 网页后端还是前端?
  • 它将是前端。这是一款我想在网络浏览器中玩的游戏。
  • 只是好奇,编译为 emscripten 代码时需要多少 MB 的 Boost? :D

标签: javascript c++ boost emscripten


【解决方案1】:

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

【讨论】:

  • 伟大的工作@julien。您是否尝试使用 user-config.jam 而不是硬编码路径?
  • @LCIDFire 我对Boost的配置文件不够熟悉,所以没有尝试user-config.jam。这确实是一个反复试验的过程,在我的游戏运行之前我还有工作要做。
  • @Julien,感谢您的帖子,我正在从事类似情况的项目,我按照您的建议构建了 boost。一个问题,你如何处理那些只在头文件中的类/函数?它们没有内置在静态或共享库中
【解决方案2】:

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

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

b2 toolset=emscripten 

【讨论】:

  • 这确实很有希望,但我遇到了诸如Error: ambiguity found when searching for best transformation Trying to produce type 'SEARCHED_LIB' from: 之类的问题...您是否成功地在 OSX 上使用 Emscripten 构建了 Boost?
  • 看来此错误是由 b2 查找外部库(例如 zlib、icu、bzip2 等)的方式引起的。我可以通过修改 boost_1_67_0/tools/build/src/build/generators.jam 以明确忽略生成器 searched-lib-generator 来解决这个问题
【解决方案3】:

在较新版本的 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")

More details from issue

【讨论】:

  • 单独使用emcc,不使用emcc有什么解决办法吗?使用 -s USE_BOOST_HEADERS=1 时仍然出现链接错误。谢谢!
【解决方案4】:

您可以尝试配置指定 gcc 作为工具集的 Boost 库,因为 Emscripten 建议自己使用 as being a drop-in replacement for gcc。另外,我认为最好将 Boost 构建为这种情况下的静态库。请记住,大多数 Boost 库都只有标头,因为它们只定义模板类/函数。

【讨论】:

  • 我的问题中列出的 Boost 库不仅仅是标题,否则太容易了 :) 我将尝试您的解决方案,我只需要找到如何告诉 Boost 使用 @987654324 进行编译@ 而不是 gcc
  • 同样的问题,来自 Boost 的仅标头库可以使用 -s USE_BOOST_HEADERS=1 正常工作,但其他库需要手动编译和链接,我遇到了问题,无论是使用 emcc 还是 emcmake,请参阅相关的 @987654322 @
【解决方案5】:

我不知道您是否碰巧在FAQ 中看到了这个特殊问题,但如果您没有:

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

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

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

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

【讨论】:

  • 我已经看到了这个问题,这就是为什么我尝试使用 emscripten 编译 Boost。
【解决方案6】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多