Uh oh!
There was an error while loading. Please reload this page.
Add EXQLITE_EXTRA_SRC: statically compile SQLite extensions into the NIF - #355
Add EXQLITE_EXTRA_SRC: statically compile SQLite extensions into the NIF#355AlanMcCann wants to merge 1 commit into
Conversation
Some targets cannot use run-time loadable extensions at all: iOS forbids
dynamic code loading, and hardened deployments often disable load_extension.
Shipping per-architecture .so files is also a maintenance burden that static
compilation removes.
EXQLITE_EXTRA_SRC takes a space-separated list of C files compiled and linked
into the NIF alongside the bundled sqlite3.c. Paired with the existing
EXQLITE_SYSTEM_CFLAGS (-DSQLITE_CORE=1 -DSQLITE_EXTRA_INIT=...), an extension
such as sqlite-vec registers itself on every connection with no load_extension
call anywhere.
- Only applies when compiling the bundled SQLite; ignored under
EXQLITE_USE_SYSTEM (linking is the system library's business there).
- No-op when the variable is unset: OBJ and the pattern rules are unchanged,
verified by building and running with and without the hook.
- Extra objects are namespaced as extra_<basename>.o in BUILD, with sources
resolved via vpath, so out-of-tree paths (deps, vendored dirs) work.
- POSIX make only for now; Makefile.win untouched.
Verified end-to-end against this branch via a path dep and make_env only
(no fork consumer patches): sqlite-vec v0.1.9 statically linked into the
bundled 3.53.4, SELECT vec_distance_cosine(vec_f32('[1,0]'), vec_f32('[0,1]'))
returning 1.0 and the 45-degree case returning 1 - 1/sqrt(2). Also verified on
iOS (device-SDK static archive + execution in the simulator) in the migration
that motivated this, where load_extension was not an option.warmwaffles
commented
Aug 13, 2026
At some point I am going to package https://sqlite.org/vec1/doc/trunk/doc/vec1.md with this project once it becomes "offical" and stable. |
warmwaffles
left a comment
There was a problem hiding this comment.
This doesn't seem too insane to me. Tools for people who know the risks they are taking.
I was contemplating bundling sqlite-vec with this project, but I don't know if I can get it to cross compile for all supported precompiled architectures.
warmwaffles
commented
Aug 13, 2026
Question:
How is this possible? This is a precompiled binary or compiled straight from source, how is the "hardened" server deployments disabling load extension @AlanMcCann? |
Why
Run-time loadable extensions don't cover every target: iOS forbids dynamic code loading outright, and some hardened server deployments disable
load_extension. Shipping one pre-compiled.soper architecture is also a real maintenance burden. For those cases the natural answer is compiling the extension into the NIF next to the bundledsqlite3.c— SQLite supports this officially viaSQLITE_EXTRA_INIT— but the Makefile's source list is currently fixed, so today this requires forking exqlite.We hit this migrating a production Elixir app (SQLite + sqlite-vec for vector search, including an iOS target) and carried exactly this patch as a vendored fork; upstreaming the generic hook so nobody else has to.
What
EXQLITE_EXTRA_SRC— a space-separated list of C files compiled and linked into the NIF. Combined with the existingEXQLITE_SYSTEM_CFLAGS, an extension registers on every connection with noload_extensionanywhere:with an 8-line shim calling
sqlite3_auto_extension(sqlite3_vec_init). README section and CHANGELOG entry included.Design notes
OBJand the existing pattern rules are byte-identical without the variable.EXQLITE_USE_SYSTEM(linking is the system library's business there).extra_<basename>.owith sources resolved viavpath, so out-of-tree paths (deps, vendored dirs) work. Basename collisions are documented.Makefile.winuntouched (happy to add if you want it).Verified by execution
Against this branch, consumed as a plain path dep through
make_envonly:(orthogonal vectors → cosine distance 1.0; 45° → 1 − 1/√2 — known-answer checks, not just "it loaded"). The same static-link approach (same flags + shim) was additionally verified on iOS: device-SDK static archive builds clean and the query executes correctly in the simulator, which is the platform where this hook is the only option.