Skip to content

Commit 84ed06e

Browse files
authored
fix(site)+feat(tomlplusplus): 文档站点死链修复;build.mcpp 中可 import tomlplusplus (#518)
* fix(site): 文档死链 —— 补注册 docs、zh 译文、base_url,并加内部链接检查 - .xpkgindex.json:注册 descriptor-examples、openkal-compat(含 zh); repository-and-schema 挂 zh 译文;base_url 改为 https://mcpp.index.xlings.org - site-check:新增 tools/site/check_links.py,产物内任一内部死链即失败 - site-check 临时 pin xpkgindex 到 openxlings/xpkgindex#10(相对链接回退、 译文 guide 保持语言),合入后改回默认分支 修复 https://mcpp.index.xlings.org/zh/docs/contributing/descriptor-examples.md 等 9 页 23 条 404。 * feat(tomlplusplus): build.mcpp 中也可 import tomlplusplus marzer.tomlplusplus 由 Form B 改为 Form A:mcpp = "*/mcpp.toml",install() 把 mcpp.toml([lib] path 显式声明导出面)与上游 master 的 src/modules/tomlplusplus.cppm 写入解包后的 v3.4.0 源码树。 - host module 需要 lib root,Form B 无法声明;mcpp 编译 host module 不带包的 include_dirs,模块单元改为相对自身 include 头文件(mcpp-community/mcpp#797) - 各平台 revision = 1,旧 Form B payload 自动重装(实测迁移通过) - 新成员 tests/examples/marzer.tomlplusplus-build-mcpp:build.mcpp 解析 build-config.toml 并注入 define;与项目侧测试分开(同包双角色 bug,见 #797) * docs(agents): 站点死链与 Form B host-module 分析/方案 * test(tomlplusplus): 项目侧成员注明 build.mcpp 用法的兄弟成员 同时让 CI 选中该成员:描述符变更按 mcpp.toml 中出现 'marzer.tomlplusplus' 字面量选成员,而 [dependencies.marzer] 写法不含该字面量。 * ci(site-check): xpkgindex#10 已合入,改回默认分支
1 parent bf7e87c commit 84ed06e

13 files changed

Lines changed: 522 additions & 47 deletions

File tree

‎.agents/docs/2026-10-11-site-doc-links-and-formb-host-module-plan.md‎

Lines changed: 261 additions & 0 deletions
Large diffs are not rendered by default.

‎.github/workflows/site-check.yml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ on:
1515
- '.xpkgindex.json'
1616
- '.xpkgindex/**'
1717
- 'docs/**'
18+
- 'tools/site/**'
1819
- '.github/workflows/site-check.yml'
1920
workflow_dispatch:
2021

@@ -58,6 +59,13 @@ jobs:
5859
test -s "/tmp/site/$f" || { echo "::error::missing $f"; exit 1; }
5960
done
6061
62+
- name: Every internal link resolves
63+
# A guide links repository files, the templates link pages, the plugin
64+
# links packages; a dead one fails here whichever layer produced it.
65+
# This is what let /zh/docs/contributing/descriptor-examples.md ship as
66+
# a 404.
67+
run: python3 tools/site/check_links.py /tmp/site
68+
6169
- uses: actions/upload-artifact@v4
6270
if: always()
6371
with:

‎.xpkgindex.json‎

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
}
9494
]
9595
},
96-
"base_url": "https://mcpplibs.github.io/mcpp-index",
96+
"base_url": "https://mcpp.index.xlings.org",
9797
"languages": [
9898
"en",
9999
"zh",
@@ -169,6 +169,18 @@
169169
"zh": "docs/zh/package-types.md"
170170
}
171171
},
172+
{
173+
"slug": "descriptor-examples",
174+
"title": {
175+
"en": "Descriptor examples",
176+
"zh": "描述符示例总览",
177+
"zh-Hant": "描述符範例總覽"
178+
},
179+
"path": "docs/descriptor-examples.md",
180+
"translations": {
181+
"zh": "docs/zh/descriptor-examples.md"
182+
}
183+
},
172184
{
173185
"slug": "cn-mirror",
174186
"title": {
@@ -183,8 +195,27 @@
183195
},
184196
{
185197
"slug": "repository-and-schema",
186-
"title": "Repository & schema",
187-
"path": "docs/repository-and-schema.md"
198+
"title": {
199+
"en": "Repository & schema",
200+
"zh": "仓库结构与 schema",
201+
"zh-Hant": "倉庫結構與 schema"
202+
},
203+
"path": "docs/repository-and-schema.md",
204+
"translations": {
205+
"zh": "docs/zh/repository-and-schema.md"
206+
}
207+
},
208+
{
209+
"slug": "openkal-compat",
210+
"title": {
211+
"en": "openkal compatibility",
212+
"zh": "openkal 兼容性",
213+
"zh-Hant": "openkal 相容性"
214+
},
215+
"path": "docs/openkal-compat.md",
216+
"translations": {
217+
"zh": "docs/zh/openkal-compat.md"
218+
}
188219
}
189220
],
190221
"cta": {

‎docs/descriptor-examples.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ in the [root README](../README.md#reference-examples).
4545
| Whole-source direct build (config snapshot + source list, no external build system) | [`compat.ffmpeg`](../pkgs/c/compat.ffmpeg.lua) (2281 TUs including NASM assembly, declared through 28 directory globs) |
4646
| Build-time generator output vendored into the descriptor | [`compat.gmp`](../pkgs/c/compat.gmp.lua) (516 TUs, all three platforms. GMP's build COMPILES AND RUNS seven table generators and substitutes `gmp.h` from `gmp-h.in` — all of it a pure function of limb=64/nail=0, so the outputs are produced once by upstream's own generators and shipped in `generated_files` (~270 KB, of which `trialdivtab.h` is 109 KB). That is what removes the `install()` hook, autotools, and the host compiler its probes needed — and with them the reason windows was deferred, since GMP's generic C only ever needed a GCC-compatible compiler. `generated_files` also carries a one-line forwarding header per source directory, so the package compiles with **no `-I` at all** and `include_dirs` exposes `gmp.h` + `gmpxx.h` rather than GMP's private headers. Verified against a `--disable-assembly` autotools build of the same tarball: identical 598-symbol export set, and GMP's own `make check` passes 177/178 against it) |
4747
| Module layer over a compat source build (external Form-A repo) | [`godotengine.godot-cpp-m`](../pkgs/g/godotengine.godot-cpp-m.lua) (two versions tracking upstream: `10.0.0-rc1` = Godot 4.6, `4.5.0` = Godot 4.5. `import godot_cpp;` re-exports the whole `godot` namespace, ~1800 names GENERATED from the headers rather than curated; the 1022-TU build stays in `compat.godot-cpp`, so the index carries only this descriptor. Macros — `GDCLASS`, `GDREGISTER_CLASS`, `memnew`, `ERR_*` — are the one thing a named module cannot export, so the package ships a side header to include next to the import. It also ships a generated `hashfuncs.hpp` shim — upstream's header minus `static` on two functions whose bodies declare an unnamed union — without which GCC refuses the module interface outright, a hard error no `-W` flag reaches) |
48-
| C++23 module wrapper | [`nlohmann.json`](../pkgs/n/nlohmann.json.lua) · [`marzer.tomlplusplus`](../pkgs/m/marzer.tomlplusplus.lua) · [`neargye.magic_enum`](../pkgs/n/neargye.magic_enum.lua) · [`boost-ext.ut`](../pkgs/b/boost-ext.ut.lua) (upstream's own `include/boost/ut.cppm` reproduced verbatim but for one `__argc`/`__argv` shim that Clang-on-MSVC needs; namespace `boost-ext` since it is NOT an official Boost library) |
48+
| C++23 module wrapper | [`nlohmann.json`](../pkgs/n/nlohmann.json.lua) · [`neargye.magic_enum`](../pkgs/n/neargye.magic_enum.lua) · [`boost-ext.ut`](../pkgs/b/boost-ext.ut.lua) (upstream's own `include/boost/ut.cppm` reproduced verbatim but for one `__argc`/`__argv` shim that Clang-on-MSVC needs; namespace `boost-ext` since it is NOT an official Boost library) |
49+
| C++23 module wrapper importable from `build.mcpp` too | [`marzer.tomlplusplus`](../pkgs/m/marzer.tomlplusplus.lua) (Form A: `mcpp = "*/mcpp.toml"`, and `install()` writes that manifest plus upstream master's `src/modules/tomlplusplus.cppm` into the unpacked v3.4.0 tree. A `build.mcpp` host module (`[build-dependencies] … host-module = true`) needs a lib root, which a Form B table cannot state, so `[lib] path` is written down instead of inferred. The unit includes its header by a path relative to itself, because mcpp compiles a host module without the package's `include_dirs` ([mcpp#797](https://github.com/mcpp-community/mcpp/issues/797)). Tested both ways: `tests/examples/marzer.tomlplusplus` imports it from the project, `marzer.tomlplusplus-build-mcpp` from `build.mcpp`) |
4950
| C++23 module, upstream's own unit | [`khronos.vulkan-hpp`](../pkgs/k/khronos.vulkan-hpp.lua) (Vulkan-Hpp 1.4.357.0 — Khronos generates `vulkan.cppm` / `vulkan_video.cppm` into every Vulkan-Headers release, so `sources` names the two units and NOTHING is authored here; the payload is the same tarball, URL and sha256 as `compat.vulkan-headers`, which is what makes the module and the headers it includes impossible to skew. `import_std = true` is forced by the unit's own unconditional `export import std;`. No `include_dirs`: the headers arrive with the `compat.vulkan` dependency, which is also what satisfies the STATIC dispatcher's direct calls at link — depending on headers alone gives a package that compiles and then fails at every consumer's link. Module names stay upstream's `vulkan` / `vulkan_video`, never `khronos.vulkan`. The second unit `import`s the first and mcpp orders the pair from the scan, which `tests/examples/vulkan-hpp-module/tests/video.cpp` is the regression for) |
5051
| C++23 module, upstream's CPU partitions | [`taskflow.taskflow`](../pkgs/t/taskflow.taskflow.lua) (Taskflow 4.1.0, `import tf;`; reuses the four upstream CPU module units and omits the competing CUDA entry point. The checked install hook removes two nonexistent exports, moves the umbrella include/version export into core and imports core first for GCC, and supplies `<algorithm>` to utility for libc++. Only three module files are patched; headers and scheduler implementation stay upstream. No fork; consumers use `tf::version()` because macros are not exported) |
5152
| C++23 module, upstream asynchronous logging | [`odygrd.quill`](../pkgs/o/odygrd.quill.lua) (Quill 13.0.0, upstream experimental `quill` module; the checked install hook generates `.cppm` from `src/quill.cc`, guards x86 intrinsics by target architecture and includes Apple Mach headers in the global module fragment. Consumers use `import std; import quill;` and the macro-free API, or define `QUILL_USE_MODULE` and include `quill/LogMacros.h` for logging macros. Bundled fmt needs no separate dependency; Linux links with `-pthread`. Multi-TU logger identity, worker-thread output, formatting and filtering are tested) |

‎docs/zh/descriptor-examples.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
| 全源码直编(config 快照 + 源列表,零外部构建系统) | [`compat.ffmpeg`](../../pkgs/c/compat.ffmpeg.lua)(2281 TU 含 NASM 汇编,28 个目录 glob 声明) |
4444
| 构建期生成器产物内联进描述符 | [`compat.gmp`](../../pkgs/c/compat.gmp.lua)(516 TU,三平台齐全。GMP 的构建要**编译并运行**七个表生成器,还要把 `gmp-h.in` substitute 成 `gmp.h` —— 这些都只是 limb=64/nail=0 的纯函数,故用上游自己的生成器跑一次,产物写进 `generated_files`(约 270 KB,其中 `trialdivtab.h` 占 109 KB)。这一步换掉的是 `install()` 钩子、autotools 以及其探针所需的宿主编译器,连带解掉 windows 推迟的理由 —— GMP 的通用 C 内核从来只要一个 GCC 兼容编译器。`generated_files` 里还按源码目录各放一个一行转发头,于是整包编译**不需要任何 `-I`**,`include_dirs` 只暴露 `gmp.h` + `gmpxx.h`,而不是 GMP 的私有头。与同一 tarball 的 `--disable-assembly` autotools 构建对拍:导出符号 598 个完全一致,上游自带 `make check` 对本产物 177/178 通过) |
4545
| 模块层叠在 compat 源码构建之上(外部 Form-A 仓) | [`godotengine.godot-cpp-m`](../../pkgs/g/godotengine.godot-cpp-m.lua)(两个版本与上游对齐:`10.0.0-rc1` 对应 Godot 4.6,`4.5.0` 对应 Godot 4.5。`import godot_cpp;` 重导出整个 `godot` 命名空间,约 1800 个名字由头文件**生成**而非手工罗列;1022 个 TU 的构建留在 `compat.godot-cpp`,索引侧只留这一个描述符。宏 —— `GDCLASS`、`GDREGISTER_CLASS`、`memnew`、`ERR_*` —— 是具名模块唯一带不走的东西,故包内附一个与 import 并排包含的侧头文件。另外还带一份生成的 `hashfuncs.hpp` 遮蔽头 —— 上游那个头去掉两个函数的 `static`(它们体内声明了匿名 union)—— 否则 GCC 直接拒绝该模块接口,且是任何 `-W` 开关都够不到的硬错误) |
46-
| C++23 module wrapper | [`nlohmann.json`](../../pkgs/n/nlohmann.json.lua) · [`marzer.tomlplusplus`](../../pkgs/m/marzer.tomlplusplus.lua) · [`neargye.magic_enum`](../../pkgs/n/neargye.magic_enum.lua) · [`boost-ext.ut`](../../pkgs/b/boost-ext.ut.lua)(逐字复用上游自带的 `include/boost/ut.cppm`,仅加一处 Clang-on-MSVC 需要的 `__argc`/`__argv` shim;命名空间取 `boost-ext`,因其并非 boost 官方库) |
46+
| C++23 module wrapper | [`nlohmann.json`](../../pkgs/n/nlohmann.json.lua) · [`neargye.magic_enum`](../../pkgs/n/neargye.magic_enum.lua) · [`boost-ext.ut`](../../pkgs/b/boost-ext.ut.lua)(逐字复用上游自带的 `include/boost/ut.cppm`,仅加一处 Clang-on-MSVC 需要的 `__argc`/`__argv` shim;命名空间取 `boost-ext`,因其并非 boost 官方库) |
47+
| 也能在 `build.mcpp` 中 import 的 C++23 module wrapper | [`marzer.tomlplusplus`](../../pkgs/m/marzer.tomlplusplus.lua)(Form A:`mcpp = "*/mcpp.toml"`,由 `install()` 把这份清单和上游 master 的 `src/modules/tomlplusplus.cppm` 写进解包后的 v3.4.0 源码树。`build.mcpp` 的 host module(`[build-dependencies] … host-module = true`)需要 lib root,而 Form B 表无法声明它,所以显式写 `[lib] path`,不做推导。模块单元按相对自身的路径 include 头文件,因为 mcpp 编译 host module 时不带包的 `include_dirs`([mcpp#797](https://github.com/mcpp-community/mcpp/issues/797))。两种用法都有测试:`tests/examples/marzer.tomlplusplus` 在项目里 import,`marzer.tomlplusplus-build-mcpp` 在 `build.mcpp` 里 import) |
4748
| C++23 module,上游自带单元 | [`khronos.vulkan-hpp`](../../pkgs/k/khronos.vulkan-hpp.lua)(Vulkan-Hpp 1.4.357.0 —— Khronos 把 `vulkan.cppm` / `vulkan_video.cppm` 生成进每个 Vulkan-Headers release,所以 `sources` 点名这两个单元即可,本仓**不写一行**包装体;载荷与 `compat.vulkan-headers` 是同一份 tarball、同一个 URL 与 sha256,这让模块与它 include 的头不可能错配。`import_std = true` 由单元自身无条件的 `export import std;` 决定。不声明 `include_dirs`:头随 `compat.vulkan` 依赖到达,而该依赖同时满足静态 dispatcher 在链接期的直接调用 —— 只依赖头会得到一个「能编译、每个消费者都链接失败」的包。模块名保持上游的 `vulkan` / `vulkan_video`,绝不写成 `khronos.vulkan`。第二个单元 `import` 第一个,顺序由 mcpp 扫描决定,`tests/examples/vulkan-hpp-module/tests/video.cpp` 就是这条的回归)|
4849
| C++23 module,上游 CPU 分区 | [`taskflow.taskflow`](../../pkgs/t/taskflow.taskflow.lua)(Taskflow 4.1.0,`import tf;`;复用上游四个 CPU 模块单元,排除提供同名主模块的 CUDA 入口。安装钩子逐项校验匹配次数:移除两个不存在的导出,将总头文件及版本导出移至 core 并优先导入 core 以兼容 GCC,为 utility 补 `<algorithm>` 以兼容 libc++。仅适配三个模块文件,头文件和调度实现保持上游原样,无独立 fork;宏不随模块导出,版本查询使用 `tf::version()`) |
4950
| C++23 module,上游异步日志 | [`odygrd.quill`](../../pkgs/o/odygrd.quill.lua)(Quill 13.0.0,上游实验性 `quill` 模块;安装钩子以 `src/quill.cc` 生成 `.cppm`,精确适配 x86 intrinsic 的架构条件与 Apple Mach 头的全局模块归属。消费者使用 `import std; import quill;` 和无宏 API,或定义 `QUILL_USE_MODULE` 并包含 `quill/LogMacros.h` 使用日志宏。自带 fmt,无需额外依赖;Linux 链接使用 `-pthread`。测试覆盖多 TU logger 身份、工作线程输出、格式化和过滤) |

‎mcpp.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ members = [
7474
"tests/examples/imgui-window",
7575
"tests/examples/jwt-cpp",
7676
"tests/examples/marzer.tomlplusplus",
77+
"tests/examples/marzer.tomlplusplus-build-mcpp",
7778
"tests/examples/mcpp-plugins",
7879
"tests/examples/mio",
7980
"tests/examples/muduo",

0 commit comments

Comments
 (0)