我在构建独立的Web程序集时遇到麻烦,我需要完全控制内存和布局。我不想使用emscripten,因为,正如下面的帖子所述,它不能满足我所需的所有编译时选项(例如,堆栈大小控制,能够选择以独立模式导入内存等)。 )我一直关注以下页面:How to generate standalone webassembly with emscripten而且,emscripten太过分了。
到目前为止,我已经做了:我有一个通过自制软件下载的完全正常工作的llvm 9工具链(我在macOS 10.14上)。我正在混用https://aransentin.github.io/cwasm/和https://depth-first.com/articles/2019/10/16/compiling-c-to-webassembly-and-running-it-without-emscripten/我使用wasi来获取C标准库。使用-Wl,-z,stack-size=$[1024 * 1024]
这样的链接器标记,我可以控制堆栈的大小。编译成功。太好了!
但是,我需要使用C ++标准库来支持我自己的库和其他第三方库。据我所知,似乎没有任何简单的方法来获取libc ++和libc ++ abi。
我尝试了“ hack”,在其中下载了Emscripten,并让它构建了自己的libc ++和libc ++ abi文件。然后,我尝试将那些文件和标头复制到正确的位置。然后我收到了有关缺少线程API的错误消息,这显然是由于未使用EMSCRIPTEN进行编译引起的。因此,我定义了EMSCRIPTEN宏并进行了这种工作。然后我以为也许可以删除wasi依赖项,并使用emscripten的libc版本保持一致,但是随后也有冲突/缺少标头。
简而言之,我认为我已经接近需要的位置,但是事情变得非常混乱。我怀疑我采用了最简单的非脚本化方法。
有人成功为独立的Web程序集创建了一个构建系统,可让您使用c和c ++标准库吗?
编辑:
这是我现在拥有的超级hacky构建脚本(它是我在网上找到的东西的重大修改版本:]
DEPS =
OBJ = library.o
STDLIBC_OBJ = $(patsubst %.cpp,%.o,$(wildcard stdlibc/*.cpp))
OUTPUT = library.wasm
DIR := ${CURDIR}
COMPILE_FLAGS = -Wall \
--target=wasm32-unknown-wasi \
-Os \
-D __EMSCRIPTEN__ \
-D _LIBCPP_HAS_NO_THREADS \
-flto \
--sysroot ./ \
-std=c++17 \
-ffunction-sections \
-fdata-sections \
-I./libcxx/ \
-I./libcxx/support/xlocale \
-I./libc/include \
-DPRINTF_DISABLE_SUPPORT_FLOAT=1 \
-DPRINTF_DISABLE_SUPPORT_LONG_LONG=1 \
-DPRINTF_DISABLE_SUPPORT_PTRDIFF_T=1
$(OUTPUT): $(OBJ) $(NANOLIBC_OBJ) Makefile
wasm-ld \
-o $(OUTPUT) \
--no-entry \
--export-all \
--initial-memory=131072 \
--stack-size=$[1024 * 1024] \
-error-limit=0 \
--lto-O3 \
-O3 \
-lc -lc++ -lc++abi \
--gc-sections \
-allow-undefined-file ./stdlibc/wasm.syms \
$(OBJ) \
$(LIBCXX_OBJ) \
$(STDLIBC_OBJ)
%.o: %.cpp $(DEPS) Makefile
clang++ \
-c \
$(COMPILE_FLAGS) \
-fno-exceptions \
-o $@ \
$<
library.wat: $(OUTPUT) Makefile
~/build/wabt/wasm2wat -o library.wat $(OUTPUT)
wat: library.wat
clean:
rm -f $(OBJ) $(STDLIBC_OBJ) $(OUTPUT) library.wat
我从emscripten中放入了libc,libc ++和libc ++ abi(但老实说,这是一个糟糕的安装过程。)
我一直在逐步尝试填补我猜emscripten通常会做的空白,但现在我再次陷入困境:
./libcxx/type_traits:4837:57: error: use of undeclared identifier 'byte'
constexpr typename enable_if<is_integral_v<_Integer>, byte>::type &
^
./libcxx/type_traits:4837:64: error: definition or redeclaration of 'type'
cannot name the global scope
constexpr typename enable_if<is_integral_v<_Integer>, byte>::type &
由于系统可能会意外地编译特定于平台的内容,因此我不再确定这是否还会起作用。我真正想要的是一个垫片,该垫片将只允许我主要使用标准容器。这已经变得难以管理。接下来我该怎么办?
编辑2:是的,因此缺少C ++ 17类型特征内容,当我使用C ++ 14(我仍然想要C ++ 17)时,我最终会遇到更多丢失的东西。绝对卡住了。
如果有帮助,Surma就如何做到这一点写了一篇很棒的文章: