❮ Table of contents

Compile SQLite to WebAssembly

I'm working on a custom file format where SQLite fits the bill. It needs to be read by a web application, and that's super easy with sql.js, a version of SQLite compiled to WebAssembly. SQLite have a few extensions I'd like to use that's not in the distributed sql.js wasm file, so here's the steps to compile your own version of SQLite to WebAssembly.

Start by installing a fresh Ubuntu 20.04 or later in your preferred hypervisor or copy and paste a script to set up Ubuntu 20.04 on WSL. Emscripten installs Node globally and writes a bunch of text to the console every time you login afterwards, so you probably don't want to run this in an OS you use for other things.

Requirements

sudo apt-get install cmake default-jre git-core unzip

Install Emscripten

git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh

Compile sql.js

git clone https://github.com/sql-js/sql.js.git
cd sql.js
npm run rebuild

Let's see what flags sql.js is compiled with by default by investigating sql.js/Makefile

Flag Description
O2 Optimization flag. Though O3 applies all optimizations, I got a slightly bigger wasm file when using O3 (only a few kilobytes though). More details here.
SQLITE_OMIT_LOAD_EXTENSION Omits the entire extension loading mechanism from SQLite. Additional extensions can still be compiled into the binary, I think they just can't be loaded dynamically.
SQLITE_DISABLE_LFS Disable Large File Support. This seems related to a kernel change in Linux regarding support for files greater than 2GB on 32-bit systems. Not supporting SQLite files greater than 2GB on web seems fair.
SQLITE_ENABLE_FTS3 Enable an old full-text search extension. You should remove this.
SQLITE_ENABLE_FTS3_PARENTHESIS Adds support for operators AND and NOT as well as nested parenthesis in an extension you're not going to use. You should remove this.
SQLITE_THREADSAFE=0 Removes thread-safety logic. This flag makes sense because JavaScript is single-threaded.
SQLITE_ENABLE_NORMALIZE This is an undocumented flag, but it enables the function sqlite3_normalized_sql. It's purpose seems to be about making it easier to write prepared statements. Read more.

Read more about all the flags in SQLite's documentation

I hope to write an article later about the extensions I'd like to use: JSON1, FTS5 and Spellcheck1. They're a great match between simple and powerful, and I believe they can be quite useful in a web application. When removing FTS3 from the build, the additional extensions only add 100 kb to the .wasm-file (before gzip).