Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions .agents/docs/2026-08-09-add-sqlite3-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# 新增 SQLite 收录(compat.sqlite3,C 源码 compat)

**日期**: 2026-08-09
**本仓**: `mcpplibs/mcpp-index`
**参考**: PR #48(cJSON compat)、#50(eigen);skill [`add-mcpp-index-package`](../skills/add-mcpp-index-package/SKILL.md)
**目标**: 收录 SQLite 引擎本体为 `compat.sqlite3`(C 源码 compat 形态),版本 **3.45.3**,用户
`#include <sqlite3.h>` 开箱即用;最小示例 `tests/examples/sqlite3/` 走完整冷验证。

---

## 1. 版本选择:3.45.3(部署最广,而非最新)

用户要求"选最广泛使用的版本,不追求最新"。调研结论:3.45.x 是当前部署面最广的版本线。

| 平台 | SQLite 版本 |
|---|---|
| Ubuntu 24.04 LTS(支持至 2029+) | 3.45.1(安全更新在 3.45.x 线内) |
| CPython 3.11 / 3.12 / 3.13 官方安装器 | 3.45.1 / 3.45.3 / 3.45.3 |
| Debian 13(trixie)/ Debian 12(bookworm) | 3.46.1 / 3.40.1(3.45 处于两者交集) |
| Android 15+ / iOS 18+ 时代生态 | 3.45+ 被普遍视为兼容基准 |

- **3.45.3** = 3.45.x 线最后一个维护版(含该线安全/稳定性修复),API 与 Ubuntu 24.04 LTS 的 3.45.1 一致,更成熟。
- 未选最新 3.53.4:新版本线部署面尚未铺开,收录后对消费侧无兼容收益。
- 后续可加新版本线:xpm 加行即可,mcpp 块不变。

## 2. 上游布局与哈希(已实测)

- GLOBAL:`https://sqlite.org/2024/sqlite-amalgamation-3450300.zip`(HEAD 200 已验证;3.45.1/3.45.2/3.45.3
均存在,年路径为发布年)。
- sha256(两次计算一致):`ea170e73e447703e8359308ca2e4366a3ae0c4304a8665896f068c736781c651`。
- zip 单层 wrap `sqlite-amalgamation-3450300/`,内含 `sqlite3.c`(9.0 MB)、`shell.c`、`sqlite3.h`、
`sqlite3ext.h`。glob `*` 吸收 wrap 层。
- 许可:Public Domain(SPDX 无标准 id,采用 `LicenseRef-Public-Domain` 惯例)。

## 3. 形态判定:形态 A(C 源码 compat),无 feature

- 只编 `sqlite3.c` 进 lib;`shell.c`(交互式 CLI)不编 —— 它依赖 editline/readline。
- `include_dirs = {"*"}` 暴露 `sqlite3.h` / `sqlite3ext.h`。
- amalgamation 开箱即编,无需任何 define/config;`c_standard = c11`(与 compat.cjson 对齐)。
- **无可门控组件**:amalgamation 是单一 TU,可选功能全部由编译期 define 控制(如
`SQLITE_OMIT_*` / `SQLITE_ENABLE_*`),而当前 mcpp feature 表只能门控 sources、不能携带 define → 不实现
feature(同 compat.eigen 对 define 类开关的结论)。
- **无 CN 镜像**:sqlite.org 是 amalgamation 的唯一权威来源(GitHub `sqlite/sqlite` 镜像仓**不含**生成的
`sqlite3.c`,raw 404 实测);无 `mcpp-res` 写权限 → 采用纯字符串 url 回退(先例:compat.hiredis /
compat.spdlog / compat.redis-plus-plus)。

## 4. 描述符与消费者示例

- `pkgs/c/compat.sqlite3.lua`:三平台同 url+sha;`sources = {"*/sqlite3.c"}`;target `sqlite3`(kind lib)。
- `tests/examples/sqlite3/`:`mcpp.toml` 依赖 `compat.sqlite3 = "3.45.3"`;`tests/sqlite3_test.cpp` 断言
`sqlite3_libversion() == "3.45.3"`,并走 `sqlite3_open(:memory:) → sqlite3_exec 建表/插入 → 预编译语句查询`
全链路。
- 根 `mcpp.toml` `[workspace] members` 登记 `tests/examples/sqlite3`(CI 的成员选择与 `--all` 都读它)。

## 5. 本地验证(mcpp 2026.8.8.2,与 CI 同版)

