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 中的建構選項即可」。

Achtung:程式碼縮小

建置環境非常喜歡最小化所有程式碼,包含將程式碼符號縮減成短小的偽隨機版本。這種方法在所有參與的程式碼都被鎖在產生的 JS/WASM 模組中時運作良好,但對於打算供模組外部程式碼使用的函式庫(例如本專案)來說卻是致命的。

在所有高於 1 的最佳化等級中,Emscripten 都會嘗試最小化所有 JS 程式碼,即使透過 --minify 0 旗標告知不要這樣做。解決方法是永遠使用 -g3(高除錯資訊等級)建置,然後使用 wasm-strip 移除產生的 WASM 檔案中的除錯資訊。