将 Boost 与 Emscripten 结合使用
Using Boost with Emscripten
我有一个 c++ 项目,我想转换为 Web 应用程序。为此,我想使用 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 编译了所需的库。以下是我遵循的步骤。
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/config/posix_features.hpp
,在67号线附近强制BOOST_HAS_SCHER_YIELD
。
然后编译库:./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
作为记录,Boost现在包含一个"emscripten"工具集,它(根据我的经验(使上述过程变得不必要。
使用时,boostrap boost 像往常一样,然后像这样使用 b2(或 bjam(编译:
b2 toolset=emscripten
在较新版本的 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")
问题中的更多详细信息
您可以尝试配置将gcc
指定为工具集的 Boost 库,因为 Emscripten 建议自己作为 gcc 的直接替代品。另外,我认为在这种情况下,最好将 Boost 构建为静态库。请记住,大多数 Boost 库都是仅标头的,因为它们只定义模板类/函数。
UPDATE for 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
导航到要克隆提升存储库并运行的目录
git clone --recursive https://github.com/boostorg/boost.git
您可以添加参数 '--jobs N',其中 N 是克隆子模块的进程数(如果这样做,这将加快速度(。
cd boost
现在使用引导脚本创建提升构建可执行文件 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
您是否碰巧在常见问题解答中看到过这个特定问题,但如果您没有:
问。如何链接到 SDL、boost 等系统库?
答:包含在 emscripten 中的系统库 - libc、libc++ (C++ STL( 和 SDL - 在您编译时会自动包含(以及它们的必要部分(。与其他编译器不同,您甚至不需要 -lSDL(但 -lSDL 也不会受到伤害(。
其他不包含在 emscripten 中的库,如 boost,您需要自己编译并与程序链接,就像它们是项目中的模块一样。例如,看看BananaBread如何在libz中链接。(请注意,在 boost 的特定情况下,如果您只需要 boost 标头,则无需编译任何内容。
未包含的库的另一个选项是将它们实现为 JS 库,就像 emscripten 对 libc(减去 malloc(和 SDL(但不是 libc++ 或 malloc(所做的那样。请参见 EMCC 中的 --js-library。
- 多态性和功能结合
- 将 Vulkan 与 SFML 结合使用?
- 在 emscripten 网页汇编正在运行期间更新进度条?
- 将 c++ 生成器应用程序与外部 dll 结合使用
- 如何将增强MSM与增强信号结合使用?
- MS Visual Studio 解决方案结合了非托管C++项目和 C# 项目
- 函数未在作用域中声明 / 如何结合使用 header.h、header.cpp 和 main.cpp?
- 为什么 emscripten 不编译我的函数?
- Javascript 找不到使用 emscripten 编译的导出 WASM 函数
- 没有 Emscripten,如何使用标准库编译C++到 WebAssembly
- emscripten 链接全局命名符号乘法定义
- 将预编译的 C 共享库与 JNI/NDK 结合使用
- 我可以在不使用Qt for Webassembly的情况下使用Emscripten编译Qt吗?
- C++ 将函数指针与最佳性能相结合
- glfw 的基本设置会导致与 emscripten 生成的 js 文件中的事件侦听器有关的运行时错误
- Problems with emscripten (WebAssembly)
- 将 Lua 与 C++ DLL 结合使用
- 错误:未定义的符号:gzclose opencv emscripten
- 将 Boost 与 Emscripten 结合使用
- 如何将emscripten与闭包工具结合使用