Emscripten

Emscripten 是构建 WASM 应用程序的“首选”工具链。尽管还有其他一些工具可用,例如 wasi-sdk 甚至原生 clang,但 Emscripten 拥有构建许多类型的 C 库并使其开箱即用所需的几个特性,最值得注意的是其 POSIX I/O API 代理支持。sqlite3 *可以* 使用其他工具链构建,但目前它无法做太多事情,因为要加载生成的 WASM 文件需要客户端为 I/O 层函数提供实现(一项相当艰巨的任务!)。

此页面介绍了在 Linux 上使用 Emscripten SDK 构建 sqlite3 的过程。它在其他平台上未经测试。使用通过 Linux 包管理器安装的 Emscripten 版本进行构建可能有效也可能无效。

Emscripten SDK(又名 emsdk)

首先,安装 Emscripten SDK,如 此处 所述,并在下面针对 Linux 环境进行了总结

# Clone the emscripten repository:
$ sudo apt install git
$ git clone https://github.com/emscripten-core/emsdk.git
$ cd emsdk

# Download and install the latest SDK tools:
$ ./emsdk install latest

# Make the "latest" SDK "active" for the current user:
$ ./emsdk activate latest

这些部分只需要运行一次,但可以使用以下命令更新 SDK:

$ git pull
$ ./emsdk install latest
$ ./emsdk activate latest

基于痛苦的经验的提醒:如果更新 SDK 导致问题,请务必查看 EMSDK 变更日志 以了解不兼容的更改(例如,堆栈内存大小等默认值的更改)。

以下内容需要为每个需要 emcc 编译器的 shell 实例运行

# Activate PATH and other environment variables in the current terminal:
$ source /path/to/emsdk/emsdk_env.sh

$ which emcc
/path/to/emsdk/upstream/emscripten/emcc

或者,将其添加到您的登录 shell 的资源文件(~/.bashrc 或等效文件)中

EMSDK_HOME=$HOME/src/emsdk
if [ -f "$EMSDK_HOME/emsdk_env.sh" ]; then
    export EMSDK_HOME
    export EMSDK_QUIET=1
    source "$EMSDK_HOME/emsdk_env.sh"
fi

WABT 工具(wasm-strip

wabt 工具包含 wasm-strip,它由规范构建过程用于“剥离”生成的 .wasm 文件以使其更小。

由于 Emscripten 处理符号名称混淆和缩小的方式与 sqlite3 构建不兼容(导致完全无法使用的 JS 文件),因此必须使用 -g3 启用完整调试信息来创建构建。这会抑制 Emscripten 对符号的缩小,但也会导致 .wasm 文件非常大。然后,wasm-strip 可以通过删除调试符号来缩小这些文件。如果构建找到 wasm-strip,它将自动使用。如果找不到,构建将发出警告但仍会继续,主要缺点是 .wasm 文件将非常大。

如果 wasm-strip 警告“无效代码段”,则 wasm-strip 的版本太旧,只需更新即可。

使用 Emscripten 构建 sqlite3

最简单的方法是从 sqlite3 源代码树的顶部执行以下操作

$ ./configure --enable-all
$ make sqlite3.c
$ cd ext/wasm
$ make

请注意,此处的 make 是 GNU Make,在某些平台上称为 gmake

该目录中的 GNUMakefile 包含用于创建结果 WASM 文件的完整构建选项详细信息。Emscripten 提供了 大量设置,并且 makefile 包含有关其中几个设置以及为什么使用(或不使用)它们的说明。

待办事项:扩展这些文档以提供创建自定义构建的“以散文为导向的指南”,而不仅仅是告诉客户端“只需修改 makefile 中的构建选项”。

注意:代码缩小

构建环境*非常* 喜欢最小化所有代码,包括将代码符号缩减为小的伪随机版本。当所有参与代码都锁定在生成的 JS/WASM 模块中时,这种方法可以正常工作,但对于旨在由这些库外部的代码(如本项目)使用的*库*来说是致命的。

Emscripten 在高于 1 的所有优化级别上,都会尝试最小化所有 JS 代码,即使通过 --minify 0 标志指示它不要这样做。解决方法是始终使用 -g3(高调试信息级别)进行构建,然后使用 wasm-strip 剥离生成的 WASM 文件。