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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions .agents/docs/2026-10-16-add-mcr-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# 新增 mcr 收录(Form A,模块库)

## 1. 来源与形态

- 收录 [yizhinailong/mcr](https://github.com/yizhinailong/mcr) 0.1.5,即上游最新 tag
`v0.1.5`(在此之前为 `v0.1.3`、`v0.1.4`)。
- 形态为 **A**:上游仓自带 `mcpp.toml`(`[lib] path = "src/mcr.cppm"`)与
`build.mcpp`,是完整的 mcpp 工程,而不是需要本仓以 `compat` 形态适配的第三方库。
因此描述符只登记身份与下载地址,构建交给上游 `mcpp.toml`
(`mcpp = "*/mcpp.toml"`,`gzj-creator.galay` / `marzer.tomlplusplus` 同形);
`mcpp xpkg parse` 也自报 `form A — no mcpp segment`。
- **GLOBAL 必须是 tag 归档而不是 release 资产**:GitHub API 列出 3 个 release
(`v0.1.3/4/5`),`assets` 全为空 —— 上游的 `version-tag.yml` 只打 tag 并触发 CI,
不做 `mcpp pack`、不发布 tarball。归档
`https://github.com/yizhinailong/mcr/archive/refs/tags/v0.1.5.tar.gz`
SHA-256 `bd55e9dc19b620d7dfb89d20fd4a6b1ab9cf947fe872dc536dee53b4e869f8f5`
(248 803 字节),两次下载一致;顶层包装层为 `mcr-0.1.5/`,由前导 `*/` 吞掉。
- License MIT(`LICENSE` 首行 `MIT License` / `Copyright (c) 2026 yizhinailong`)。
- 上游依赖 `compat.curl` 8.21.0 与 `nlohmann.json` 3.12.0(见其 `mcpp.lock`),两者
本仓都已在索引中;`compat.openssl` 3.5.1 亦已存在(仅 linux/macosx 需要)。

## 2. 描述符设计

- 身份 `yizhinailong:mcr`,文件 `pkgs/y/yizhinailong.mcr.lua` —— 目录取**完整包名**
`yizhinailong.mcr` 的首字母(`compat.rapidcsv` → `pkgs/c/`、`nlohmann.json` →
`pkgs/n/` 同理,`docs/repository-and-schema.md` §Repository layout 的规则)。
- **命名空间由来**:mcr 自己的 `mcpp.toml` 只写 `name = "mcr"`,不带命名空间;索引侧
身份由描述符给,取仓主 `yizhinailong`。这与既有先例一致 ——
`tensorvia-cpu` 的上游同样无命名空间,描述符补 `namespace = "aimol"`;
`galay` 补 `gzj-creator`。消费侧因此写作
`[dependencies.yizhinailong] mcr = "0.1.5"`。
- 三平台共用同一份源码归档(纯源码,无平台差异),`xpm` 的 linux/macosx/windows
三个块 url 与 sha256 全等。
- **平台差异不内联进描述符**:mcr 自己的 manifest 已按平台分支
(`[target.linux|macosx.dependencies.compat] openssl` +
`defines = ["MCR_SSL_CTX_OPENSSL"]`,Windows 走 Schannel)。Form A 的要点正是
这一决定仍归上游所有,描述符不重复表达,也就不会与上游漂移。
- **CN 镜像**:本次没有 `mcpp-res` 写权限,按 `docs/cn-mirror.md` 的回退路径写
**纯字符串 url**(`gzj-creator.galay` 同形)。`tests/check_mirror_urls.lua` 明确
「plain url: fine」,只对表形 url 校验 GLOBAL/CN 成对。日后补镜像只需把 `url`
改写成 `{ GLOBAL = …, CN = … }`,sha256 不变。

## 3. Feature 评估

无。feature 机制只对 **Form B**(本仓内联构建)有意义 —— 它门控的是描述符 `mcpp`
段里的 `sources`。Form A 的可选组件由上游 manifest 自己的 `features` 表达,消费者
直接写 `features = [...]` 即可,本仓无需(也无法)再门控一层。

## 4. 测试与验证

`tests/examples/mcr` 是公开 Form A 消费测试。成员级 `[indices]` 只声明
`yizhinailong`(成员级表**替换**而非合并仓根的 `compat`,这是硬约束:两个项目级
index repo 会让每次查找歧义,mcpp#238),因此 mcr 自带的 `compat.*` 依赖故意从
**已发布的远端索引**解析,新命名空间才解析到本 checkout。

测试刻意**离线**:活体 HTTP 往返需要本地服务与 curl 运行时,不适合放进索引成员。
断言覆盖离线可观测的全部面:

- `mcr::VERSION` / `VERSION_MAJOR|MINOR|PATCH` —— 该模块由 mcr **自己的
`build.mcpp`** 从 `mcpp.toml` 生成,断言它等于 `0.1.5` 即证明构建钩子确实跑过、
且生成模块进了 lib 目标(这是本次最值得盯的一环,见下);
- `mcr::status` 的五个 `constexpr` 分类器(`static_assert`)+ 具名状态码常量;
- `mcr::Url` 与 `mcr::Header` 的大小写无关查找(`CaseInsensitiveCompare`);
- `mcr::JsonBody` 构造期取紧凑序列化、与原值往返相等;
- `mcr::Response::TryJson()` 在成功时给出值、在非法 JSON 时给出 `JsonError`,而
`Json()` 对同一输入抛 `mcr::Json::exception`。

## 5. 注意事项与风险

- **`build.mcpp` 是本次唯一非平凡风险点**。上游的构建钩子 `import mcpp;`、调用
`mcpp::manifest_dir()` / `mcpp::out_dir()` / `mcpp::generated()`,并生成
`mcr_version.cppm`(其 global module fragment 里 `#include <curl/curlver.h>`),
因此构建程序需要 host 侧 `mcpp` 模块可达。既有 Form A 案例
(`galay` / `tinyhttps` / `tensorvia-cpu`)都没有 `build.mcpp`,本条无先例可依;
测试里对 `mcr::VERSION` 的断言就是为它设的探针。
- **上游只对 Windows 有 CI**。mcr 的 README 与 `.github/workflows/windows-ci.yml`
只覆盖 Windows(LLVM 22.1.8 + MSVC);linux/macosx 的 OpenSSL 路径由上游 manifest
声明但未被上游验证。描述符按上游 manifest 的意图声明三平台,若 linux/macos 腿在
CI 暴露问题,退路是像 `gzj-creator.galay` 那样先只声明已验证的平台。
- 上游 Windows 配置使用 Schannel,`compat.openssl` 无 Windows 构建 —— 这一点上游
manifest 已经处理好,本仓无需介入。

### 验证结论

- `mcpp xpkg parse pkgs/y/yizhinailong.mcr.lua` → `parse OK`(三平台 0.1.5,
mcpp 自报 `form A`)。
- 冷验证 `mcpp test -p mcr`(清掉 `tests/examples/mcr/{target,.mcpp}`)结果见 commit/PR
描述;关键中间证据:本地索引能解析并下载 —— 日志出现
`Workspace building member 'mcr-tests'` 与 `Downloading yizhinailong.mcr v0.1.5`。
- 本机缺 `lua5.4` 与 `bash`,`tests/check_*.lua` 与 `tests/run_members.sh` 无法本地
复现,交由 CI 的 `lint` 与 `workspace` 覆盖;本地已按 `check_mirror_urls.lua` /
`check_cross_package_refs.lua` 的规则逐条核对(纯字符串 url 合法、无 `pkginfo.*`
跨包引用)。本机 mcpp 为 2026.10.11.1,新于 CI pin 的 2026.10.1.2,故本地跑绿
不等于 CI 跑绿。
40 changes: 40 additions & 0 deletions .agents/docs/2026-10-16-update-compat-imgui-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Update compat:imgui to 1.93.0

## Scope and source

- Upstream: <https://github.com/ocornut/imgui/releases/tag/v1.93.0>, released 2026-10-14.
- Add `1.93.0` and `1.93.0-docking` to Linux, macOS and Windows; retain both 1.92.8 entries.
- Keep the existing Form B recipe: four core C++ sources, public headers and backend include directory.
- Update the `imgui` and `imgui-window` example dependencies to `1.93.0`.
- The separate `ocornut:imgui` module package is outside this update.

## Archives and mirrors

The GitHub tag archives were downloaded and each SHA-256 was calculated twice:

| Version | SHA-256 |
| --- | --- |
| 1.93.0 | `f7bf6bc76e5d79d40d751096663e6c5d18daf08129dd52e7f7b09e4251c8eeee` |
| 1.93.0-docking | `746c265540bd3aa109570f29492ef4d8f5b421dd9fd0049c35ca35f21496f1a5` |

No GitCode configuration or token is available in this environment. The new entries use plain upstream URLs,
as allowed by `docs/zh/cn-mirror.md`; the existing 1.92.8 mirror entries are retained.

## Recipe and compatibility

There are no new sources to gate behind a feature. Docking remains an upstream archive variant.
The existing rendering test exercises context creation, font atlas generation and valid draw data without a display.
1.93.0 changes custom draw-list rendering; see upstream's release notes for stroke and pixel-alignment changes.

## Validation

- Lua syntax, mirror URL rules, package identity, reserved namespaces, platform version parity and duplicate-version checks passed.
- `mcpp xpkg parse pkgs/c/compat.imgui.lua` passed with both the CI-pinned mcpp 2026.10.1.2 and local mcpp 2026.10.11.1,
listing both new versions on all three platforms.
- `mcpp test -p imgui --cache local` passed on Windows with the CI-pinned mcpp 2026.10.1.2 and LLVM 23.1.3 / system MSVC:
the 1.93.0 core sources were recompiled, and the rendering test passed (one test, zero failures).
- The verified `1.93.0-docking` archive's four core sources were compiled directly with `clang++ -std=c++23`, together
with the existing `tests/examples/imgui/tests/render.cpp`. The resulting executable passed (exit code 0).
A separate mcpp docking test was stopped after spending over three minutes waiting on another archive download;
the docking check therefore covers the downloaded source build and rendering, not a completed mcpp install.
- `imgui-window` is Linux-only; Windows does not exercise its backend build or window rendering.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ Additional example: [`compat.etl`](pkgs/c/compat.etl.lua) — Header-only; [`con
Additional example: [`compat.richdem`](pkgs/c/compat.richdem.lua) — C++ sources, serial terrain analysis; [`consumer test`](tests/examples/richdem/mcpp.toml).
Additional example: [`compat.fmt`](pkgs/c/compat.fmt.lua) — {fmt} in header form (`#include <fmt/format.h>`; the non-module sibling of `fmtlib.fmt`), its C API behind a `c-api` feature; [`consumer test`](tests/examples/fmt/mcpp.toml), [`feature test`](tests/examples/fmt-c/mcpp.toml).
Additional example: [`compat.soci`](pkgs/c/compat.soci.lua) — C++ database API, with the SQLite3 backend compiled in and the engine taken from `compat.sqlite3`; [`consumer test`](tests/examples/soci/mcpp.toml).
Additional example: [`compat.imgui`](pkgs/c/compat.imgui.lua) — Dear ImGui 1.93.0 core sources, including the docking variant; [`headless test`](tests/examples/imgui/mcpp.toml), [`GLFW/OpenGL3 backend test`](tests/examples/imgui-window/mcpp.toml).
Additional example: [`yizhinailong.mcr`](pkgs/y/yizhinailong.mcr.lua) — Form A module library: libcurl-based C++23 HTTP client with sync, async, coroutine and batch requests, built from the upstream's own `mcpp.toml`; [`consumer test`](tests/examples/mcr/mcpp.toml).

## Documentation

Expand Down
2 changes: 2 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ agent(如 Claude Code)即可:
新增示例: [`compat.richdem`](pkgs/c/compat.richdem.lua) — C++ sources, serial terrain analysis; [`消费测试`](tests/examples/richdem/mcpp.toml)。
新增示例: [`compat.fmt`](pkgs/c/compat.fmt.lua) — {fmt} 头文件形态(`#include <fmt/format.h>`,即 `fmtlib.fmt` 的非模块兄弟),C API 由 `c-api` feature 门控; [`消费测试`](tests/examples/fmt/mcpp.toml)、[`feature 测试`](tests/examples/fmt-c/mcpp.toml)。
新增示例: [`compat.soci`](pkgs/c/compat.soci.lua) — C++ 数据库访问层,SQLite3 后端编入同一库,引擎来自 `compat.sqlite3`; [`消费测试`](tests/examples/soci/mcpp.toml)。
示例: [`compat.imgui`](pkgs/c/compat.imgui.lua) — Dear ImGui 1.93.0 核心源码,含 docking 版本; [`无窗口测试`](tests/examples/imgui/mcpp.toml)、[`GLFW/OpenGL3 后端测试`](tests/examples/imgui-window/mcpp.toml)。
新增示例: [`yizhinailong.mcr`](pkgs/y/yizhinailong.mcr.lua) — Form A 模块库:基于 libcurl 的 C++23 HTTP 客户端,支持同步、异步、协程与批量请求,构建由上游自带 `mcpp.toml` 负责; [`消费测试`](tests/examples/mcr/mcpp.toml)。

## 文档

Expand Down
1 change: 1 addition & 0 deletions mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ members = [
"tests/examples/wamr-runtime-features",
"tests/examples/quickjs-ng",
"tests/examples/rapidcsv",
"tests/examples/mcr",
]

# ── The index redirect, hoisted to the workspace root ───────────────────
Expand Down
25 changes: 25 additions & 0 deletions pkgs/c/compat.imgui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ package = {

xpm = {
linux = {
-- No CN mirror credentials: use upstream URLs for the new releases.
["1.93.0"] = {
url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.93.0.tar.gz",
sha256 = "f7bf6bc76e5d79d40d751096663e6c5d18daf08129dd52e7f7b09e4251c8eeee",
},
["1.93.0-docking"] = {
url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.93.0-docking.tar.gz",
sha256 = "746c265540bd3aa109570f29492ef4d8f5b421dd9fd0049c35ca35f21496f1a5",
},
["1.92.8"] = {
url = {
GLOBAL = "https://github.com/ocornut/imgui/archive/refs/tags/v1.92.8.tar.gz",
Expand All @@ -25,6 +34,14 @@ package = {
},
},
macosx = {
["1.93.0"] = {
url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.93.0.tar.gz",
sha256 = "f7bf6bc76e5d79d40d751096663e6c5d18daf08129dd52e7f7b09e4251c8eeee",
},
["1.93.0-docking"] = {
url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.93.0-docking.tar.gz",
sha256 = "746c265540bd3aa109570f29492ef4d8f5b421dd9fd0049c35ca35f21496f1a5",
},
["1.92.8"] = {
url = {
GLOBAL = "https://github.com/ocornut/imgui/archive/refs/tags/v1.92.8.tar.gz",
Expand All @@ -41,6 +58,14 @@ package = {
},
},
windows = {
["1.93.0"] = {
url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.93.0.tar.gz",
sha256 = "f7bf6bc76e5d79d40d751096663e6c5d18daf08129dd52e7f7b09e4251c8eeee",
},
["1.93.0-docking"] = {
url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.93.0-docking.tar.gz",
sha256 = "746c265540bd3aa109570f29492ef4d8f5b421dd9fd0049c35ca35f21496f1a5",
},
["1.92.8"] = {
url = {
GLOBAL = "https://github.com/ocornut/imgui/archive/refs/tags/v1.92.8.tar.gz",
Expand Down
51 changes: 51 additions & 0 deletions pkgs/y/yizhinailong.mcr.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-- Form A descriptor: mcr is an mcpp-native library — its own mcpp.toml and
-- build.mcpp sit at the archive root — so the descriptor carries identity and
-- the download address only, and the build comes from upstream through
-- `mcpp = "*/mcpp.toml"` (the galay / marzer.tomlplusplus shape).
--
-- GLOBAL is the TAG ARCHIVE, not a release tarball: upstream publishes git
-- tags v0.1.3 .. v0.1.5, but all three GitHub releases are empty (no assets),
-- so there is nothing else to point at. The archive wraps as `mcr-0.1.5/`,
-- which is what the leading `*/` absorbs.
--
-- All three platforms share the one source archive. TLS is not inlined here
-- because mcr's OWN manifest already branches it — Schannel on Windows,
-- `compat.openssl` on linux/macosx — and Form A means upstream keeps owning
-- that decision. Its dependencies (compat.curl 8.21.0, nlohmann.json 3.12.0)
-- are both already in this index.
--
-- No mcpp-res mirror is configured locally, so the plain-string GLOBAL url is
-- the documented fallback for CN consumers (docs/cn-mirror.md) until a
-- maintainer creates the mirror; lint accepts this form.
package = {
spec = "1",
namespace = "yizhinailong",
name = "mcr",
description = "Modular C++23 HTTP client on libcurl — sync, async, coroutine and batch requests with JSON support",
licenses = {"MIT"},
repo = "https://github.com/yizhinailong/mcr",
type = "package",

xpm = {
linux = {
["0.1.5"] = {
url = "https://github.com/yizhinailong/mcr/archive/refs/tags/v0.1.5.tar.gz",
sha256 = "bd55e9dc19b620d7dfb89d20fd4a6b1ab9cf947fe872dc536dee53b4e869f8f5",
},
},
macosx = {
["0.1.5"] = {
url = "https://github.com/yizhinailong/mcr/archive/refs/tags/v0.1.5.tar.gz",
sha256 = "bd55e9dc19b620d7dfb89d20fd4a6b1ab9cf947fe872dc536dee53b4e869f8f5",
},
},
windows = {
["0.1.5"] = {
url = "https://github.com/yizhinailong/mcr/archive/refs/tags/v0.1.5.tar.gz",
sha256 = "bd55e9dc19b620d7dfb89d20fd4a6b1ab9cf947fe872dc536dee53b4e869f8f5",
},
},
},

mcpp = "*/mcpp.toml",
}
2 changes: 1 addition & 1 deletion tests/examples/imgui-window/mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name = "imgui-window-tests"
version = "0.1.0"

[target.'cfg(linux)'.dependencies.compat]
imgui = "1.92.8"
imgui = "1.93.0"
glfw = "3.4.0.1"
[target.'cfg(linux)'.build]
ldflags = ["-ldl"]
2 changes: 1 addition & 1 deletion tests/examples/imgui/mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ name = "imgui-tests"
version = "0.1.0"

[dependencies.compat]
imgui = "1.92.8"
imgui = "1.93.0"
18 changes: 18 additions & 0 deletions tests/examples/mcr/mcpp.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Public Form-A consumer for `yizhinailong.mcr`. The package owns its build
# (upstream mcpp.toml + build.mcpp), so this member only proves the descriptor
# resolves and the exported module compiles and links.
#
# The member-level [indices] REPLACES the workspace root's `compat` table
# rather than merging with it, which is the documented hard constraint: two
# project index repos make every lookup ambiguous (mcpp#238). So `compat.*` —
# mcr's own compat.curl / nlohmann.json dependencies — deliberately resolves
# from the published remote index while the new namespace resolves here.
[indices]
yizhinailong = { path = "../../.." }

[package]
name = "mcr-tests"
version = "0.1.0"

[dependencies.yizhinailong]
mcr = "0.1.5"
65 changes: 65 additions & 0 deletions tests/examples/mcr/tests/api.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// yizhinailong.mcr — prove the public module surface compiles, links and
// behaves. A live HTTP round trip is deliberately out of scope: it would need
// a local server plus the curl runtime, neither of which belongs in an index
// member. What is exercised here is everything that is observable offline —
// the generated version module, the status classifiers, the owned option
// types, and the Response JSON parsing path.

import std;
import mcr;

int main() {
// mcr.version is generated by the package's own build.mcpp, read out of
// its mcpp.toml. Asserting on it proves the build hook ran and the
// generated module unit reached the library target.
if (mcr::VERSION != "0.1.5") return 1;
if (mcr::VERSION_MAJOR != 0 || mcr::VERSION_MINOR != 1 || mcr::VERSION_PATCH != 5) return 2;

// Status classification is constexpr and independent of libcurl.
static_assert(mcr::status::is_informational(100));
static_assert(mcr::status::is_success(200));
static_assert(mcr::status::is_redirect(301));
static_assert(mcr::status::is_client_error(404));
static_assert(mcr::status::is_server_error(503));
if (!mcr::status::is_success(mcr::status::HTTP_OK)) return 3;
if (mcr::status::is_success(mcr::status::HTTP_NOT_FOUND)) return 4;

// Url and Header are the owned, cpr-shaped option types. Header lookups
// fold case, which is the property std::map alone would not give.
mcr::Url const url{ "http://127.0.0.1:8080/echo" };
if (url.Str() != "http://127.0.0.1:8080/echo") return 5;

mcr::Header header;
header["Content-Type"] = "application/json";
if (header.find("content-type") == header.end()) return 6;
if (header.at("CONTENT-TYPE") != "application/json") return 7;

// JsonBody owns the compact serialization of a value, taken at construction.
mcr::Json const value{ { "name", "Alice" }, { "enabled", true } };
mcr::JsonBody const body{ value };
if (mcr::Json::parse(body.Str()) != value) return 8;

// Response::TryJson reports a parse failure as a diagnostic rather than
// throwing, while Json() throws and does not check the status code.
mcr::Response response;
response.status_code = mcr::status::HTTP_OK;
response.text = R"({"answer":42})";
auto parsed = response.TryJson();
if (!parsed) return 9;
if (parsed->at("answer").get<int>() != 42) return 10;

response.text = "{ not json";
auto failed = response.TryJson();
if (failed) return 11;
if (failed.error().message.empty()) return 12;

bool threw{ false };
try {
(void)response.Json();
} catch (mcr::Json::exception const&) {
threw = true;
}
if (!threw) return 13;

return 0;
}
Loading