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 文件。