- 环境:`MCPP`/`MCPP_HOME`/`MCPP_VENDORED_XLINGS` 指向 `mcpp-2026.8.8.2-macosx-arm64` 解包根,
`MCPP_INDEX_MIRROR=GLOBAL`;`~/.mcpp/registry` 复制 release 自带 registry。
- 结果(`$MCPP test -p sqlite3`,冷状态,自动装 llvm@20.1.7 工具链):
`sqlite3_test ... ok (0.27s)` / `test result ok. 1 passed; 0 failed; finished in 104.29s`。
- 包从 sqlite.org 下载、`sqlite3.c` 编译、链接、运行断言全部通过。

## 6. lint(复现 validate.yml)

- lua 语法 `loadfile(...,'t')` OK;`spec/name/xpm` 必填字段齐全;无前导 v。
- `check_mirror_urls.lua` OK(纯字符串 url 不施加镜像约束)。
- `check_package_name.lua` OK;全仓 `check_cross_package_refs.lua` OK。

## 7. 后续可选项(不在本 PR 范围)

- **C++ 封装层**(SQLiteCpp / sqlite_orm):用户已评估 —— 非必要,引擎先行;若后续做,sqlite_orm 为
header-only 且提供 MIT 双许可,适合独立 PR。
- **CN 镜像**:获得 `mcpp-res` 写权限后,可将 url 改写为 `{ GLOBAL=…, CN=… }` 表(sha256 不变)。
- **新版本线**:3.46+/3.50+/3.53+ 作为新 xpm 行追加。

## 8. 多版本支持方案(后续可实施,难度低)

SQLite amalgamation 布局几十年来恒定(每版均为 `sqlite3.c` / `sqlite3.h` / `sqlite3ext.h` / `shell.c`,
同一个 wrap 层),因此**一个 `mcpp` 块通吃所有版本**:`sources` / `include_dirs` / `c_standard` 不变,
加版本 = 三平台各加一行 `xpm` 条目。对比本仓难例(`compat.catch2` v2/v3 形态切换、`compat.redis-plus-plus`
subset/superset 源码并集),SQLite 属最简单一档。

### 8.1 URL 数字编码与年路径(唯一需要小心的点)

版本号 → 数字编码 = 大版本 1 位 + 次版本 2 位 + 补丁 2 位;URL 带**发布年**路径。已实测:

| 版本 | URL | 备注 |
|---|---|---|
| 3.45.3 | `https://sqlite.org/2024/sqlite-amalgamation-3450300.zip` | 本 PR 收录 |
| 3.46.1 | `https://sqlite.org/2024/sqlite-amalgamation-3460100.zip` | 3.46 → `34601` |
| 3.50.0 | `https://sqlite.org/2025/sqlite-amalgamation-3500000.zip` | 3.50 → `35000`,勿写成 `350` |
| 3.53.4 | `https://sqlite.org/2026/sqlite-amalgamation-3530400.zip` | 年路径随发布年变 |

### 8.2 加一版的操作步骤

1. 下载对应 zip,`tar -tzf` 确认布局仍为四件套(应无变化)。
2. `sha256sum` 计算两次确认稳定。
3. 描述符三平台各加一个 `["x.y.z"] = { url=…, sha256=… }` 行(mcpp 块不动)。
4. 新成员 `tests/examples/sqlite3-<ver>/`(或复用既有成员改 pin)做冷验证。

### 8.3 测试与 CI 覆盖策略

- **每版本一个成员、断言各自 pin 的版本**(先例:`tests/examples/redis-plus-plus` 与
`redis-plus-plus-v133` 各 pin 一版),不放松 `sqlite3_libversion()` 断言 —— 否则「解析到的确为所 pin
版本」的证明被削弱。
- CI 成员选择规则为「描述符变更 → 选中所有 mcpp.toml 引用 `sqlite3` 的成员」,故新增第二成员后,改描述符
时两个版本都会被 CI 覆盖。
- SQLite API 纯增量、文件格式兼容,同一行为测试跨版本通常直接通过;各成员的意义在于证明该版本
编译+链接+行为均正常。

### 8.4 何时加

