From af34f6ebab013e41c893f31467322d7f16e0aa44 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Sun, 28 Jun 2026 21:34:04 +0800 Subject: [PATCH 1/4] docs(skills): add `add-mcpp-index-package` agent skill (SOP) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codifies the full process used for cjson/nlohmann/eigen into a reusable skill under .agents/skills/add-mcpp-index-package/: - SKILL.md — 12-step SOP, the sources-only feature gate (+ mandatory negative test), version-matched local verification, red-flags/common mistakes. - package-types.md — descriptor templates for the four shapes (C-source compat / header-only / C++23 module via generated wrapper / external Form-A module repo), each with real sample paths. - cn-mirror.md — gtc/gitcode mcpp-res mirror closed loop + every known gotcha. - references.md — repo layout, descriptor schema cheat-sheet, validate.yml CI behavior, one-shot local lint, real worked examples (#48 / #50). --- .../skills/add-mcpp-index-package/SKILL.md | 100 +++++++++++++ .../add-mcpp-index-package/cn-mirror.md | 64 ++++++++ .../add-mcpp-index-package/package-types.md | 138 ++++++++++++++++++ .../add-mcpp-index-package/references.md | 86 +++++++++++ 4 files changed, 388 insertions(+) create mode 100644 .agents/skills/add-mcpp-index-package/SKILL.md create mode 100644 .agents/skills/add-mcpp-index-package/cn-mirror.md create mode 100644 .agents/skills/add-mcpp-index-package/package-types.md create mode 100644 .agents/skills/add-mcpp-index-package/references.md 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..baf36cc --- /dev/null +++ b/.agents/skills/add-mcpp-index-package/SKILL.md @@ -0,0 +1,100 @@ +--- +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 新增一个库(SOP) + +把一个上游库收录进 [`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)。 + +> 配套参考文件(按需读): +> - [package-types.md](package-types.md) —— 四种库形态的描述符模板 + 真实样例路径 +> - [cn-mirror.md](cn-mirror.md) —— gtc / gitcode CN 镜像闭环 +> - [references.md](references.md) —— 仓库结构、schema、CI、关键文件、踩坑清单 + +## 何时用 / 不用 +- **用**:把一个新的第三方库(或新版本)加进 mcpp-index。 +- **不用**:改 mcpp 本体、改 xlings 引擎、纯文档。那些不在本仓。 + +## 总流程(12 步) + +按顺序做;每步的细节进对应参考文件。建议用 todo 跟踪。 + +1. **调研上游**(最关键,决定形态) + - 上游仓库、**最新 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. **定形态 → 选模板**:见 [package-types.md](package-types.md)。四类:C-source compat / header-only / C++23 module(generated wrapper)/ 外部 Form-A 模块仓。 +3. **建 CN 镜像**:`gtc` 在 gitcode `mcpp-res` org 下建仓 + 发 release,上传**与 GLOBAL 同一个 tarball**(保证 byte-identical → 同 sha)。见 [cn-mirror.md](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 机制")。只能门控 **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** 在对应表(mcpplibs 模块库 / 独立模块库 / 第三方 C/C++ 库)加一行。 +9. **设计文档** `.agents/docs/-add--plan.md`,记录形态判断、镜像、feature 评估、实测结论、踩坑。 +10. **本地 lint**:模拟 `validate.yml` 的 lint(语法 / 必填字段 / 无前导 v / mirror 检查)。见 [references.md](references.md)。 +11. **分支 → commit → push → PR**(从 `main` 切新分支;别直接推 main)。PR 描述写清形态、镜像、feature、实测。 +12. **盯 CI 绿**:`detect` 应只选中本库的 example(`smoke-full-linux`/`portable` 显示 `skipping`),`smoke-examples ()` 绿;`mirror-cn-reachable` 覆盖新 CN url。合并交维护者。 + +## feature 机制(务必读准) + +mcpp **0.0.68** 的包描述符 `features` 表 **只能门控 `sources`**(其它子字段被 skip;源码核实见 `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`。 +- ❌ 直接 push `main`。✅ 切分支开 PR。 +- 完成前遵循 `verification-before-completion`:**贴出真实命令输出**再说"绿/完成",不要凭感觉。 diff --git a/.agents/skills/add-mcpp-index-package/cn-mirror.md b/.agents/skills/add-mcpp-index-package/cn-mirror.md new file mode 100644 index 0000000..f7cab0f --- /dev/null +++ b/.agents/skills/add-mcpp-index-package/cn-mirror.md @@ -0,0 +1,64 @@ +# CN 镜像闭环(gtc / gitcode / mcpp-res) + +给每个包配一个国内下载镜像,让 `mcpp add/build` 在中国也快。机制 = `xpm...url` 从单串变成 +`{ GLOBAL = "<上游>", CN = "" }`,解析优先级 **GLOBAL > CN**(GLOBAL 仍是默认,死了才回落 CN)。 +解析方是 **xlings**(xim 引擎),不是 mcpp 的 C++ parser —— 这是 spec 驱动、走既有引擎。 + +- CN 布局:gitcode org **`mcpp-res`**,一库一仓,资产挂在按版本号打的 release 上。 +- **repo slug = 包名去 `compat.` / `mcpplibs.` 前缀**(`compat.eigen` → `eigen`,`compat.nlohmann?` 用 `nlohmann-json` 避免裸 `json` 歧义)。 +- CN 资产公网 URL 约定: + `https://gitcode.com/mcpp-res//releases/download//-.` + +## 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 同一个文件 → byte-identical → 同 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.2s,遇 429 退避。 +- **同名 release 资产不可覆盖**:误传只能网页删 → 命名一次定死(`-.`)。 +- **新仓无分支**:不先 push init,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/.agents/skills/add-mcpp-index-package/package-types.md b/.agents/skills/add-mcpp-index-package/package-types.md new file mode 100644 index 0000000..975cd1a --- /dev/null +++ b/.agents/skills/add-mcpp-index-package/package-types.md @@ -0,0 +1,138 @@ +# 库形态与描述符模板 + +先判断库属于哪一类,再抄对应模板。所有 `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) | + +公共骨架(`package` 头 + `xpm`),A/B/C 通用: + +```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` 合成 +(zlib 用 `mcpp_generated/include/mcpp_zlib_config.h` + `cflags = {"-include …"}`)。 + +## B. header-only(`compat.eigen` / `compat.opengl`) + +无可编译源:`include_dirs` 暴露头,加一个 trivial anchor `.c` 给 mcpp 一个可构建的 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;只有"额外可编译源"才门控得了(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,而非 inline 的 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/C 库用文本 `#include`。 diff --git a/.agents/skills/add-mcpp-index-package/references.md b/.agents/skills/add-mcpp-index-package/references.md new file mode 100644 index 0000000..b9cf7dd --- /dev/null +++ b/.agents/skills/add-mcpp-index-package/references.md @@ -0,0 +1,86 @@ +# 参考:仓库结构 / 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 index 列表(三张表:mcpplibs 模块库 / 独立模块库 / 第三方 C/C++ 库) +.github/workflows/validate.yml CI:lint / mirror-cn-reachable / detect / smoke-examples / smoke-full-linux / smoke-portable +.agents/docs/-*.md 设计文档惯例 +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 在 ~line 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` | From 71ad4b08bbf8c109b198e12db4bfa32e8077f0cf Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Sun, 28 Jun 2026 21:43:40 +0800 Subject: [PATCH 2/4] docs(readme): slim down to intro + usage + contribution + links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the package tables/dependency tree/smoke breakdown/Form-A-B examples from the index README — the browsable site (mcpplibs.github.io/mcpp-index) is the package list, and the how-to detail lives in the add-mcpp-index-package skill. README now = what it is, mcpp add/build usage, the two package categories (native module libs / third-party compat) with a pointer to the skill, and related tools / community. --- README.md | 288 +++++------------------------------------------------- 1 file changed, 24 insertions(+), 264 deletions(-) diff --git a/README.md b/README.md index 3a317b7..40f1bdd 100644 --- a/README.md +++ b/README.md @@ -1,292 +1,52 @@ # mcpp-index > [`mcpp`](https://github.com/mcpp-community/mcpp) 构建工具的默认包索引仓库 -> -> 在线浏览: **https://mcpplibs.github.io/mcpp-index/** +> · 在线浏览所有包 **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 -``` +mcpp add ftxui@6.1.9 # 添加依赖到 mcpp.toml +mcpp build # 自动拉取源码 + 构建(依赖沿链路自动传递) -### 本地 smoke 验证(全量回归) - -```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) - -`xpm.<平台>.<版本>.url` 除了普通字符串,还支持镜像表,为不同地区提供下载源: - -```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/`。后续更新: - -```bash -mcpp search # 触发索引刷新 + 搜索 -``` - -也可手动拉取: - -```bash -cd ~/.mcpp/registry/data/mcpp-index && git pull -``` +收录两类包: -## 添加新包 +- **原生 mcpp 模块库** — 以 C++23 模块发布、`import` 即用(如 `mcpplibs.*`、`nlohmann.json`、`imgui`)。 + 上游多自带 `mcpp.toml`,描述文件只声明元数据与下载地址。 +- **第三方 C/C++ 库(`compat`)** — 上游无 mcpp 支持,在描述文件里内联构建信息:header-only、纯 C 源码、 + C++23 module wrapper 等不同形态,可选组件经 `features` 门控,并配 GitCode CN 镜像。 -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` 合入后自动发布到浏览站 +**新增一个包** → 参考 agent skill [`add-mcpp-index-package`](.agents/skills/add-mcpp-index-package/SKILL.md): +完整 SOP —— 四种库形态模板、`gtc` CN 镜像闭环、`features` 门控、本地 + CI 验证。字段规范见 +[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 底层的包安装引擎 + 沙箱环境 | +| [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 的通用包索引仓库 | +| [mcpplibs](https://github.com/mcpplibs) | mcpp 生态的模块化 C++23 库 | +| [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;各上游库保留其自身许可证。 From 73b57464328b05d76de0937d293cb0d31e1489e1 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Sun, 28 Jun 2026 22:50:39 +0800 Subject: [PATCH 3/4] docs: add docs/, README example table + agent prompt; skill mirror fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move the skill's reference files into a human-facing docs/ folder (single source): package-types.md, cn-mirror.md, repository-and-schema.md (+ index docs/README.md). SKILL.md now links to ../../../docs/*; the skill dir keeps just SKILL.md (the agent SOP). - README: add a "参考示例" table linking typical descriptors by shape (Form-A module / C-source compat / header-only / module wrapper), a copy-paste agent prompt that drives the skill end-to-end, and links to docs/. - skill + docs: document the no-`mcpp-res`-permission fallback — use a plain-string upstream `url` (lint forbids a {GLOBAL,CN} table whose CN isn't gitcode/mcpp-res; plain strings are unconstrained). Real precedent: pkgs/t/tensorvia-cpu.lua. - skill step 1 now distinguishes the two sources: a third-party upstream lib vs. the user's own mcpp-based library (Form A, lighter research). --- .../skills/add-mcpp-index-package/SKILL.md | 25 ++++++++----- README.md | 36 +++++++++++++++---- docs/README.md | 13 +++++++ .../cn-mirror.md | 20 +++++++++++ .../package-types.md | 0 .../repository-and-schema.md | 0 6 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 docs/README.md rename {.agents/skills/add-mcpp-index-package => docs}/cn-mirror.md (77%) rename {.agents/skills/add-mcpp-index-package => docs}/package-types.md (100%) rename .agents/skills/add-mcpp-index-package/references.md => docs/repository-and-schema.md (100%) diff --git a/.agents/skills/add-mcpp-index-package/SKILL.md b/.agents/skills/add-mcpp-index-package/SKILL.md index baf36cc..03e7e46 100644 --- a/.agents/skills/add-mcpp-index-package/SKILL.md +++ b/.agents/skills/add-mcpp-index-package/SKILL.md @@ -14,26 +14,33 @@ description: Use when adding a new third-party library/package to the mcpp-index - `.agents/docs/2026-06-28-add-eigen-plan.md`(header-only + source-gated `blas` feature) - 既有 PR:#48(cjson + nlohmann.json),#50(eigen)。 -> 配套参考文件(按需读): -> - [package-types.md](package-types.md) —— 四种库形态的描述符模板 + 真实样例路径 -> - [cn-mirror.md](cn-mirror.md) —— gtc / gitcode CN 镜像闭环 -> - [references.md](references.md) —— 仓库结构、schema、CI、关键文件、踩坑清单 +> 配套参考文件(在仓库 `docs/` 下,人/agent 共用,按需读): +> - [docs/package-types.md](../../../docs/package-types.md) —— 四种库形态的描述符模板 + 真实样例路径 +> - [docs/cn-mirror.md](../../../docs/cn-mirror.md) —— gtc / gitcode CN 镜像闭环(含无 mcpp-res 权限的回退) +> - [docs/repository-and-schema.md](../../../docs/repository-and-schema.md) —— 仓库结构、schema、CI、关键文件、踩坑清单 ## 何时用 / 不用 -- **用**:把一个新的第三方库(或新版本)加进 mcpp-index。 +- **用**:把一个新库(或新版本)加进 mcpp-index。两种来源都适用: + - **(a) 第三方上游库** —— 自己没有 mcpp 支持(如 cJSON / Eigen / nlohmann),由本仓以 `compat` 形态适配。 + - **(b) 用户基于 mcpp 开发的库** —— 上游已经是 mcpp 工程(自带 `mcpp.toml`、`mcpp emit xpkg` 产出描述符、自有 release), + 要登记进索引(如 `mcpplibs.*`、`tensorvia-cpu`)。这类多是 **Form A**:描述符只声明元数据 + 下载地址,无需内联构建。 - **不用**:改 mcpp 本体、改 xlings 引擎、纯文档。那些不在本仓。 ## 总流程(12 步) 按顺序做;每步的细节进对应参考文件。建议用 todo 跟踪。 -1. **调研上游**(最关键,决定形态) +1. **调研来源与形态**(最关键,决定模板) + - **先分清来源**:是 (a) 第三方上游库,还是 (b) 用户自己的 mcpp 库? + - (b) 自有 mcpp 库:形态已定(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. **定形态 → 选模板**:见 [package-types.md](package-types.md)。四类:C-source compat / header-only / C++23 module(generated wrapper)/ 外部 Form-A 模块仓。 -3. **建 CN 镜像**:`gtc` 在 gitcode `mcpp-res` org 下建仓 + 发 release,上传**与 GLOBAL 同一个 tarball**(保证 byte-identical → 同 sha)。见 [cn-mirror.md](cn-mirror.md)。 +2. **定形态 → 选模板**:见 [docs/package-types.md](../../../docs/package-types.md)。四类:C-source compat / header-only / C++23 module(generated wrapper)/ 外部 Form-A 模块仓。 +3. **建 CN 镜像**:`gtc` 在 gitcode `mcpp-res` org 下建仓 + 发 release,上传**与 GLOBAL 同一个 tarball**(保证 byte-identical → 同 sha)。**没有 `mcpp-res` 写权限时**:不要写镜像表,直接用 plain-string `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`。 @@ -45,7 +52,7 @@ description: Use when adding a new third-party library/package to the mcpp-index 7. **本地实测**(用与 CI 同版本的 mcpp):见下"本地验证"。必须真跑过 `mcpp build && mcpp run` 绿。 8. **README** 在对应表(mcpplibs 模块库 / 独立模块库 / 第三方 C/C++ 库)加一行。 9. **设计文档** `.agents/docs/-add--plan.md`,记录形态判断、镜像、feature 评估、实测结论、踩坑。 -10. **本地 lint**:模拟 `validate.yml` 的 lint(语法 / 必填字段 / 无前导 v / mirror 检查)。见 [references.md](references.md)。 +10. **本地 lint**:模拟 `validate.yml` 的 lint(语法 / 必填字段 / 无前导 v / mirror 检查)。见 [docs/repository-and-schema.md](../../../docs/repository-and-schema.md)。 11. **分支 → commit → push → PR**(从 `main` 切新分支;别直接推 main)。PR 描述写清形态、镜像、feature、实测。 12. **盯 CI 绿**:`detect` 应只选中本库的 example(`smoke-full-linux`/`portable` 显示 `skipping`),`smoke-examples ()` 绿;`mirror-cn-reachable` 覆盖新 CN url。合并交维护者。 diff --git a/README.md b/README.md index 40f1bdd..c634f81 100644 --- a/README.md +++ b/README.md @@ -22,14 +22,38 @@ mcpp self config --mirror CN # 切到国内镜像(默认走 GLOBAL 上游源) 收录两类包: -- **原生 mcpp 模块库** — 以 C++23 模块发布、`import` 即用(如 `mcpplibs.*`、`nlohmann.json`、`imgui`)。 - 上游多自带 `mcpp.toml`,描述文件只声明元数据与下载地址。 -- **第三方 C/C++ 库(`compat`)** — 上游无 mcpp 支持,在描述文件里内联构建信息:header-only、纯 C 源码、 +- **原生 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 镜像。 -**新增一个包** → 参考 agent skill [`add-mcpp-index-package`](.agents/skills/add-mcpp-index-package/SKILL.md): -完整 SOP —— 四种库形态模板、`gtc` CN 镜像闭环、`features` 门控、本地 + CI 验证。字段规范见 -[mcpp 扩展字段文档](https://github.com/mcpp-community/mcpp/blob/main/docs/04-schema-xpkg-extension.md)。 +### 参考示例(`.lua` 描述符) + +| 形态 | 示例 | +|------|------| +| 原生模块库(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) | + +### 新增一个包 + +照 agent skill [`add-mcpp-index-package`](.agents/skills/add-mcpp-index-package/SKILL.md) 走完整 SOP。 +最快的方式 —— 把下面这段丢给 agent(Claude Code 等),让它**用该 skill** 完成描述文件与全流程: + +```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 绿。 +``` + +详细文档(人 / agent 共用,在 [`docs/`](docs/) 下): + +- [库形态与描述符模板](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) > 开 PR 后 `validate` 自动 lint + 按改动库选跑示例;合入后 `deploy-site` 发布到浏览站。 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..42201f0 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,13 @@ +# mcpp-index 文档 + +给本仓贡献者(人 / agent 共用)的参考文档。新增一个包的**端到端 SOP** 在 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/.agents/skills/add-mcpp-index-package/cn-mirror.md b/docs/cn-mirror.md similarity index 77% rename from .agents/skills/add-mcpp-index-package/cn-mirror.md rename to docs/cn-mirror.md index f7cab0f..26a9fb9 100644 --- a/.agents/skills/add-mcpp-index-package/cn-mirror.md +++ b/docs/cn-mirror.md @@ -9,6 +9,26 @@ - CN 资产公网 URL 约定: `https://gitcode.com/mcpp-res//releases/download//-.` +## 没有 `mcpp-res` 写权限时的回退 + +建镜像需要 gitcode `mcpp-res` org 的写权限(token)。**拿不到时不要硬凑镜像表** —— lint +(`check_mirror_urls.lua`)强制:`url` 一旦写成表,`CN` **必须**是 `https://gitcode.com/mcpp-res/…`, +所以 `{ GLOBAL=上游, CN=上游 }` 会直接挂 lint。正确回退是**用 plain-string 单串 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 在 diff --git a/.agents/skills/add-mcpp-index-package/package-types.md b/docs/package-types.md similarity index 100% rename from .agents/skills/add-mcpp-index-package/package-types.md rename to docs/package-types.md diff --git a/.agents/skills/add-mcpp-index-package/references.md b/docs/repository-and-schema.md similarity index 100% rename from .agents/skills/add-mcpp-index-package/references.md rename to docs/repository-and-schema.md From 04701d57bdc1c8b8803c0b01ff47e9f8944304b8 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Sun, 28 Jun 2026 23:07:07 +0800 Subject: [PATCH 4/4] docs: rewrite README/docs/skill in a formal declarative register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite all prose across README.md, docs/*, and the add-mcpp-index-package skill into declarative, academic-style Chinese: remove colloquial terms (一把梭 / 踩坑 / 丢给 / 硬凑 / 藏不住 …) and decorative emoji (⚠️✅❌📘✓), and reformulate fragments as complete declarative sentences. The red-flag table becomes a "错误做法 / 正确做法" table; section headings are normalized (e.g. "本地 lint 一把梭" → "本地 lint 复现(等价于 CI lint job)", "踩坑" → "注意事项", "CI 兜底" → "CI 保障"). Technical content, commands, code samples, and links are unchanged. --- .../skills/add-mcpp-index-package/SKILL.md | 191 ++++++++++-------- README.md | 63 +++--- docs/README.md | 12 +- docs/cn-mirror.md | 89 ++++---- docs/package-types.md | 91 +++++---- docs/repository-and-schema.md | 87 ++++---- 6 files changed, 293 insertions(+), 240 deletions(-) diff --git a/.agents/skills/add-mcpp-index-package/SKILL.md b/.agents/skills/add-mcpp-index-package/SKILL.md index 03e7e46..c7cc977 100644 --- a/.agents/skills/add-mcpp-index-package/SKILL.md +++ b/.agents/skills/add-mcpp-index-package/SKILL.md @@ -3,82 +3,107 @@ 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 新增一个库(SOP) - -把一个上游库收录进 [`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) —— gtc / gitcode 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 引擎、纯文档。那些不在本仓。 - -## 总流程(12 步) - -按顺序做;每步的细节进对应参考文件。建议用 todo 跟踪。 - -1. **调研来源与形态**(最关键,决定模板) - - **先分清来源**:是 (a) 第三方上游库,还是 (b) 用户自己的 mcpp 库? - - (b) 自有 mcpp 库:形态已定(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-source compat / header-only / C++23 module(generated wrapper)/ 外部 Form-A 模块仓。 -3. **建 CN 镜像**:`gtc` 在 gitcode `mcpp-res` org 下建仓 + 发 release,上传**与 GLOBAL 同一个 tarball**(保证 byte-identical → 同 sha)。**没有 `mcpp-res` 写权限时**:不要写镜像表,直接用 plain-string `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 机制")。只能门控 **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** 在对应表(mcpplibs 模块库 / 独立模块库 / 第三方 C/C++ 库)加一行。 -9. **设计文档** `.agents/docs/-add--plan.md`,记录形态判断、镜像、feature 评估、实测结论、踩坑。 -10. **本地 lint**:模拟 `validate.yml` 的 lint(语法 / 必填字段 / 无前导 v / mirror 检查)。见 [docs/repository-and-schema.md](../../../docs/repository-and-schema.md)。 -11. **分支 → commit → push → PR**(从 `main` 切新分支;别直接推 main)。PR 描述写清形态、镜像、feature、实测。 -12. **盯 CI 绿**:`detect` 应只选中本库的 example(`smoke-full-linux`/`portable` 显示 `skipping`),`smoke-examples ()` 绿;`mirror-cn-reachable` 覆盖新 CN url。合并交维护者。 - -## feature 机制(务必读准) - -mcpp **0.0.68** 的包描述符 `features` 表 **只能门控 `sources`**(其它子字段被 skip;源码核实见 `manifest.cppm` 的 features 解析)。 +# 向 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" }, -- 默认总编 + sources = { "*/core.c" }, -- 默认始终编译 features = { - ["extra"] = { sources = { "*/extra.c" } }, -- 默认排除;features=["extra"] 时编入同一个 lib 目标 + ["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` 或编译找不到),证明门控真生效——不是默认就编进去了。 + +- 消费侧声明:`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`。**用同一版本本地跑**,别用恰好装着的旧版。 +CI 所用 mcpp 版本由 `.github/workflows/validate.yml` 的 `env.MCPP_VERSION` 指定。本地验证应使用同一版本,而非本地 +恰好安装的其它版本。 ```bash MV=$(grep -oP 'MCPP_VERSION:\s*"\K[0-9.]+' .github/workflows/validate.yml) @@ -88,20 +113,24 @@ 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 单独兜 +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`。 -- ❌ 直接 push `main`。✅ 切分支开 PR。 -- 完成前遵循 `verification-before-completion`:**贴出真实命令输出**再说"绿/完成",不要凭感觉。 + +- 输出末尾应包含断言行与 `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 c634f81..a004db2 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,72 @@ # 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` 描述文件。 +本仓收录可被 `mcpp` 直接 `add` 的 C++23 包,既包含 `import` 即用的模块化库,也包含以 `compat` 形态从上游源码或 +头文件构建的第三方 C/C++ 库。每个包对应一个 `pkgs/<首字母>/<包名>.lua` 描述文件。 ## 使用 ```bash mcpp add ftxui@6.1.9 # 添加依赖到 mcpp.toml -mcpp build # 自动拉取源码 + 构建(依赖沿链路自动传递) +mcpp build # 自动拉取源码并构建,依赖沿链路自动传递 -mcpp search # 搜索 / 刷新索引 -mcpp self config --mirror CN # 切到国内镜像(默认走 GLOBAL 上游源) +mcpp search # 搜索并刷新索引 +mcpp self config --mirror CN # 切换至国内镜像,默认使用 GLOBAL 上游源 ``` 完整包列表见 **[在线索引站](https://mcpplibs.github.io/mcpp-index/)**。 ## 包生态与贡献 -收录两类包: +本仓收录两类包: -- **原生 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 镜像。 +- **原生 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 镜像。 ### 参考示例(`.lua` 描述符) | 形态 | 示例 | |------|------| | 原生模块库(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 源码 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) | ### 新增一个包 -照 agent skill [`add-mcpp-index-package`](.agents/skills/add-mcpp-index-package/SKILL.md) 走完整 SOP。 -最快的方式 —— 把下面这段丢给 agent(Claude Code 等),让它**用该 skill** 完成描述文件与全流程: +完整流程定义于 agent skill [`add-mcpp-index-package`](.agents/skills/add-mcpp-index-package/SKILL.md)。可将下列 +指令提供给 agent(如 Claude Code),由其调用该 skill 完成描述文件的编写与全流程: ```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 绿。 +参考本仓 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 通过。 ``` -详细文档(人 / agent 共用,在 [`docs/`](docs/) 下): +细节文档位于 [`docs/`](docs/),供人工与 agent 共同使用: -- [库形态与描述符模板](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) +- [库形态与描述符模板](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)。 -> 开 PR 后 `validate` 自动 lint + 按改动库选跑示例;合入后 `deploy-site` 发布到浏览站。 +> 提交 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) | +| [mcpplibs](https://github.com/mcpplibs) | mcpp 生态的模块化 C++23 库集合 | +| [mcpp-res](https://gitcode.com/mcpp-res) | 包资源的 CN 镜像组织(gitcode) | ## 社区 @@ -73,4 +74,4 @@ mcpp self config --mirror CN # 切到国内镜像(默认走 GLOBAL 上游源) ## License -包描述文件 CC0;各上游库保留其自身许可证。 +包描述文件采用 CC0;各上游库保留其自身许可证。 diff --git a/docs/README.md b/docs/README.md index 42201f0..16233f1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,13 +1,13 @@ # mcpp-index 文档 -给本仓贡献者(人 / agent 共用)的参考文档。新增一个包的**端到端 SOP** 在 agent skill -[`add-mcpp-index-package`](../.agents/skills/add-mcpp-index-package/SKILL.md);下面是各环节的细节参考。 +本目录为面向贡献者的参考文档,供人工与 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、真实案例表 | +| [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 = { … }` 扩展)以上游为准,见 > [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 index 26a9fb9..65c9c90 100644 --- a/docs/cn-mirror.md +++ b/docs/cn-mirror.md @@ -1,84 +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 org **`mcpp-res`**,一库一仓,资产挂在按版本号打的 release 上。 -- **repo slug = 包名去 `compat.` / `mcpplibs.` 前缀**(`compat.eigen` → `eigen`,`compat.nlohmann?` 用 `nlohmann-json` 避免裸 `json` 歧义)。 -- CN 资产公网 URL 约定: +为每个包配备国内下载镜像,可提升 `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` 写权限时的回退 +## 无 `mcpp-res` 写权限时的回退 -建镜像需要 gitcode `mcpp-res` org 的写权限(token)。**拿不到时不要硬凑镜像表** —— lint -(`check_mirror_urls.lua`)强制:`url` 一旦写成表,`CN` **必须**是 `https://gitcode.com/mcpp-res/…`, -所以 `{ GLOBAL=上游, CN=上游 }` 会直接挂 lint。正确回退是**用 plain-string 单串 url**(只填上游 release), -lint 对纯字符串 url 不做镜像约束: +建立镜像需要 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(单串即可) +-- 回退:无 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 不变)。 +- CN 用户将回退至上游源,访问较慢但功能不受影响。 +- 既有先例:`pkgs/t/tensorvia-cpu.lua`(用户自有 mcpp 库,无 CN 镜像,三平台均使用上游单一字符串 url)。 +- 后续在获得权限、或由维护者补充镜像后,可将该版本的 `url` 改写为 `{ GLOBAL=…, CN=… }` 表(sha256 保持不变)。 -> 想表达「GLOBAL 和 CN 都走上游」就用上面的单串写法,**不要**写成 `{GLOBAL=x, CN=x}` 表(过不了 CN 必须指向 -> gitcode 的 lint)。 +如需表达“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`。 +`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 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 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`。 + +`gtc` 不能创建 org;`mcpp-res` 已存在。如需新建 org,应调用 `POST /api/v5/orgs` 并同时提供 `name` 与 `path` 字段。 ## 标准操作(以 slug=`eigen`、ver=`5.0.1` 为例) ```bash -# 0. 下 GLOBAL 上游 tarball,算 sha256(填进描述符三平台);复算两次确认稳定 +# 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 +# 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 同一个文件 → byte-identical → 同 sha) +# 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 字节一致 +# 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 ✓" +[ "$(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` 所执行)。 -- **gitcode API 限流 = 25 次/分/用户** → 调用间隔 ~3.2s,遇 429 退避。 -- **同名 release 资产不可覆盖**:误传只能网页删 → 命名一次定死(`-.`)。 -- **新仓无分支**:不先 push init,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 保障 -## CI 兜底 +`.github/workflows/validate.yml` 设有两道校验: -`.github/workflows/validate.yml` 两道闸: -- `lint` 里 `tests/check_mirror_urls.lua`:url 写成表时 **GLOBAL+CN 都得有,且 CN 必须指向 gitcode `mcpp-res` 镜像**。 -- `mirror-cn-reachable`:把所有 CN url 抽出来逐个 `curl`,非 200 即失败。 +- `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 index 975cd1a..9e2f440 100644 --- a/docs/package-types.md +++ b/docs/package-types.md @@ -1,38 +1,38 @@ # 库形态与描述符模板 -先判断库属于哪一类,再抄对应模板。所有 `mcpp = {}` 内路径是**相对 verdir 的 GLOB**,前导 `*` 吸收 tarball 的 -`-/` wrap 层;`*` 匹配单段、`**` 跨段(`*/blas/*.cpp` 合法)。 +编写描述符前,应先判定库所属的形态,再选用对应模板。`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. 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) | -公共骨架(`package` 头 + `xpm`),A/B/C 通用: +A、B、C 三类共用的骨架(`package` 头与 `xpm`)如下: ```lua package = { spec = "1", - namespace = "compat", -- compat / nlohmann / mcpplibs / …(决定 import 前缀与依赖 key) - name = "compat.", -- 完整包名;决定 pkgs/<首字母>/ 落点 + namespace = "compat", -- compat / nlohmann / mcpplibs 等,决定 import 前缀与依赖 key + name = "compat.", -- 完整包名,决定 pkgs/<首字母>/ 的落点 description = "…", licenses = {"MIT"}, -- SPDX repo = "https://…", type = "package", - xpm = { -- 三平台都写;纯源码/纯头时三平台同 url+sha256 + 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 = "<算出来>" } }, + sha256 = "<计算所得>" } }, macosx = { ["1.2.3"] = { url = { GLOBAL = "…", CN = "…" }, sha256 = "…" } }, windows = { ["1.2.3"] = { url = { GLOBAL = "…", CN = "…" }, sha256 = "…" } }, }, - mcpp = { … 见下各形态 … }, + mcpp = { … 见下文各形态 … }, } ``` @@ -40,64 +40,67 @@ package = { ## A. C 源码 compat(`compat.cjson` / `compat.zlib`) -把 C 源编成 lib,头经 `include_dirs` 暴露。可选组件走 `features` 门控。 +将 C 源码编译为 lib,头文件经 `include_dirs` 暴露,可选组件由 `features` 门控。 ```lua mcpp = { - language = "c++23", -- 与既有 compat 对齐;真正的 C 由 c_standard 决定 + language = "c++23", -- 与既有 compat 对齐;实际的 C 行为由 c_standard 决定 import_std = false, c_standard = "c99", -- 或 c11 - include_dirs = { "*" }, -- 暴露顶层头(*/foo.h) - sources = { "*/cJSON.c" }, -- 核心源,总编 + include_dirs = { "*" }, -- 暴露顶层头文件(*/foo.h) + sources = { "*/cJSON.c" }, -- 核心源码,始终编译 targets = { ["cjson"] = { kind = "lib" } }, - features = { -- 可选扩展,默认不编 + features = { -- 可选扩展,默认不编译 ["utils"] = { sources = { "*/cJSON_Utils.c" } }, }, deps = { }, } ``` -要点:多源时逐个列(见 `compat.zlib` 列了 15 个 `.c`),或用 glob;需要配置头时用 `generated_files` 合成 -(zlib 用 `mcpp_generated/include/mcpp_zlib_config.h` + `cflags = {"-include …"}`)。 + +要点:多源码时可逐个列出(`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` 给 mcpp 一个可构建的 lib 目标。 +此类库无可编译源码:由 `include_dirs` 暴露头文件,并加入一个 trivial anchor `.c`,以提供一个可构建的 lib 目标。 ```lua mcpp = { language = "c++23", import_std = false, c_standard = "c11", - include_dirs = { "*" }, -- 或更精确 "*/include" / "*/api" + 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: + -- 若存在额外可编译源码的组件(非纯头),可实现为 source-gated feature: features = { ["blas"] = { sources = { "*/blas/*.cpp", "*/blas/f2c/*.c" } }, -- eigen 实例 }, deps = { }, } ``` -注意:**纯头的可选项藏不住**(共享 include 根)→ 不要硬做 feature;只有"额外可编译源"才门控得了(eigen `blas` 就是 -C++/f2c-C,无 Fortran → 可门控)。 + +注意:纯头形式的可选项无法隐藏(与核心共享 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,别自己猜符号清单**。 +使用户可 `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 易冲突 + import_std = false, -- wrapper 含上游头,启用 import std 易产生冲突 modules = { "nlohmann.json" }, - include_dirs = { "*/single_include" }, -- 让 wrapper 内 #include <…> 可解析 + include_dirs = { "*/single_include" }, -- 使 wrapper 内的 #include <…> 可解析 generated_files = { ["mcpp_generated/nlohmann.json.cppm"] = "module;\n#include \nexport module nlohmann.json;\n…", }, @@ -106,20 +109,23 @@ mcpp = { deps = { }, } ``` -⚠️ **mcpp 段解析器不支持 Lua 长括号 `[[ … ]]`**:`generated_files` 内容必须用双引号字符串 + `\n`/`\"` 转义 -(否则 `malformed mcpp segment`)。消费侧:`import x.y;` 别和文本 `#include ` 混用(GCC modules 冲突), -配 `import std;`。 + +注意: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,而非 inline 的 Form B)。 -新增独立库基本属于另一个仓(如 `mcpplibs/imgui-m`),本仓只登记。照抄 `pkgs/i/imgui.lua`、`pkgs/m/mcpplibs.xpkg.lua` 的写法。 +上游或独立仓库自带 mcpp 描述符,本仓仅充当指针:`mcpp = "<相对或远程路径>"`(Form A,而非内联的 Form B)。新增的 +独立库通常归属于另一仓库(如 `mcpplibs/imgui-m`),本仓只负责登记。写法可参照 `pkgs/i/imgui.lua` 与 +`pkgs/m/mcpplibs.xpkg.lua`。 --- ## 最小工程(`tests/examples//`) -`mcpp.toml`(短依赖 / 长依赖二选一): +`mcpp.toml`(短式依赖与长式依赖二选一): + ```toml [package] name = "-example" @@ -127,12 +133,13 @@ version = "0.1.0" [toolchain] default = "gcc@16.1.0" [indices] -compat = { path = "../../.." } # 指回仓根 → 用本地描述符 +compat = { path = "../../.." } # 指回仓根,以使用本地描述符 [dependencies.compat] = "1.2.3" # 或: = { version = "1.2.3", features = ["…"] } [targets.-example] kind = "bin" -main = "src/main.cpp" # C 库可用 .c +main = "src/main.cpp" # C 库可使用 .c ``` -`src/main.cpp`:做**真断言**并 `return ok ? 0 : 1`(别只打印)。module 库用 `import std; import x.y;`; -header/C 库用文本 `#include`。 + +`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 index b9cf7dd..9e998d5 100644 --- a/docs/repository-and-schema.md +++ b/docs/repository-and-schema.md @@ -1,64 +1,73 @@ -# 参考:仓库结构 / schema / CI / 关键文件 +# 仓库结构、schema、CI 与关键文件 ## 仓库布局 ``` -pkgs//.lua 描述符。 = 完整包名首字母(compat.* → c, nlohmann.json → n, imgui → i) -tests/examples// 每库最小工程( = 名去 compat./mcpplibs. 前缀) +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 index 列表(三张表:mcpplibs 模块库 / 独立模块库 / 第三方 C/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 设计文档惯例 -tools/gtc gitcode CLI(见 cn-mirror.md) -.xpkgindex.json 站点配置(标题/链接/install 模板),一般不动 +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 在 ~line 172)。 +- 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`。 +`package` 必填字段:`spec`、`namespace`、`name`、`description`、`licenses`、`repo`、`type="package"`、`xpm`、`mcpp`。 -`xpm..`: -- `url`:字符串 或 `{ GLOBAL=…, CN=… }`(本仓一律用表)。 -- `sha256`:必填,= 实际下载字节。 +`xpm..<裸版本>`: + +- `url`:字符串,或 `{ GLOBAL=…, CN=… }` 表(本仓统一使用表形式)。 +- `sha256`:必填,等于实际下载字节的摘要。 `mcpp`(常用键): + | 键 | 说明 | |---|---| -| `language` | 一般 `"c++23"` | -| `import_std` | 多数 `false` | -| `c_standard` | C 源:`"c99"`/`"c11"` | +| `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` | 追加到对应规则 | +| `generated_files` | `{ ["相对路径"]="内容字符串" }`;不支持 `[[…]]`,须以 `\n`、`\"` 转义 | +| `sources` | glob 列表,编入 lib 的源码 | +| `cflags` / `cxxflags` / `ldflags` | 追加至对应规则 | | `targets` | `{ ["name"]={ kind="lib"/"bin", main=…, soname=… } }` | -| `features` | `{ ["f"]={ sources={…} } }` —— **只认 sources** | -| `deps` | `{ ["ns.name"]="ver" }` 扁平/点号式 | +| `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`。 +- 触发条件: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) +## 本地 lint 复现(等价于 CI lint job) ```bash fail=0 @@ -68,19 +77,19 @@ for f in pkgs/*/*.lua; do 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 ✓" +[ $fail -eq 0 ] && echo "ALL LINT PASS" ``` ## 合并后 -`publish-artifact.yml` 在合到 `main` 后自动重发 mcpp-index artifact + 移指针,**无需发 mcpp 版本**。在线浏览: -https://mcpplibs.github.io/mcpp-index/ +`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 源码 + 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` |