Proposal
Vendor the SQLite amalgamation (sqlite3.c / sqlite3.h, public domain) into contrib/sqlite/ and compile it from source through the same zig cc backend the rest of the toolchain cross-compiles with. This makes sqlite-using programs self-contained across targets — no target-system libsqlite3 required — and caches the compiled object in CI/release infra exactly like std.audio's miniaudio already does.
Why it fits Aether's model well
- zig cc compiles C from source per-target (
tools/ae_cross.c): zig bundles each target's libc/headers, so a dependency-free C amalgamation is the ideal cross case. The SQLite amalgamation is exactly that — pure C99, no external deps, public domain (zero license friction).
- Precedent already in the tree:
std.audio vendors miniaudio (std/audio/miniaudio.h, ~96k lines) and its compiled .o is cached in GitHub Actions, keyed by source content-hash, split restore/save (PRs read, only a merge-to-main fills, on a miss). A vendored sqlite3.c slots into the identical pattern. See .github/workflows/ci.yml "miniaudio object cache" steps.
What it fixes
Today contrib/sqlite links the system -lsqlite3 (aether_sqlite.c bundles nothing; ae_cross.c maps the veneer to -laether_sqlite -lsqlite3). That's the weak link for cross builds: there is no libsqlite3 for, say, aarch64-freebsd on a Linux host, so cross-compiling a sqlite program is effectively blocked. Compiling a vendored amalgamation per-target removes that dependency entirely.
Caveats (why this isn't a no-brainer — the trade-offs to decide)
-
Repo size / the deliberate contrib policy. The amalgamation is ~4 MiB (~250k lines). aether_sqlite.c:36-38 explicitly says "Bundling the 4 MiB amalgamation in contrib/ would defeat the point of having moved sqlite to contrib/" (see docs/stdlib-vs-contrib.md). This proposal reverses that decision — worth an explicit call. Mitigation: fetch-on-demand the pinned amalgamation (checksum-verified) instead of committing it, or gate vendoring behind a build flag (--with-vendored-sqlite).
-
Compile cost. ~250k lines is ~a minute per fresh compile (miniaudio's ~96k costs ~1 min). Acceptable only because it's cached — but see caveat 3 for the cross gap.
-
The existing miniaudio cache is NATIVE-per-runner, NOT cross-target. ci.yml is explicit: "Never shared across platforms (matrix.os/matrix.cc are in the key)." So dropping sqlite into the miniaudio pattern gets you a cached object for each native matrix build, but not for --target cross objects. To cache cross-compiled sqlite (the actual payoff here) the cache key must be extended to include the target triple (sqlite-obj-<triple>-<srchash>), and the release workflow must compile+cache each --target variant. The caching machinery exists; this is a key-scheme + workflow addition, not new infra.
-
Feature-flag set. The zig cc invocation needs the standard -DSQLITE_THREADSAFE=…, -DSQLITE_ENABLE_FTS5, etc. threaded through (ae_cross.c already plumbs feature_defs / user_cflags), and that set becomes part of the cache key so a flag change invalidates correctly.
-
Version pinning / provenance. Pin an exact amalgamation version + SHA-256, documented, so builds are reproducible and the fetched/vendored blob is auditable.
Suggested phasing (the two decisions are separable)
- Phase 1 — native vendoring + cache (drop-in, mirrors miniaudio exactly): fetch/pin the amalgamation, compile the bridge against it, cache the native
.o per matrix runner. Immediate: removes the -lsqlite3 system dependency for native builds.
- Phase 2 — cross caching: extend the cache key with the target triple and have
--target builds compile+reuse per-triple sqlite objects. This is what actually enables self-contained sqlite cross-compiles at low build cost.
Acceptance
ae build --target aarch64-linux prog.ae (and other triples) links a working sqlite with no target-system libsqlite3 present, and CI/release reuses a cached per-(triple, srchash) sqlite object rather than recompiling the amalgamation every build.
Proposal
Vendor the SQLite amalgamation (
sqlite3.c/sqlite3.h, public domain) intocontrib/sqlite/and compile it from source through the same zig cc backend the rest of the toolchain cross-compiles with. This makes sqlite-using programs self-contained across targets — no target-systemlibsqlite3required — and caches the compiled object in CI/release infra exactly likestd.audio's miniaudio already does.Why it fits Aether's model well
tools/ae_cross.c): zig bundles each target's libc/headers, so a dependency-free C amalgamation is the ideal cross case. The SQLite amalgamation is exactly that — pure C99, no external deps, public domain (zero license friction).std.audiovendors miniaudio (std/audio/miniaudio.h, ~96k lines) and its compiled.ois cached in GitHub Actions, keyed by source content-hash, split restore/save (PRs read, only a merge-to-main fills, on a miss). A vendoredsqlite3.cslots into the identical pattern. See.github/workflows/ci.yml"miniaudio object cache" steps.What it fixes
Today
contrib/sqlitelinks the system-lsqlite3(aether_sqlite.cbundles nothing;ae_cross.cmaps the veneer to-laether_sqlite -lsqlite3). That's the weak link for cross builds: there is nolibsqlite3for, say,aarch64-freebsdon a Linux host, so cross-compiling a sqlite program is effectively blocked. Compiling a vendored amalgamation per-target removes that dependency entirely.Caveats (why this isn't a no-brainer — the trade-offs to decide)
Repo size / the deliberate contrib policy. The amalgamation is ~4 MiB (~250k lines).
aether_sqlite.c:36-38explicitly says "Bundling the 4 MiB amalgamation in contrib/ would defeat the point of having moved sqlite to contrib/" (seedocs/stdlib-vs-contrib.md). This proposal reverses that decision — worth an explicit call. Mitigation: fetch-on-demand the pinned amalgamation (checksum-verified) instead of committing it, or gate vendoring behind a build flag (--with-vendored-sqlite).Compile cost. ~250k lines is ~a minute per fresh compile (miniaudio's ~96k costs ~1 min). Acceptable only because it's cached — but see caveat 3 for the cross gap.
The existing miniaudio cache is NATIVE-per-runner, NOT cross-target.
ci.ymlis explicit: "Never shared across platforms (matrix.os/matrix.cc are in the key)." So dropping sqlite into the miniaudio pattern gets you a cached object for each native matrix build, but not for--targetcross objects. To cache cross-compiled sqlite (the actual payoff here) the cache key must be extended to include the target triple (sqlite-obj-<triple>-<srchash>), and the release workflow must compile+cache each--targetvariant. The caching machinery exists; this is a key-scheme + workflow addition, not new infra.Feature-flag set. The zig cc invocation needs the standard
-DSQLITE_THREADSAFE=…,-DSQLITE_ENABLE_FTS5, etc. threaded through (ae_cross.calready plumbsfeature_defs/user_cflags), and that set becomes part of the cache key so a flag change invalidates correctly.Version pinning / provenance. Pin an exact amalgamation version + SHA-256, documented, so builds are reproducible and the fetched/vendored blob is auditable.
Suggested phasing (the two decisions are separable)
.oper matrix runner. Immediate: removes the-lsqlite3system dependency for native builds.--targetbuilds compile+reuse per-triple sqlite objects. This is what actually enables self-contained sqlite cross-compiles at low build cost.Acceptance
ae build --target aarch64-linux prog.ae(and other triples) links a working sqlite with no target-system libsqlite3 present, and CI/release reuses a cached per-(triple, srchash) sqlite object rather than recompiling the amalgamation every build.