diff --git a/.agents/skills/add-mcpp-index-package/SKILL.md b/.agents/skills/add-mcpp-index-package/SKILL.md new file mode 100644 index 0000000..c7cc977 --- /dev/null +++ b/.agents/skills/add-mcpp-index-package/SKILL.md @@ -0,0 +1,136 @@ +--- +name: add-mcpp-index-package +description: Use when adding a new third-party library/package to the mcpp-index repo — writing a pkgs/*/*.lua descriptor, setting up a GitCode CN mirror via gtc, adding a minimal example, and opening a green PR. Covers the four package shapes (C-source compat / header-only / C++23 module / external Form-A module repo), the GLOBAL+CN mirror table, lint rules, the feature (sources-only) gate, and local + CI verification. +--- + +# 向 mcpp-index 新增一个库(标准作业流程) + +本文件定义将上游库收录进 [`mcpp-index`](https://github.com/mcpplibs/mcpp-index) 的标准流程。其产出包括:一个 +`pkgs//.lua` 描述符、一个 GitCode CN 镜像、一个位于 `tests/examples/` 的最小工程、一条 README 记录, +以及一份设计文档。完整流程为:本地验证通过,提交 PR,CI 全部通过,由维护者合并。合并后,`publish-artifact.yml` +将自动重新发布 index artifact。 + +可直接参考的既有案例如下: + +- `.agents/docs/2026-06-27-add-cjson-and-nlohmann-json-plan.md`(C 源码 compat 与模块库)。 +- `.agents/docs/2026-06-28-add-eigen-plan.md`(header-only 库及 source-gated `blas` feature)。 +- 既有 PR:#48(cjson 与 nlohmann.json)、#50(eigen)。 + +配套参考文档位于仓库 `docs/` 目录,供人工与 agent 共同使用,可按需查阅: + +- [docs/package-types.md](../../../docs/package-types.md) —— 四种库形态的描述符模板与样例路径。 +- [docs/cn-mirror.md](../../../docs/cn-mirror.md) —— CN 镜像闭环,含无 `mcpp-res` 权限时的回退方案。 +- [docs/repository-and-schema.md](../../../docs/repository-and-schema.md) —— 仓库结构、schema、CI 行为、关键文件与注意事项。 + +## 适用范围 + +本流程适用于将一个新库(或库的新版本)加入 mcpp-index。被收录的库有两种来源,均适用本流程: + +- **(a) 第三方上游库**:其上游自身不提供 mcpp 支持(如 cJSON、Eigen、nlohmann),由本仓以 `compat` 形态适配。 +- **(b) 基于 mcpp 开发的库**:其上游已是 mcpp 工程(自带 `mcpp.toml`,可由 `mcpp emit xpkg` 产出描述符,且具备自有 + release),仅需登记进索引(如 `mcpplibs.*`、`tensorvia-cpu`)。此类库通常采用 **Form A**,描述符只声明元数据与 + 下载地址,无需内联构建信息。 + +本流程不适用于修改 mcpp 本体、修改 xlings 引擎或纯文档变更,上述内容不在本仓范围内。 + +## 总流程(十二步) + +各步骤应按顺序执行,每一步的细节见对应参考文档。建议以 todo 跟踪进度。 + +1. **调研来源与形态**(决定模板,为最关键步骤)。 + - 首先判定来源:属于 (a) 第三方上游库,还是 (b) 基于 mcpp 开发的库。 + - 对 (b),形态已确定(Form A 模块库),版本与 release 由上游提供,因此本步骤较为简单:可直接采用上游 + `mcpp emit xpkg` 的描述符,或参照 `pkgs/t/tensorvia-cpu.lua` 编写;工作重心在镜像、登记与验证。 + - 对 (a),需按下文判定形态。 + - 确定上游仓库与**最新 tag/版本**(`git ls-remote --tags ` 配合 `sort -V | tail`;须注意大版本跳跃, + 如 Eigen 由 3.4 跃迁至 5.x)。 + - 确认 License 与源码布局:下载 tarball,以 `tar -tzf` 查看顶层 wrap 目录与子目录,据此判定其属于 + **纯头文件 / C 源码 / 自带 `.cppm` 模块 / 含可选组件(可实现 feature)** 中的何种形态。 + - 计算 `sha256sum`,并**重复计算两次以确认稳定**。GitLab 等部分归档源会重新打包,导致 sha 漂移,进而使 CI + 经 GLOBAL 拉取时校验失败。 +2. **确定形态并选择模板**:详见 [docs/package-types.md](../../../docs/package-types.md)。四类形态为:C 源码 compat、 + header-only、C++23 module(generated wrapper)、外部 Form-A 模块仓。 +3. **建立 CN 镜像**:使用 `gtc` 在 gitcode `mcpp-res` 组织下建仓并发布 release,上传**与 GLOBAL 相同的 tarball**, + 以保证字节一致(sha 相同)。**在不具备 `mcpp-res` 写权限时**,不应构造镜像表,而应使用纯字符串形式 + `url = ""`(lint 允许此形式,CN 用户将回退至上游源),镜像由维护者后续补充。详见 + [docs/cn-mirror.md](../../../docs/cn-mirror.md)。 +4. **编写描述符** `pkgs//.lua`。 + - 目录 `` **取完整包名首字母**(`compat.eigen` 对应 `pkgs/c/`,`nlohmann.json` 对应 `pkgs/n/`), + 而非短名。放置错误将导致本地 path index 报 `not found in local index`。 + - `xpm` 须覆盖三平台(linux/macosx/windows),每个版本包含 `url = { GLOBAL=…, CN=… }` 与 `sha256`。 + - 版本号采用**裸版本**(如 `"1.2.3"`),不含前导 `v`;下载 URL 中可保留上游的 `…/v1.2.3.tar.gz` 形式。 +5. **识别可门控的可选组件并实现 feature**(参见下文“feature 机制”)。feature 仅能门控 **sources**。 +6. **编写最小工程** `tests/examples//`(`short` 为包名去除 `compat.`/`mcpplibs.` 前缀后的结果)。 + - 包含 `mcpp.toml`(其 `[indices].compat = { path = "../../.." }` 指回仓根)与一个 `src/main.*`, + 后者须包含**可失败的有效断言**(`return ok ? 0 : 1`)。 + - 如需测试 feature,依赖采用长式声明 `name = { version = "…", features = ["…"] }`。 +7. **本地验证**(使用与 CI 相同版本的 mcpp,详见下文“本地验证”)。必须实际执行 `mcpp build` 与 `mcpp run` 并通过。 +8. **更新 README**:在对应分类表中新增一条记录。 +9. **撰写设计文档** `.agents/docs/-add--plan.md`,记录形态判定、镜像、feature 评估、验证结论 + 与注意事项。 +10. **本地 lint**:在本地复现 `validate.yml` 的 lint 检查(语法、必填字段、无前导 v、镜像表校验)。详见 + [docs/repository-and-schema.md](../../../docs/repository-and-schema.md)。 +11. **提交变更**:由 `main` 切出新分支,依次 commit、push、开 PR(不应直接推送 `main`)。PR 描述应载明形态、镜像、 + feature 与验证结论。 +12. **确认 CI 通过**:`detect` 应仅选中本库对应的 example(`smoke-full-linux` 与 `smoke-portable` 显示 `skipping`), + `smoke-examples ()` 通过,`mirror-cn-reachable` 覆盖新增 CN url。合并由维护者执行。 + +## feature 机制 + +mcpp **0.0.68** 的包描述符 `features` 表**仅能门控 `sources`**;其余子字段会被解析器忽略(经 `manifest.cppm` 的 +features 解析逻辑确认)。 + +```lua +mcpp = { + sources = { "*/core.c" }, -- 默认始终编译 + features = { + ["extra"] = { sources = { "*/extra.c" } }, -- 默认排除;请求 features=["extra"] 时编入同一 lib 目标 + }, +} +``` + +- 消费侧声明:`dep = { version = "…", features = ["extra"] }`。 +- 既有实例:`compat.gtest` 的 `main`(gtest_main.cc)、`compat.cjson` 的 `utils`(cJSON_Utils.c)、`compat.eigen` + 的 `blas`(`*/blas/*.cpp` 与 `*/blas/f2c/*.c`)。 +- 判定某可选组件能否实现为 feature 的准则:该组件是否为**额外的可编译源码**。若是,则可门控。纯头文件(如 Eigen 的 + `unsupported/`,与核心共享 include 根,无法隐藏)不可门控;编译期 **define**(如 `EIGEN_MPL2_ONLY`、 + `EIGEN_USE_BLAS`)当前无法由 feature 表携带,因而不可门控,应在描述符中加注释说明,待 mcpp 支持 define/cflags + 后再实现。 +- glob 规则:支持 `*`(段内匹配)与 `**`(跨段匹配),因此 `*/blas/*.cpp`、`*/foo/**/*.c` 均合法。 +- **须进行负向验证**:在不启用 feature 时,对应的符号或源码应**确实缺失**(表现为链接期 `undefined reference` + 或编译期找不到),以此证明门控确实生效,而非默认即被编入。 + +## 本地验证(与 CI 同版本) + +CI 所用 mcpp 版本由 `.github/workflows/validate.yml` 的 `env.MCPP_VERSION` 指定。本地验证应使用同一版本,而非本地 +恰好安装的其它版本。 + +```bash +MV=$(grep -oP 'MCPP_VERSION:\s*"\K[0-9.]+' .github/workflows/validate.yml) +curl -L -fsS -o mcpp.tgz "https://github.com/mcpp-community/mcpp/releases/download/v$MV/mcpp-$MV-linux-x86_64.tar.gz" +tar -xzf mcpp.tgz +root="$PWD/mcpp-$MV-linux-x86_64" +mkdir -p ~/.mcpp/registry && cp -a "$root/registry/." ~/.mcpp/registry/ +export MCPP="$root/bin/mcpp" +export MCPP_VENDORED_XLINGS="$root/registry/bin/xlings" +export MCPP_INDEX_MIRROR=GLOBAL # CI example 使用 GLOBAL;CN 由 mirror-cn-reachable 单独校验 +MCPP="$MCPP" bash tests/run_example.sh +``` + +- 输出末尾应包含断言行与 `OK: `。 +- `run_example.sh` 会执行 `rm -rf target .mcpp`,自干净状态走完整管线(fetch、generate、compile、link、run)。 +- 如需查看头文件或源码,解包结果位于 `tests/examples//.mcpp/.xlings/data/xpkgs/-x-///`。 + +## 常见错误与规避 + +| 错误做法 | 正确做法 | +|----------|----------| +| 将 `compat.foo.lua` 置于 `pkgs/f/` | 置于 `pkgs/c/`,目录取完整包名首字母 | +| 版本写作 `"v1.2.3"` | 采用裸版本 `"1.2.3"`,lint 会拦截前导 v | +| CN 镜像上传经改动的包(与 GLOBAL 不一致) | 上传与 GLOBAL 相同的 tarball,sha 一致,以维持 GLOBAL/CN 一致性 | +| 仅执行 `mcpp build` 而不 `run`,或示例缺少有效断言 | 实际运行,并以 `return ok ? 0 : 1` 断言 | +| 声称实现了 feature 却未做负向验证 | 验证默认构建确实不含该组件 | +| 未对齐 CI 的 mcpp 版本,本地通过而 CI 失败 | 读取 `MCPP_VERSION` 并使用同一版本 | +| 直接推送 `main` | 切出分支并提交 PR | + +完成前应遵循 `verification-before-completion`:在声明“通过/完成”之前,须给出真实命令输出作为证据。 diff --git a/README.md b/README.md index 3a317b7..a004db2 100644 --- a/README.md +++ b/README.md @@ -1,292 +1,77 @@ # mcpp-index -> [`mcpp`](https://github.com/mcpp-community/mcpp) 构建工具的默认包索引仓库 -> -> 在线浏览: **https://mcpplibs.github.io/mcpp-index/** +> [`mcpp`](https://github.com/mcpp-community/mcpp) 构建工具的默认包索引仓库。 +> 在线浏览所有包:**https://mcpplibs.github.io/mcpp-index/** -## 快速使用 +本仓收录可被 `mcpp` 直接 `add` 的 C++23 包,既包含 `import` 即用的模块化库,也包含以 `compat` 形态从上游源码或 +头文件构建的第三方 C/C++ 库。每个包对应一个 `pkgs/<首字母>/<包名>.lua` 描述文件。 -```bash -mcpp add ftxui@6.1.9 # 添加依赖到 mcpp.toml -mcpp build # 自动拉取源码 + 构建 -``` - -## 已收录的包 - -### mcpplibs 模块化库 - -| 包名 | 版本 | 简介 | 仓库 | -|------|------|------|------| -| `mcpplibs.cmdline` | 0.0.2 | 命令行解析框架 — `import mcpplibs.cmdline;` | [mcpplibs/cmdline](https://github.com/mcpplibs/cmdline) | -| `mcpplibs.tinyhttps` | 0.2.2 | 轻量 HTTP/HTTPS 客户端(SSE 流式) — `import mcpplibs.tinyhttps;` | [mcpplibs/tinyhttps](https://github.com/mcpplibs/tinyhttps) | -| `mcpplibs.llmapi` | 0.2.5 | 大语言模型 API 客户端(OpenAI/Anthropic 兼容) — `import mcpplibs.llmapi;` | [mcpplibs/llmapi](https://github.com/mcpplibs/llmapi) | -| `mcpplibs.capi.lua` | 0.0.3 | Lua 5.4 C API 的 C++23 模块封装 — `import mcpplibs.capi.lua;` | [mcpplibs/lua](https://github.com/mcpplibs/lua) | -| `mcpplibs.xpkg` | 0.0.40 | xpkg V1 规范的 C++23 参考实现 — `import mcpplibs.xpkg;` | [openxlings/libxpkg](https://github.com/openxlings/libxpkg) | -| `mcpplibs.templates` | 0.0.1 | 最小化模块库模板 — `import mcpplibs.templates;` | [mcpplibs/templates](https://github.com/mcpplibs/templates) | - -### 独立模块化库 - -| 包名 | 版本 | 简介 | 仓库 | -|------|------|------|------| -| `imgui` | 0.0.1 | Dear ImGui C++23 模块封装 — `import imgui.core;` / `import imgui.backend.glfw_opengl3;` | [mcpplibs/imgui-m](https://github.com/mcpplibs/imgui-m) | -| `nlohmann.json` | 3.12.0 | JSON for Modern C++,开箱即用的 C++23 模块 — `import nlohmann.json;` | [nlohmann/json](https://github.com/nlohmann/json) | - -### 第三方 C/C++ 库 - -| 包名 | 版本 | 简介 | -|------|------|------| -| `ftxui` | 6.1.9 | C++ 函数式终端 UI 库(screen + dom + component) | -| `glfw` | 3.4 | GLFW 窗口与输入库(X11/null 后端源码构建) | -| `gtest` | 1.15.2 | Google Test 测试框架 | -| `cjson` | 1.7.19 | 超轻量 ANSI C JSON 解析库(`#include `,`compat` 源码构建) | -| `eigen` | 5.0.1 | C++ 模板线性代数库(header-only,`#include `;`unsupported/` 实验模块亦可用;`features = ["blas"]` 编入 Eigen 参考 BLAS) | -| `imgui` | 1.92.8 | Dear ImGui immediate-mode GUI 核心源码 | -| `opengl` | 2026.05.31 | Khronos OpenGL API 头文件 | -| `glx-runtime` | 2026.06.03 | Linux host GLVND/GLX/OpenGL runtime adapter | -| `khrplatform` | 2026.05.31 | Khronos KHR platform 头文件 | -| `xorgproto` | 2025.1 | X.Org protocol 头文件 | -| `xtrans` | 1.6.0 | X.Org transport support headers/source snippets | -| `xau` | 1.0.12 | X authorization runtime library(`libXau.so`) | -| `xdmcp` | 1.1.5 | X Display Manager Control Protocol runtime library(`libXdmcp.so`) | -| `xcb-proto` | 1.17.0 | XCB protocol XML definitions and generator metadata | -| `xcb` | 1.17.0 | X C Binding runtime library(`libxcb.so`) | -| `x11` | 1.8.13 | Xlib runtime library(`libX11.so`) and public headers | -| `xcursor` | 1.2.3 | Xcursor runtime library(`libXcursor.so`) and public headers | -| `xext` | 1.3.7 | Xext runtime library(`libXext.so`) and public headers | -| `xfixes` | 6.0.2 | Xfixes runtime library(`libXfixes.so`) and public headers | -| `xi` | 1.8.3 | XInput runtime library(`libXi.so`) and public headers | -| `xinerama` | 1.1.6 | Xinerama runtime library(`libXinerama.so`) and public headers | -| `xrandr` | 1.5.5 | Xrandr runtime library(`libXrandr.so`) and public headers | -| `xrender` | 0.9.12 | Xrender runtime library(`libXrender.so`) and public headers | -| `mbedtls` | 3.6.1 | TLS/加密库(纯 C) | -| `lua` | 5.4.7 | Lua 脚本语言(纯 C 嵌入式库) | -| `zlib` | 1.3.2 | DEFLATE 压缩库 | -| `bzip2` | 1.0.8 | bzip2 压缩库 | -| `lz4` | 1.10.0 | LZ4 压缩库 | -| `zstd` | 1.5.7 | Zstandard 压缩库 | -| `xz` | 5.8.3 | XZ Utils liblzma 压缩库 | -| `libarchive` | 3.8.7 | 多格式归档与压缩库 | - -### 依赖关系链 - -``` -mcpplibs.llmapi - └── mcpplibs.tinyhttps - └── mbedtls ← mcpp 自动传递,无需手动声明 - -mcpplibs.xpkg - └── mcpplibs.capi.lua - └── lua ← 同上 - -imgui - ├── compat.imgui - ├── compat.glfw - │ ├── compat.opengl - │ └── compat.glx-runtime - │ └── compat.xext → compat.x11 - │ ← Linux GLX/OpenGL driver runtime provider - └── compat.opengl ← 消费者只需要 import imgui.* 模块 - -libarchive - ├── zlib - ├── bzip2 - ├── lz4 - ├── zstd - └── xz ← 压缩后端自动传递 - -glfw - ├── opengl - │ └── khrplatform ← GLFW/glfw3.h 所需 OpenGL/KHR 头文件 - ├── glx-runtime - │ └── xext → x11 ← GLFW GLX dlopen 所需 host GLVND/driver runtime - └── x11 / xcursor / xext / xfixes / xi - / xinerama / xorgproto / xrandr / xrender - ← GLFW Linux X11 后端所需 runtime/header 闭包 - -xau / xdmcp - └── xorgproto ← X11 底层 runtime 库的协议头文件 - -xcb - ├── xcb-proto ← hook 内生成 xcb 协议源文件 - ├── xau - └── xdmcp - -x11 - ├── xcb - ├── xorgproto - └── xtrans ← Xlib/XIM transport 源码片段 -``` - -mcpp 0.0.3+ 的 transitive walker 自动沿链路传播头文件和依赖,消费者只需声明直接依赖。 - -> 当前 X11/XCB/Xau/Xdmcp 以及 GLFW 需要的 Xcursor/Xext/Xfixes/Xi/Xinerama/ -> Xrandr/Xrender 都已按上游源码提供 runtime `.so`,并声明标准 ELF SONAME -> (如 `libX11.so.6`、`libxcb.so.1`)。`compat.glx-runtime` 是 Linux host -> GLVND/GLX/OpenGL driver runtime adapter,提供 GLFW 上游 `dlopen` 需要的 -> `libGLX.so.0`/`libGL.so.1`/`libGL.so` runtime 目录,并通过 `compat.xext` -> 带入 host GLX 库常见的 X11/Xext ABI 依赖闭包。 -> 窗口运行时仍需要宿主环境提供可用的 X server/GLX/OpenGL 驱动。 - -### 单库示例工程(`tests/examples//`) - -每个库可以有一个最小可构建工程(自带 `mcpp.toml` + 源码,`[indices]` 相对指回本仓), -既是文档也是测试。CI 在 PR 上**只跑改动到的库**对应的示例(`tests/run_example.sh`), -其余情况(push / nightly / 改动脚手架)才跑下面的全量 smoke。 +## 使用 ```bash -MCPP=/path/to/mcpp tests/run_example.sh cjson # #include -MCPP=/path/to/mcpp tests/run_example.sh nlohmann.json # import nlohmann.json; -# 等价于:cd tests/examples/cjson && mcpp run -``` - -### 本地 smoke 验证(全量回归) +mcpp add ftxui@6.1.9 # 添加依赖到 mcpp.toml +mcpp build # 自动拉取源码并构建,依赖沿链路自动传递 -```bash -MCPP=/path/to/mcpp tests/smoke_compat_core.sh -MCPP=/path/to/mcpp tests/smoke_compat_imgui.sh -MCPP=/path/to/mcpp tests/smoke_compat_archive.sh -MCPP=/path/to/mcpp tests/smoke_imgui_module.sh +mcpp search # 搜索并刷新索引 +mcpp self config --mirror CN # 切换至国内镜像,默认使用 GLOBAL 上游源 ``` -该脚本会通过当前 checkout 作为本地 path index 创建临时 mcpp 项目,验证: +完整包列表见 **[在线索引站](https://mcpplibs.github.io/mcpp-index/)**。 -- `compat.gtest`/`compat.ftxui`/`compat.lua`/`compat.mbedtls` 能用上游 - `#include <...>` API 构建并运行最小用例 -- `compat.opengl`/`compat.khrplatform` 能提供 GLFW/OpenGL 常见头文件闭包 -- `compat.imgui@1.92.8` core 能构建并运行一个 headless ImGui frame -- `imgui@0.0.1` 模块包能通过 `[dependencies] imgui = "0.0.1"` 构建并运行 - `import imgui.core;` / `import imgui.backend.glfw_opengl3;` 最小用例 -- `compat.glfw@3.4` 能构建、运行 `glfwInit()` smoke,并链接 X11 扩展 runtime `.so` -- `compat.xau@1.0.12`/`compat.xdmcp@1.1.5` 能构建、运行并链接 runtime `.so` -- `compat.xcb@1.17.0` 能构建、运行并链接 `libxcb.so` -- `compat.x11@1.8.13` 能构建、运行并链接 `libX11.so` → `libxcb.so` -- `compat.xcursor`/`compat.xext`/`compat.xfixes`/`compat.xi`/`compat.xinerama`/ - `compat.xrandr`/`compat.xrender` 能构建、运行并链接对应 `libX*.so` -- `compat.libarchive` 能连同 `zlib`/`bzip2`/`lz4`/`zstd`/`xz` 压缩后端构建并运行 +## 包生态与贡献 -有窗口的 ImGui + GLFW + OpenGL demo 单独放在可选 smoke 中: +本仓收录两类包: -```bash -MCPP=/path/to/mcpp tests/smoke_compat_imgui_window.sh -MCPP=/path/to/mcpp MCPP_INDEX_RUN_WINDOW_SMOKE=1 tests/smoke_compat_imgui_window.sh -``` - -默认只验证 demo 构建和 X11 runtime 链接闭包。显式设置 -`MCPP_INDEX_RUN_WINDOW_SMOKE=1` 后才会运行隐藏窗口帧渲染,此时需要当前 -`DISPLAY` 可用,并且宿主机提供 GLVND/GLX/OpenGL 驱动 runtime。脚本会把 -宿主 GL runtime 和 compat X11 runtime 组装到临时 `LD_LIBRARY_PATH` 中, -避免系统 X11 库覆盖 mcpp 构建出的 `libX11.so`/`libxcb.so`。 - -## 包描述文件 - -每个包对应一个 `pkgs/<首字母>/<包名>.lua` 文件,遵循 [xpkg V1 规范](https://github.com/d2learn/xim-pkgindex/blob/main/docs/V1/xpackage-spec.md)。 - -### 两种形式 - -**Form A** — 上游自带 `mcpp.toml`,描述文件只声明元数据和下载地址: - -```lua -package = { - spec = "1", - name = "mcpplibs.tinyhttps", - xpm = { - linux = { ["0.2.2"] = { url = "...", sha256 = "..." } }, - macosx = { ["0.2.2"] = { url = "...", sha256 = "..." } }, - windows = { ["0.2.2"] = { url = "...", sha256 = "..." } }, - }, -} -``` - -**Form B** — 上游没有 `mcpp.toml`,在描述文件里内联构建信息: - -```lua -package = { - spec = "1", - name = "ftxui", - xpm = { ... }, - mcpp = { - include_dirs = { "*/include", "*/src" }, - sources = { - "*/src/ftxui/**/*.cpp", - "!*/src/ftxui/**/*_test.cpp", -- glob 排除(mcpp 0.0.4+) - "!*/src/ftxui/**/*_fuzzer.cpp", - }, - targets = { ["ftxui"] = { kind = "lib" } }, - }, -} -``` - -### 镜像源(GLOBAL / CN) +- **原生 mcpp 模块库**:以 C++23 模块发布、`import` 即用,包括 `mcpplibs.*`、`nlohmann.json`、`imgui`,以及由 + 用户基于 mcpp 开发并登记进索引的库(如 `tensorvia-cpu`)。其上游通常自带 `mcpp.toml`,描述文件(Form A)只声明 + 元数据与下载地址。 +- **第三方 C/C++ 库(`compat`)**:其上游不提供 mcpp 支持,描述文件(Form B)内联构建信息。该类库存在 + header-only、纯 C 源码、C++23 module wrapper 等形态,可选组件经 `features` 门控,并配备 GitCode CN 镜像。 -`xpm.<平台>.<版本>.url` 除了普通字符串,还支持镜像表,为不同地区提供下载源: +### 参考示例(`.lua` 描述符) -```lua -["3.6.1"] = { - url = { - GLOBAL = "https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/mbedtls-3.6.1.tar.gz", - CN = "https://gitcode.com/mcpp-res/mbedtls/releases/download/3.6.1/mbedtls-3.6.1.tar.gz", - }, - sha256 = "db75d2f7f35e29cf09f7bd6734d8ee3325f29c298ef071350c5e70a40dd4f0f9", -}, -``` - -- **GLOBAL**(默认):上游原始地址(GitHub / 官方站点),行为与之前完全一致。 -- **CN**:[`mcpp-res`](https://gitcode.com/mcpp-res) 组织在 gitcode 上的镜像 — - 每个库一个仓库,资源以 release 资产形式按版本 tag 发布,URL 形如 - `https://gitcode.com/mcpp-res/<库>/releases/download/<版本>/<库>-<版本>.`。 - CN 镜像内容与 GLOBAL 源 **逐字节一致**(同一 `sha256`),只是托管在国内可 - 快速访问的 gitcode 上。 - -切换镜像(底层透传给 xlings 安装引擎): - -```bash -mcpp self config --mirror CN # 使用国内镜像 -mcpp self config --mirror GLOBAL # 使用上游源(默认) -``` - -> 镜像表遵循 [xpkg V1 规范](https://github.com/d2learn/xim-pkgindex/blob/main/docs/V1/xpackage-spec.md) -> 的 `url = { GLOBAL=..., CN=... }` 约定,解析优先级 `GLOBAL > CN`。`validate` -> workflow 会校验镜像表完整性并探测每个 CN 资源可达。 - -### 获取方式 - -mcpp 初次运行时自动 clone 本仓库到 `~/.mcpp/registry/data/mcpp-index/`。后续更新: +| 形态 | 示例 | +|------|------| +| 原生模块库(Form A) | [`mcpplibs.tinyhttps`](pkgs/t/tinyhttps.lua) · [`tensorvia-cpu`](pkgs/t/tensorvia-cpu.lua) | +| C 源码 compat(含 `features`) | [`compat.cjson`](pkgs/c/compat.cjson.lua) · [`compat.zlib`](pkgs/c/compat.zlib.lua) | +| header-only(含 `features`) | [`compat.eigen`](pkgs/c/compat.eigen.lua) | +| C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) | -```bash -mcpp search # 触发索引刷新 + 搜索 -``` +### 新增一个包 -也可手动拉取: +完整流程定义于 agent skill [`add-mcpp-index-package`](.agents/skills/add-mcpp-index-package/SKILL.md)。可将下列 +指令提供给 agent(如 Claude Code),由其调用该 skill 完成描述文件的编写与全流程: -```bash -cd ~/.mcpp/registry/data/mcpp-index && git pull +```text +参考本仓 skill `.agents/skills/add-mcpp-index-package`,将 <库名 / 仓库URL> @<版本> 收录进 mcpp-index: +判定形态;配置 CN 镜像(无 mcpp-res 权限时使用 plain-string 上游 url);编写 pkgs/<首字母>/<包名>.lua; +添加 tests/examples/<库>/ 最小工程;使用与 CI 同版本的 mcpp 本地执行 `mcpp build && run` 进行验证; +更新 README 与在线索引;提交 PR 并确认 CI 通过。 ``` -## 添加新包 +细节文档位于 [`docs/`](docs/),供人工与 agent 共同使用: -1. Fork 本仓库 -2. 在 `pkgs/<首字母>/` 下创建 `<包名>.lua`,参考现有文件([compat.mbedtls.lua](pkgs/c/compat.mbedtls.lua)、[compat.ftxui.lua](pkgs/c/compat.ftxui.lua)) -3. 提交 PR — `validate` workflow 自动 lint,`deploy-site` 合入后自动发布到浏览站 +- [库形态与描述符模板](docs/package-types.md):C 源码、header-only、模块、外部 Form-A 四类模板与样例。 +- [CN 镜像闭环](docs/cn-mirror.md):`gtc` 与 gitcode 操作,以及无 `mcpp-res` 权限时的回退方案。 +- [仓库结构与 schema 与 CI](docs/repository-and-schema.md):字段速查、选跑机制与本地 lint。 +- 字段规范见 [mcpp 扩展字段文档](https://github.com/mcpp-community/mcpp/blob/main/docs/04-schema-xpkg-extension.md)。 -详细格式说明见 [mcpp 扩展字段文档](https://github.com/mcpp-community/mcpp/blob/main/docs/04-schema-xpkg-extension.md)。 +> 提交 PR 后,`validate` 自动执行 lint 并按改动库选跑示例;合并后,`deploy-site` 将其发布至在线浏览站。 ## 相关链接 | 项目 | 说明 | |------|------| -| [mcpp](https://github.com/mcpp-community/mcpp) | 现代 C++23 构建 & 包管理工具 | -| [xlings](https://github.com/d2learn/xlings) | mcpp 底层的包安装引擎 + 沙箱环境 | +| [mcpp](https://github.com/mcpp-community/mcpp) | 现代 C++23 构建与包管理工具 | +| [xlings](https://github.com/d2learn/xlings) | mcpp 底层的包安装引擎与沙箱环境 | | [xpkg V1 spec](https://github.com/d2learn/xim-pkgindex/blob/main/docs/V1/xpackage-spec.md) | 包描述文件规范 | | [mcpplibs](https://github.com/mcpplibs) | mcpp 生态的模块化 C++23 库集合 | -| [mcpp-res](https://gitcode.com/mcpp-res) | 包资源的 CN 镜像组织(gitcode release 资产) | -| [xim-pkgindex](https://github.com/d2learn/xim-pkgindex) | xlings 的通用包索引仓库 | +| [mcpp-res](https://gitcode.com/mcpp-res) | 包资源的 CN 镜像组织(gitcode) | ## 社区 -- **Issues / 反馈**: [mcpp issues](https://github.com/mcpp-community/mcpp/issues) · [mcpp-index issues](https://github.com/mcpp-community/mcpp-index/issues) -- **讨论 / 论坛**: [d2learn 论坛](https://forum.d2learn.org) -- **mcpplibs 库贡献**: 各库仓库接受 PR,CI 使用 mcpp 构建验证 +[mcpp issues](https://github.com/mcpp-community/mcpp/issues) · [d2learn 论坛](https://forum.d2learn.org) ## License -包描述文件: CC0。各上游库保留其自身许可证。 +包描述文件采用 CC0;各上游库保留其自身许可证。 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..16233f1 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,13 @@ +# mcpp-index 文档 + +本目录为面向贡献者的参考文档,供人工与 agent 共同使用。新增一个包的端到端流程定义于 agent skill +[`add-mcpp-index-package`](../.agents/skills/add-mcpp-index-package/SKILL.md);下列文档提供各环节的细节参考。 + +| 文档 | 内容 | +|------|------| +| [package-types.md](package-types.md) | 四种库形态(C 源码 compat、header-only、C++23 module wrapper、外部 Form-A 模块仓)的描述符模板与样例 | +| [cn-mirror.md](cn-mirror.md) | GitCode `mcpp-res` CN 镜像闭环(`gtc` 工具、闭环校验、注意事项),含无 `mcpp-res` 写权限时的回退方案(plain-string 上游 url) | +| [repository-and-schema.md](repository-and-schema.md) | 仓库布局、描述符 schema 速查、`validate.yml` CI 行为、本地 lint 复现、案例索引 | + +> 包的字段规范(`mcpp = { … }` 扩展)以上游为准,见 +> [mcpp docs/04-schema-xpkg-extension.md](https://github.com/mcpp-community/mcpp/blob/main/docs/04-schema-xpkg-extension.md)。 diff --git a/docs/cn-mirror.md b/docs/cn-mirror.md new file mode 100644 index 0000000..65c9c90 --- /dev/null +++ b/docs/cn-mirror.md @@ -0,0 +1,91 @@ +# CN 镜像闭环(gtc / gitcode / mcpp-res) + +为每个包配备国内下载镜像,可提升 `mcpp add/build` 在中国大陆的访问速度。其机制为:将 `xpm...url` 由 +单一字符串改写为 `{ GLOBAL = "<上游>", CN = "" }`,解析优先级为 **GLOBAL 优先于 CN**(GLOBAL 仍为 +默认,仅在其不可用时回退至 CN)。解析由 **xlings**(xim 引擎)完成,而非 mcpp 的 C++ parser,因此该机制由 spec +驱动并经由既有引擎生效。 + +- CN 布局:gitcode 组织 **`mcpp-res`**,每库一仓,资产挂载于按版本号打的 release 上。 +- repo slug 取包名去除 `compat.` 或 `mcpplibs.` 前缀后的结果(`compat.eigen` 对应 `eigen`;`nlohmann` 类宜用 + `nlohmann-json` 以避免裸 `json` 的歧义)。 +- CN 资产的公网 URL 约定为: + `https://gitcode.com/mcpp-res//releases/download//-.` + +## 无 `mcpp-res` 写权限时的回退 + +建立镜像需要 gitcode `mcpp-res` 组织的写权限(token)。在不具备该权限时,不应勉强构造镜像表:lint +(`check_mirror_urls.lua`)强制要求,一旦 `url` 写成表形式,其 `CN` 必须为 `https://gitcode.com/mcpp-res/…`, +因此 `{ GLOBAL=上游, CN=上游 }` 会直接导致 lint 失败。正确的回退方式是采用纯字符串 url(仅填上游 release), +lint 对纯字符串 url 不施加镜像约束: + +```lua +-- 回退:无 CN 镜像,GLOBAL 与 CN 均等价于上游 release(使用单一字符串即可) +["0.1.1"] = { url = "https://github.com///releases/download/v0.1.1/-0.1.1.tar.gz", + sha256 = "…" }, +``` + +- CN 用户将回退至上游源,访问较慢但功能不受影响。 +- 既有先例:`pkgs/t/tensorvia-cpu.lua`(用户自有 mcpp 库,无 CN 镜像,三平台均使用上游单一字符串 url)。 +- 后续在获得权限、或由维护者补充镜像后,可将该版本的 `url` 改写为 `{ GLOBAL=…, CN=… }` 表(sha256 保持不变)。 + +如需表达“GLOBAL 与 CN 均指向上游”,应采用上述单一字符串写法,而不应写成 `{ GLOBAL=x, CN=x }` 表(其无法通过 +“CN 必须指向 gitcode”的 lint 检查)。 + +## gtc 工具 + +`gtc`(`tools/gtc`,亦位于 `~/.local/bin/gtc`,python 实现,基于 gitcode API v5)。Token 位于 +`~/.config/gitcode-tool/config.json`,亦可经 `GITCODE_TOKEN` 或 `--token` 覆盖。当前登录用户为 `Sunrisepeak`。 + +```bash +gtc repo create / [--description …] [--private] # owner==login 时走 /user/repos,否则走 /orgs//repos;幂等(422 仅告警) +gtc repo push / [--branch main] +gtc release create / --tag T [--name] [--body-file] [--target] [--prerelease] # 幂等(tag 已存在则跳过) +gtc release upload / --tag T # 非幂等,上传前应先查询现有资产 +gtc release publish / --tag T [--name] [--target] [--asset FILE] # 等价于 create + upload +gtc pr create / --title --head --base [--body-file] +``` + +`gtc` 不能创建 org;`mcpp-res` 已存在。如需新建 org,应调用 `POST /api/v5/orgs` 并同时提供 `name` 与 `path` 字段。 + +## 标准操作(以 slug=`eigen`、ver=`5.0.1` 为例) + +```bash +# 0. 下载 GLOBAL 上游 tarball,计算 sha256(填入描述符三平台);重复计算两次以确认稳定 +curl -L -fsS -o eigen-5.0.1.tar.gz "https://gitlab.com/libeigen/eigen/-/archive/5.0.1/eigen-5.0.1.tar.gz" +sha256sum eigen-5.0.1.tar.gz + +# 1. 建仓(幂等) +gtc repo create mcpp-res/eigen --description "Eigen — CN mirror for mcpp-index" + +# 2. 新仓尚无分支,须先推送一个 init commit,release 方可 target main +mkdir eigen-init && echo "# Eigen — CN mirror" > eigen-init/README.md +gtc repo push mcpp-res/eigen eigen-init --branch main + +# 3. 发布 release 并上传资产(上传与 GLOBAL 相同的文件,以保证字节一致与 sha 相同) +gtc release publish mcpp-res/eigen --tag 5.0.1 --name "Eigen 5.0.1" --target main --asset eigen-5.0.1.tar.gz + +# 4. 闭环校验:CN 返回 200,且与 GLOBAL 字节一致 +CN="https://gitcode.com/mcpp-res/eigen/releases/download/5.0.1/eigen-5.0.1.tar.gz" +curl -fsSL -o cn.tar.gz -w 'CN http=%{http_code}\n' "$CN" +[ "$(sha256sum eigen-5.0.1.tar.gz|cut -d' ' -f1)" = "$(sha256sum cn.tar.gz|cut -d' ' -f1)" ] && echo "BYTE-IDENTICAL" +``` + +## 注意事项 + +- gitcode API 限流为 25 次/分钟/用户,调用间隔宜约 3.2 秒,遇 429 应退避重试。 +- 同名 release 资产不可覆盖,误传后只能经网页删除,因此命名应一次确定(`-.`)。 +- 新仓无分支:未先推送 init commit 时,release `--target main` 将失败。 +- 内容过滤:部分库描述或仓名会被 gitcode 文本过滤拒绝,应改用中性措辞。 +- 必须上传与 GLOBAL 相同的包:不应上传经改动的包,否则 CN 与 GLOBAL 不一致,且除 `mirror-cn-reachable` 外难以察觉。 +- sha 漂移:GitLab 归档偶有重新打包导致 sha 变化,描述符的 sha 必须等于当前 GLOBAL 的实际字节(下载后即用,并重复 + 计算两次)。 +- xlings 按 sha256 全局去重:当 CN 与 GLOBAL 的 sha 相同时,本地“切换 CN 重新测试”会命中去重缓存,不会真正访问 + gitcode,因此校验 CN 应直接使用 `curl`(即上文第 4 步,亦为 CI `mirror-cn-reachable` 所执行)。 + +## CI 保障 + +`.github/workflows/validate.yml` 设有两道校验: + +- `lint` 中的 `tests/check_mirror_urls.lua`:当 url 写成表时,GLOBAL 与 CN 均须存在,且 CN 必须指向 gitcode + `mcpp-res` 镜像。 +- `mirror-cn-reachable`:抽取全部 CN url 并逐个 `curl`,任一非 200 即失败。 diff --git a/docs/package-types.md b/docs/package-types.md new file mode 100644 index 0000000..9e2f440 --- /dev/null +++ b/docs/package-types.md @@ -0,0 +1,145 @@ +# 库形态与描述符模板 + +编写描述符前,应先判定库所属的形态,再选用对应模板。`mcpp = {}` 内的所有路径均为**相对 verdir 的 GLOB**: +前导 `*` 用于吸收 tarball 的 `-/` wrap 层;`*` 匹配单段,`**` 匹配跨段(例如 `*/blas/*.cpp` 合法)。 + +四种形态的判定要点如下: + +| 形态 | 特征 | 样例 | 关键字段 | +|---|---|---|---| +| **A. C 源码 compat** | 纯 C 或少量源码,用户 `#include ` | `pkgs/c/compat.cjson.lua`、`compat.zlib.lua`、`compat.gtest.lua` | `sources` 与 `c_standard` | +| **B. header-only** | 纯头文件,无需编译 | `pkgs/c/compat.eigen.lua`、`compat.opengl.lua`、`compat.khrplatform.lua` | `include_dirs` 与 anchor 源 | +| **C. C++23 module** | 暴露 `import x.y;` | `pkgs/n/nlohmann.json.lua` | `modules` 与 `generated_files` 或源 `.cppm` | +| **D. 外部 Form-A 模块仓** | 上游自带 mcpp 描述符,独立仓库 | `pkgs/i/imgui.lua`、`pkgs/m/mcpplibs.*` | `mcpp = ""`(Form A) | + +A、B、C 三类共用的骨架(`package` 头与 `xpm`)如下: + +```lua +package = { + spec = "1", + namespace = "compat", -- compat / nlohmann / mcpplibs 等,决定 import 前缀与依赖 key + name = "compat.", -- 完整包名,决定 pkgs/<首字母>/ 的落点 + description = "…", + licenses = {"MIT"}, -- SPDX + repo = "https://…", + type = "package", + + xpm = { -- 三平台均需声明;纯源码或纯头时三平台共用同一 url 与 sha256 + linux = { ["1.2.3"] = { url = { GLOBAL = "https://…/v1.2.3.tar.gz", + CN = "https://gitcode.com/mcpp-res//releases/download/1.2.3/-1.2.3.tar.gz" }, + sha256 = "<计算所得>" } }, + macosx = { ["1.2.3"] = { url = { GLOBAL = "…", CN = "…" }, sha256 = "…" } }, + windows = { ["1.2.3"] = { url = { GLOBAL = "…", CN = "…" }, sha256 = "…" } }, + }, + + mcpp = { … 见下文各形态 … }, +} +``` + +--- + +## A. C 源码 compat(`compat.cjson` / `compat.zlib`) + +将 C 源码编译为 lib,头文件经 `include_dirs` 暴露,可选组件由 `features` 门控。 + +```lua +mcpp = { + language = "c++23", -- 与既有 compat 对齐;实际的 C 行为由 c_standard 决定 + import_std = false, + c_standard = "c99", -- 或 c11 + include_dirs = { "*" }, -- 暴露顶层头文件(*/foo.h) + sources = { "*/cJSON.c" }, -- 核心源码,始终编译 + targets = { ["cjson"] = { kind = "lib" } }, + features = { -- 可选扩展,默认不编译 + ["utils"] = { sources = { "*/cJSON_Utils.c" } }, + }, + deps = { }, +} +``` + +要点:多源码时可逐个列出(`compat.zlib` 列出了 15 个 `.c`)或使用 glob;需要配置头时可用 `generated_files` 合成 +(`compat.zlib` 使用 `mcpp_generated/include/mcpp_zlib_config.h` 配合 `cflags = {"-include …"}`)。 + +## B. header-only(`compat.eigen` / `compat.opengl`) + +此类库无可编译源码:由 `include_dirs` 暴露头文件,并加入一个 trivial anchor `.c`,以提供一个可构建的 lib 目标。 + +```lua +mcpp = { + language = "c++23", + import_std = false, + c_standard = "c11", + include_dirs = { "*" }, -- 或更精确的 "*/include" / "*/api" + generated_files = { + ["mcpp_generated/_anchor.c"] = "int mcpp_compat__anchor(void) { return 0; }\n", + }, + sources = { "mcpp_generated/_anchor.c" }, + targets = { [""] = { kind = "lib" } }, + -- 若存在额外可编译源码的组件(非纯头),可实现为 source-gated feature: + features = { + ["blas"] = { sources = { "*/blas/*.cpp", "*/blas/f2c/*.c" } }, -- eigen 实例 + }, + deps = { }, +} +``` + +注意:纯头形式的可选项无法隐藏(与核心共享 include 根),因此不应为其勉强构造 feature;只有额外可编译源码才能被门控 +(`compat.eigen` 的 `blas` 即由 C++ 与 f2c 转换的 C 构成,不依赖 Fortran,因此可门控)。 + +## C. C++23 module(`nlohmann.json`) + +使用户可 `import x.y;`。有两种实现路径: + +1. **上游已自带 `.cppm`**:直接 `sources = { "*/path/to/unit.cppm" }`。 +2. **上游 release 不含**(较常见):以 `generated_files` 合成 wrapper(`#include
`、`export module x.y;`、 + `export using …`),基底头 pin 至已发布 tag。应逐字复用上游官方 wrapper,而非自行推断符号清单。 + +```lua +mcpp = { + schema = "0.1", + language = "c++23", + import_std = false, -- wrapper 含上游头,启用 import std 易产生冲突 + modules = { "nlohmann.json" }, + include_dirs = { "*/single_include" }, -- 使 wrapper 内的 #include <…> 可解析 + generated_files = { + ["mcpp_generated/nlohmann.json.cppm"] = "module;\n#include \nexport module nlohmann.json;\n…", + }, + sources = { "mcpp_generated/nlohmann.json.cppm" }, + targets = { ["nlohmann_json"] = { kind = "lib" } }, + deps = { }, +} +``` + +注意:mcpp 段解析器不支持 Lua 长括号 `[[ … ]]`,`generated_files` 的内容必须采用双引号字符串并对 `\n`、`\"` +转义,否则报 `malformed mcpp segment`。消费侧不应将 `import x.y;` 与文本 `#include ` 混用(会与 GCC +modules 冲突),应配合 `import std;`。 + +## D. 外部 Form-A 模块仓(`imgui` / `mcpplibs.*`) + +上游或独立仓库自带 mcpp 描述符,本仓仅充当指针:`mcpp = "<相对或远程路径>"`(Form A,而非内联的 Form B)。新增的 +独立库通常归属于另一仓库(如 `mcpplibs/imgui-m`),本仓只负责登记。写法可参照 `pkgs/i/imgui.lua` 与 +`pkgs/m/mcpplibs.xpkg.lua`。 + +--- + +## 最小工程(`tests/examples//`) + +`mcpp.toml`(短式依赖与长式依赖二选一): + +```toml +[package] +name = "-example" +version = "0.1.0" +[toolchain] +default = "gcc@16.1.0" +[indices] +compat = { path = "../../.." } # 指回仓根,以使用本地描述符 +[dependencies.compat] + = "1.2.3" # 或: = { version = "1.2.3", features = ["…"] } +[targets.-example] +kind = "bin" +main = "src/main.cpp" # C 库可使用 .c +``` + +`src/main.cpp` 应包含有效断言并 `return ok ? 0 : 1`,而非仅打印输出。module 库使用 `import std; import x.y;`; +header-only 与 C 库使用文本 `#include`。 diff --git a/docs/repository-and-schema.md b/docs/repository-and-schema.md new file mode 100644 index 0000000..9e998d5 --- /dev/null +++ b/docs/repository-and-schema.md @@ -0,0 +1,95 @@ +# 仓库结构、schema、CI 与关键文件 + +## 仓库布局 + +``` +pkgs//.lua 描述符。 取完整包名首字母(compat.* → c,nlohmann.json → n,imgui → i) +tests/examples// 每库最小工程( 为包名去除 compat./mcpplibs. 前缀后的结果) + mcpp.toml [indices].compat = { path = "../../.." } + src/main.{cpp,c} +tests/run_example.sh 通用 runner:rm -rf target .mcpp,继而 mcpp build 与 mcpp run +tests/smoke_compat_*.sh 旧全量 smoke,已降级为 nightly/dispatch 保障 +tests/check_mirror_urls.lua lint:GLOBAL+CN 表完整性,以及 CN 指向 mcpp-res +tests/list_cn_urls.lua 抽取 CN url,供 mirror-cn-reachable 使用 +README.md 索引说明与贡献入口 +.github/workflows/validate.yml CI:lint / mirror-cn-reachable / detect / smoke-examples / smoke-full-linux / smoke-portable +.agents/docs/-*.md 设计文档惯例 +docs/ 贡献者参考文档(本目录) +tools/gtc gitcode CLI,见 cn-mirror.md +.xpkgindex.json 站点配置(标题、链接、install 模板),通常无需改动 +``` + +## 外部仓库与文档 + +- mcpp 本体:https://github.com/mcpp-community/mcpp(本地通常存在 clone: + `/home/speak/workspace/github/mcpp-community/mcpp`)。`mcpp --version` 应与 CI 对齐;feature 与 glob 行为以 + `src/manifest.cppm`、`src/modgraph/scanner.cppm`、`src/build/prepare.cppm` 为准。 +- xpkg 扩展 schema(权威): + https://github.com/mcpp-community/mcpp/blob/main/docs/04-schema-xpkg-extension.md(对应本仓 `.xpkgindex.json` 的 + “mcpp ext” 链接)。V1 xpkg spec 见 `d2learn/xim-pkgindex` 的 `docs/V1/xpackage-spec.md`(url-template 约在第 172 行)。 +- CN 镜像组织:gitcode `mcpp-res`。 + +## 描述符 schema 速查(Form B inline) + +`package` 必填字段:`spec`、`namespace`、`name`、`description`、`licenses`、`repo`、`type="package"`、`xpm`、`mcpp`。 + +`xpm..<裸版本>`: + +- `url`:字符串,或 `{ GLOBAL=…, CN=… }` 表(本仓统一使用表形式)。 +- `sha256`:必填,等于实际下载字节的摘要。 + +`mcpp`(常用键): + +| 键 | 说明 | +|---|---| +| `language` | 通常为 `"c++23"` | +| `import_std` | 多数为 `false` | +| `c_standard` | C 源码:`"c99"` 或 `"c11"` | +| `modules` | module 库:`{ "x.y" }` | +| `include_dirs` | glob 列表,暴露给消费者的头目录 | +| `generated_files` | `{ ["相对路径"]="内容字符串" }`;不支持 `[[…]]`,须以 `\n`、`\"` 转义 | +| `sources` | glob 列表,编入 lib 的源码 | +| `cflags` / `cxxflags` / `ldflags` | 追加至对应规则 | +| `targets` | `{ ["name"]={ kind="lib"/"bin", main=…, soname=… } }` | +| `features` | `{ ["f"]={ sources={…} } }`,仅识别 sources | +| `deps` | `{ ["ns.name"]="ver" }`,扁平或点号式 | + +## CI 行为(validate.yml) + +- 触发条件:PR(改动 `pkgs/**/*.lua`、`tests/**`、`README.md` 或本 workflow)、push 至 main、nightly cron、手动触发。 +- `env.MCPP_VERSION` 为全部 job 使用的 mcpp 版本,本地验证应与之对齐。 +- `lint`(始终运行):lua 语法 `loadfile(f,'t')`;须含 `spec=`/`name=`/`xpm=`;禁止前导 v 版本;执行 + `check_mirror_urls.lua`。 +- `mirror-cn-reachable`(始终运行):逐个 `curl` CN url,均须返回 200。 +- `detect`:PR 时由 `git diff` 取改动的 `pkgs/*/*.lua`,对 basename 去除 `compat.`,若存在 + `tests/examples//` 则仅运行该示例;改动 scaffolding/CI 或无对应 example 时,执行全量回归。 +- `smoke-examples ()`:在干净 runner 上运行 `run_example.sh`,`MCPP_INDEX_MIRROR=GLOBAL`。 +- `smoke-full-linux` 与 `smoke-portable`(mac/win):全量回归,仅在 push、nightly、dispatch 或脚手架变更时运行; + 常规单库 PR 应显示 `skipping`。 + +## 本地 lint 复现(等价于 CI lint job) + +```bash +fail=0 +for f in pkgs/*/*.lua; do + lua5.4 -e "assert(loadfile('$f','t'))" >/dev/null 2>&1 || { echo "SYNTAX $f"; fail=1; } + for n in 'spec *=' 'name *=' 'xpm *='; do grep -q "$n" "$f" || { echo "MISS $n $f"; fail=1; }; done + grep -nqE '\["v[0-9]+|\["[^"]+"\][[:space:]]*=[[:space:]]*"v[0-9]+' "$f" && { echo "LEADING-V $f"; fail=1; } + lua5.4 tests/check_mirror_urls.lua "$f" >/dev/null 2>&1 || { echo "MIRROR $f"; fail=1; } +done +[ $fail -eq 0 ] && echo "ALL LINT PASS" +``` + +## 合并后 + +`publish-artifact.yml` 在合并至 `main` 后自动重新发布 mcpp-index artifact 并移动指针,无需发布新的 mcpp 版本。 +在线浏览地址:https://mcpplibs.github.io/mcpp-index/ + +## 案例索引 + +| 形态 | 描述符 | example | 设计文档 / PR | +|---|---|---|---| +| C 源码 + feature | `pkgs/c/compat.cjson.lua`、`compat.gtest.lua` | `tests/examples/cjson/` | `.agents/docs/2026-06-27-add-cjson-and-nlohmann-json-plan.md` / #48 | +| C++23 module(generated wrapper) | `pkgs/n/nlohmann.json.lua` | `tests/examples/nlohmann.json/` | 同上 / #48 | +| header-only + source-gated feature | `pkgs/c/compat.eigen.lua` | `tests/examples/eigen/` | `.agents/docs/2026-06-28-add-eigen-plan.md` / #50 | +| header-only(纯头) | `pkgs/c/compat.opengl.lua`、`compat.khrplatform.lua` | — | `.agents/docs/2026-06-03-gl-runtime-packages-plan.md` |