- 用户侧出现对更新版本线的需求(如新 feature / 新文件格式扩展)时按上述步骤追加;
- 加 CN 镜像(获得 `mcpp-res` 写权限)与加新版本相互独立,互不阻塞。
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Two kinds of packages live here:
| Shape | Examples |
|------|------|
| Native module library (Form A) | [`mcpplibs.xpkg`](pkgs/x/xpkg.lua) · [`mcpplibs.tinyhttps`](pkgs/t/tinyhttps.lua) · [`tensorvia-cpu`](pkgs/t/tensorvia-cpu.lua) · [`ffmpeg`](pkgs/f/ffmpeg.lua) (module layer; sources compiled directly through `compat.ffmpeg`) · [`opencv`](pkgs/o/opencv.lua) (single repository: the module layer and the full OpenCV 5 source build both live in the package, and only this descriptor stays on the index side) · [`mcpplibs.grpc`](pkgs/g/grpc.lua) (gRPC 1.83.0 — the one library here that CANNOT be a compat descriptor: upstream publishes no self-contained source artifact, its tag archive carrying abseil/protobuf/re2/boringssl/zlib as empty submodule placeholders, so [grpc-m](https://github.com/mcpplibs/grpc-m)'s release tarball IS that artifact. It vendors only gRPC's own source and takes the five dependencies from this index, so a consumer that also uses protobuf links one copy rather than two) |
| C-source compat (with `features`) | [`compat.cjson`](pkgs/c/compat.cjson.lua) · [`compat.zlib`](pkgs/c/compat.zlib.lua) |
| C-source compat (with `features`) | [`compat.cjson`](pkgs/c/compat.cjson.lua) · [`compat.zlib`](pkgs/c/compat.zlib.lua) · [`compat.sqlite3`](pkgs/c/compat.sqlite3.lua) (plain C-source, no features: the single `sqlite3.c` amalgamation; 3.45.3, the final maintenance release of the most widely deployed 3.45.x line) |
| C++-source compat, one depending on the other | [`compat.abseil`](pkgs/c/compat.abseil.lua) (151 TUs; a wildcard over `absl/**` trimmed by upstream's test/benchmark naming conventions) · [`compat.protobuf`](pkgs/c/compat.protobuf.lua) (the libprotobuf runtime, 79 TUs transcribed from upstream's own `src/file_lists.cmake`; declares `compat.abseil` as a dependency because protobuf's public headers include `absl/…`, and its `gzip` feature defines `HAVE_ZLIB` and pulls `compat.zlib`, while `upb` adds protobuf's 64-TU C runtime out of the same tarball. It also exposes **`protoc`** as a `kind = "bin"` target, so a consumer writing `tools = ["protoc"]` gets the compiler built for its own machine out of the same package it links — making a generator/runtime version mismatch inexpressible) · [`compat.re2`](pkgs/c/compat.re2.lua) (22 TUs, upstream's own `RE2_SOURCES`) |
| C++-source compat, zero-dep client + optional components | [`compat.websocket`](pkgs/c/compat.websocket.lua) (IXWebSocket 12.0.1 — a pure RFC 6455 client compiled from upstream's `IXWEBSOCKET_SOURCES` minus the four server TUs, so the **base build has zero external dependencies**: TLS off (the OpenSSL/MbedTLS/AppleSSL TUs aren't built) and `IXWEBSOCKET_USE_ZLIB` unset, so the gzip codec compiles to a no-op. Two optional features add on top: `server` (the four server TUs — `IXWebSocketServer`, `IXSocketServer`, `IXHttpServer`, `IXWebSocketProxyServer` — needing nothing external, and it **implies `zlib`** because upstream's server advertises permessage-deflate by default, which the transport negotiates regardless of the define) and `zlib` (deps `compat.zlib` and turns the codec into real per-message-deflate compression). The default-feature test brings its own minimal RFC 6455 echo server on loopback sockets (handshake, masking, fragmentation and close all exercised offline); a second member, `websocket-features`, runs a real `ix::WebSocketServer` and asserts the compression is observable on the wire — a 64 KiB repeated payload round-trips with `wireSize` = 80) |
| header-only (with `features`) | [`compat.eigen`](pkgs/c/compat.eigen.lua) |
Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ mcpp self config --mirror CN # 切换至国内镜像,默认使用 GLOBAL 上
| 形态 | 示例 |
|------|------|
| 原生模块库(Form A) | [`mcpplibs.xpkg`](pkgs/x/xpkg.lua) · [`mcpplibs.tinyhttps`](pkgs/t/tinyhttps.lua) · [`tensorvia-cpu`](pkgs/t/tensorvia-cpu.lua) · [`ffmpeg`](pkgs/f/ffmpeg.lua)(模块层,源码经 `compat.ffmpeg` 直编) · [`opencv`](pkgs/o/opencv.lua)(单仓库:模块层与 OpenCV 5 全源码构建同在包内,索引侧只留本描述符) · [`mcpplibs.grpc`](pkgs/g/grpc.lua)(gRPC 1.83.0 —— 本索引里唯一**无法**做成 compat 描述符的库:上游不发布任何自包含源码产物,其 tag 归档里 abseil/protobuf/re2/boringssl/zlib 全是空 submodule 占位,因此 [grpc-m](https://github.com/mcpplibs/grpc-m) 的 release tarball 才是那个产物。它只 vendor gRPC 自己的源码,五个依赖全取自本索引,故同时直接使用 protobuf 的消费者链进去的是同一份而非两份)|
| C 源码 compat(含 `features`) | [`compat.cjson`](pkgs/c/compat.cjson.lua) · [`compat.zlib`](pkgs/c/compat.zlib.lua) |
| C 源码 compat(含 `features`) | [`compat.cjson`](pkgs/c/compat.cjson.lua) · [`compat.zlib`](pkgs/c/compat.zlib.lua) · [`compat.sqlite3`](pkgs/c/compat.sqlite3.lua)(纯 C 源码、无 feature:单一 `sqlite3.c` amalgamation;3.45.3,部署最广的 3.45.x 线最后一个维护版) |
| C++ 源码 compat(彼此依赖) | [`compat.abseil`](pkgs/c/compat.abseil.lua)(151 TU;对 `absl/**` 取通配后,按上游自身的 test/benchmark 命名约定裁剪) · [`compat.protobuf`](pkgs/c/compat.protobuf.lua)(libprotobuf 运行时,79 TU 逐条转录自上游 `src/file_lists.cmake`;因 protobuf 公开头文件 include 了 `absl/…`,故显式依赖 `compat.abseil`;`gzip` feature 定义 `HAVE_ZLIB` 并拉入 `compat.zlib`,`upb` feature 则从同一个 tarball 里再编出 protobuf 的 64 TU C 运行时;还以 `kind = "bin"` target 暴露 **`protoc`**,消费者写 `tools = ["protoc"]` 即可从「自己链接的那个包」拿到为本机构建的编译器,使生成器与运行时的版本错配无法表达) · [`compat.re2`](pkgs/c/compat.re2.lua)(22 TU,取自上游自身的 `RE2_SOURCES`) |
| C++ 源码 compat(零依赖客户端 + 可选组件) | [`compat.websocket`](pkgs/c/compat.websocket.lua)(IXWebSocket 12.0.1 —— 从上游 `IXWEBSOCKET_SOURCES` 剔掉 4 个 server TU 后直编的纯 RFC 6455 客户端,**基座零外部依赖**:TLS 关闭(OpenSSL/MbedTLS/AppleSSL 三组 TU 均不编),`IXWEBSOCKET_USE_ZLIB` 不定义(gzip codec 编译为 no-op)。两个可选 feature 在基座上叠加:`server`(4 个 server TU —— `IXWebSocketServer`/`IXSocketServer`/`IXHttpServer`/`IXWebSocketProxyServer`,零新增外部依赖,且 **implies `zlib`** —— 因为上游 server 默认就宣称 permessage-deflate,而 transport 的协商不受宏门控)与 `zlib`(依赖 `compat.zlib`,把 codec 变成真正的 permessage-deflate 压缩)。默认构建的测试自带基于 loopback 原始 socket 的最小 RFC 6455 echo server(握手/掩码/分片/关闭全部离线实测);第二个成员 `websocket-features` 跑真实的 `ix::WebSocketServer`,并断言压缩在线路上可观测 —— 64 KiB 重复载荷往返,`wireSize` = 80) |
| header-only(含 `features`) | [`compat.eigen`](pkgs/c/compat.eigen.lua) |
Expand Down
1 change: 1 addition & 0 deletions mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ members = [
"tests/examples/llmapi",
"tests/examples/md4c",
"tests/examples/spdlog-compiled",
"tests/examples/sqlite3",
"tests/examples/tinyhttps",
"tests/examples/vulkan",
"tests/examples/websocket",
Expand Down
60 changes: 60 additions & 0 deletions pkgs/c/compat.sqlite3.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
-- Form B inline descriptor for SQLite — the most widely deployed database
-- engine in the world, distributed as a single C amalgamation. Pure-C source
-- build (same shape as compat.cjson / compat.zlib): compile sqlite3.c into a
-- lib, expose sqlite3.h / sqlite3ext.h via include_dirs. shell.c (the
-- interactive CLI) stays out — it pulls in editline/readline dependencies.
-- The amalgamation builds out of the box with no defines.
--
-- VERSION. 3.45.3 is the FINAL maintenance release of the 3.45.x series, the
-- most widely deployed SQLite line: Ubuntu 24.04 LTS ships 3.45.1 and CPython
-- 3.11/3.12/3.13 official installers ship 3.45.1/3.45.3/3.45.3. Pinning this
-- mature baseline rather than the newest release keeps consumers
-- API-compatible with the largest installed base; newer series can be added
-- later as extra xpm rows (the mcpp block never changes).
--
-- No CN mirror: sqlite.org is the authoritative source for the amalgamation
-- (the GitHub sqlite/sqlite mirror does NOT carry the generated sqlite3.c),
-- and plain-string url is the documented fallback without mcpp-res write
-- access (docs/cn-mirror.md; precedent: compat.hiredis / compat.spdlog).
package = {
spec = "1",
namespace = "compat",
name = "sqlite3",
description = "SQLite — self-contained SQL database engine (C amalgamation)",
licenses = {"LicenseRef-Public-Domain"},
repo = "https://sqlite.org/",
type = "package",

xpm = {
linux = {
["3.45.3"] = {
url = "https://sqlite.org/2024/sqlite-amalgamation-3450300.zip",
sha256 = "ea170e73e447703e8359308ca2e4366a3ae0c4304a8665896f068c736781c651",
},
},
macosx = {
["3.45.3"] = {
url = "https://sqlite.org/2024/sqlite-amalgamation-3450300.zip",
sha256 = "ea170e73e447703e8359308ca2e4366a3ae0c4304a8665896f068c736781c651",
},
},
windows = {
["3.45.3"] = {
url = "https://sqlite.org/2024/sqlite-amalgamation-3450300.zip",
sha256 = "ea170e73e447703e8359308ca2e4366a3ae0c4304a8665896f068c736781c651",
},
},
},

mcpp = {
language = "c++23",
import_std = false,
c_standard = "c11",
-- Tarball root: exposes sqlite3.h and sqlite3ext.h to consumers
-- writing `#include <sqlite3.h>`.
include_dirs = { "*" },
sources = { "*/sqlite3.c" },
targets = { ["sqlite3"] = { kind = "lib" } },
deps = { },
},
}
9 changes: 9 additions & 0 deletions tests/examples/sqlite3/mcpp.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SQLite test project: depends on compat.sqlite3 (built from source via this
# repo's own index) and asserts behavior under `mcpp test`. Part of the
# mcpp-index self-referential workspace.
[package]
name = "sqlite3-tests"
version = "0.1.0"

[dependencies.compat]
sqlite3 = "3.45.3"
39 changes: 39 additions & 0 deletions tests/examples/sqlite3/tests/sqlite3_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Behavioral test for compat.sqlite3 (SQLite 3.45.3, C API): assert the
// resolved library version, then open an in-memory database, create a table,
// insert a row, and read it back through both sqlite3_exec and a prepared
// statement.
#include <sqlite3.h>
#include <cassert>
#include <cstring>

int main() {
// The index pins 3.45.3; prove the resolved package is that version.
assert(std::strcmp(sqlite3_libversion(), "3.45.3") == 0);

sqlite3* db = nullptr;
assert(sqlite3_open(":memory:", &db) == SQLITE_OK);
assert(db != nullptr);

// DDL + DML through the convenience API.
char* errmsg = nullptr;
int rc = sqlite3_exec(db,
"CREATE TABLE t(id INTEGER PRIMARY KEY, name TEXT NOT NULL);"
"INSERT INTO t(name) VALUES ('mcpp');",
nullptr, nullptr, &errmsg);
assert(rc == SQLITE_OK);
if (errmsg != nullptr) { sqlite3_free(errmsg); errmsg = nullptr; }

// Read back through a prepared statement.
sqlite3_stmt* stmt = nullptr;
rc = sqlite3_prepare_v2(db, "SELECT id, name FROM t;", -1, &stmt, nullptr);
assert(rc == SQLITE_OK);
assert(stmt != nullptr);
assert(sqlite3_step(stmt) == SQLITE_ROW);
assert(sqlite3_column_int(stmt, 0) == 1);
assert(std::strcmp(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)), "mcpp") == 0);
assert(sqlite3_step(stmt) == SQLITE_DONE);
sqlite3_finalize(stmt);

assert(sqlite3_close(db) == SQLITE_OK);
return 0;
}
Loading