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
100 changes: 100 additions & 0 deletions .agents/docs/2026-08-09-add-gmp-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# 新增 GMP 收录(compat,install() 驱动构建)+ linux/macOS 方案

**日期**: 2026-08-09
**本仓**: `mcpplibs/mcpp-index`
**issue**: [#171 增加libgmp科学库](https://github.com/mcpplibs/mcpp-index/issues/171)(open,无 assignee/评论)
**目标**: 收录 GNU GMP 6.3.0 为 `compat.gmp`,用户 `#include <gmp.h>` 开箱即用,链接静态 `libgmp.a`。

---

## 1. 上游调研与形态判定

- 最新发布:**6.3.0**(2023-07-30;2026 年仍为最新,ftp.gnu.org 仅有 6.3.0)。GNU 官方 tarball 自带
`configure`,**不可用 GitHub snapshot**(缺 configure)。
GLOBAL = `https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.gz`,sha256(两次计算一致)
`e56fd59d76810932a0555aa15a14b61c16bed66110d3c75cc2ac49ddaa9ab24c`。
- 许可证:GMP 双许可 **LGPL-3.0-or-later OR GPL-2.0-or-later**(tarball README 声明),描述符取宽松侧
`LGPL-3.0-or-later`。
- 形态:**autotools 工程**(configure 在构建期生成 `gmp.h`/`config.h`/`gmp-mparam.h`/汇编选择),不属于
「列出 .c 文件」的直编形态 → 采用与 `compat.openblas`(Make)、`compat.openssl`(Perl Configure + Make)
相同的 **xpkg `install()` 钩子**模式:钩子跑上游 `configure && make && make install`,把 `libgmp.a` +
`include/gmp.h` 铺进 install 目录,再 emit anchor TU 触发 mcpp 构建。

## 2. 描述符设计(pkgs/c/compat.gmp.lua)

- 身份:`namespace = "compat"`, `name = "gmp"` → `pkgs/c/`(完整包名首字母)。
- `mcpp` 段:anchor 源 `mcpp_gmp_anchor.c`(由 install() 生成,非 generated_files),`targets.gmp = lib`,
`include_dirs = {"include"}`,ldflags:linux `-Llib -l:libgmp.a -lm`(libgmp 的 mpf 层用 libm;glibc 不带)、
macosx `-Llib -lgmp`(ld64 无 `-l:`;libSystem 已含 libm)。
- configure 参数:`--disable-shared --enable-static --disable-assembly` + `--prefix=<install_dir>`
`--libdir=<install_dir>/lib`。
- **`--disable-assembly`**:通用 C 内核。与 openblas `TARGET=GENERIC` 同一取舍 —— 可移植、可复现优先,
牺牲手写汇编加速(后续可逐平台重开;mcpp feature 表无法携带 configure 标志,故这是构建期决策)。
- **`--libdir` 必须绝对路径**:GMP configure 拒绝相对值(`expected an absolute directory name`),
与 OpenSSL 不同 —— 首版踩坑,已修复并注释。
- 平台:linux + macosx(install() 内用 host cc 构建);**windows 推迟**(见 §4)。
- 构建期依赖:linux `xim:make@latest`(GNU make);macosx 无(make 回退 PATH —— macOS 自带 GNU Make 3.81 满足
GMP 的 >=3.80 要求)。
- **编译器用宿主 cc**(linux `/usr/bin/gcc`、macOS `/usr/bin/cc`),不用 xim payload 工具链:
- macOS 与 openssl 一致:xim llvm 无 macOS SDK,钉 Apple 自带驱动。
- linux 与 openssl **不同**且更严:openssl 的 Configure 只写 Makefile 从不运行可执行文件,所以 payload
glibc 的 `--sysroot/-B/-L` 足够;但 GMP 的 configure 会**编译并运行** ABI 探针程序,`make` 还要运行
gen-bases/gen-fib/gen-psqr 等构建工具 —— 链接到 xim glibc payload 的这类二进制在本钩子环境里
**无法运行**,configure 报 `could not find a working compiler`(2026-08-09 linux CI 实测)。
宿主 gcc 的探针/工具直接跑宿主 glibc,静态库的 glibc/libm 符号由消费端工具链**更新的** payload glibc
(2.44 > 宿主 2.39)在最终链接时满足 —— 与 openssl macOS 腿(Apple clang 构建、xim llvm 消费)同一模型。

## 3. 镜像决策

当前无 `mcpp-res` 写权限(gtc 登录为维护者 Sunrisepeak,不擅自发布外部资源),故按 docs/zh/cn-mirror.md
回退:**纯字符串 url**(lint 合规,CN 用户回退上游 ftp.gnu.org)。维护者后续可改写为
`{ GLOBAL=…, CN=… }`(sha256 不变)。

## 4. Windows 推迟

GMP **无官方 MSVC 构建路径,也无官方预编译二进制**(vcpkg 在 Windows 用 MPIR fork/MinGW)。与
`compat.openssl` 现状一致:不声明 windows xpm 块,测试成员用 `cfg(linux)`/`cfg(macos)` 门控 + 其他平台
no-op main。

## 5. feature 评估

无可门控组件:GMP 的可选项(汇编、C++ wrapper gmpxx、静态/共享)均由 **configure 标志**控制,而 mcpp
feature 表只能门控 `sources`,不能携带 configure 参数。`--disable-assembly` 作为确定性构建取舍固定写入
钩子,并在描述符注释说明。

## 6. 消费者测试(tests/examples/gmp/)

- `mcpp.toml`:`[target.'cfg(linux)'/'cfg(macos)'.dependencies.compat] gmp = "6.3.0"` + `-DHAVE_GMP=1`;
windows 无依赖。成员名 `gmp`,已注册进根 `mcpp.toml` members。
- `tests/gmp.cpp`(TDD 先写断言):覆盖三层算术,参考值用 Python 独立预计算:
- mpz `mpz_fac_ui(100)` = 158 位十进制串(逐字符比对);
- mpz `mpz_powm_ui(2^1000, mod 12345)` = 5341;
- mpz `mpz_gcd(123456789, 987654321)` = 9;
- mpq `mpq_add(1/2, 1/3)` = 5/6;
- mpf `mpf_sqrt(2)` ∈ (1, 2)。
每项独立 return code,失败可定位。

## 7. 本地验证(mcpp 2026.8.8.2 = validate.yml 当前 pin)

```
RED: mcpp test -p gmp → dependency 'compat.gmp': no package found(包缺失,预期失败)
GREEN: mcpp test -p gmp → gmp ... ok / test result ok. 1 passed; 0 failed
冷跑: 清 target/.mcpp 后完整重跑 45.2s(下载→install() configure+make→anchor→链接→运行)→ 通过
产物: install 目录含 include/gmp.h(84K)、lib/libgmp.a(908K)、mcpp_gmp_anchor.c;链接行
-L…/xpkgs/compat-x-gmp/6.3.0/lib -lgmp(确认用本包静态库,非宿主 libgmp)
lint: lua5.4 语法/必填字段/无前导 v/check_mirror_urls/check_package_name 全过;
mcpp xpkg parse → compat.gmp,linux+macosx 6.3.0,1 source,1 include,target gmp;
check_cross_package_refs、check_platform_version_parity(全仓)过

CI(wellwei/mcpp-index#4,选跑 gmp 成员):
- linux default 首次失败:GMP configure `could not find a working compiler` —— payload glibc 链接的
探针/工具不可运行(见 §2 编译器说明)→ 改宿主 gcc 后重跑。
- 待 linux(gcc+llvm)/macos/windows 全绿后收尾。
```

## 8. 注意事项 / 后续

- windows:需上游 MSVC 路径或维护者提供预编译产物,方可补 xpm.windows 块与钩子分支。
- 汇编:后续可逐平台尝试默认(带 asm)构建,验证 gas 兼容后去掉 `--disable-assembly`;gmpxx(C++ wrapper)
同理可在 `--enable-cxx` 下评估。
- CN 镜像:获得 `mcpp-res` 写权限后,用 gtc 建 `mcpp-res/gmp` 并上传同字节 tarball,url 改表形式。
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Two kinds of packages live here:
| Host runtime adaptation (drivers are not vendored) | [`compat.glx-runtime`](pkgs/c/compat.glx-runtime.lua) · [`compat.vulkan-runtime`](pkgs/c/compat.vulkan-runtime.lua) (mcpp binaries run against a bundled glibc, so a bare-soname `dlopen` never reaches the host drivers; a symlink farm plus `runtime.library_dirs` bridges that. Note the farm holds only versioned sonames — `library_dirs` also joins the link line) |
| Always-on interface define | `CURL_STATICLIB` in [`compat.curl`](pkgs/c/compat.curl.lua): `cflags` is always on but package-private, while a feature's `defines` reaches consumers yet has to be named — `default = { implies = … }` applies unconditionally and happens to give both |
| Multiple majors in one package (shape switches with the version) | [`compat.catch2`](pkgs/c/compat.catch2.lua) (3.x compiles `src/catch2/` into a static library; 2.x goes header-only through `single_include/`) |
| External build system (`install()` builds from source) | [`compat.openblas`](pkgs/c/compat.openblas.lua) (Make) · [`compat.openssl`](pkgs/c/compat.openssl.lua) (Perl Configure + Make, static libssl/libcrypto) |
| External build system (`install()` builds from source) | [`compat.openblas`](pkgs/c/compat.openblas.lua) (Make) · [`compat.openssl`](pkgs/c/compat.openssl.lua) (Perl Configure + Make, static libssl/libcrypto) · [`compat.gmp`](pkgs/c/compat.gmp.lua) (GNU configure + Make, static libgmp — portable generic-C kernels, linux/macOS) |
| 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) |
| 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) |
| 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) |
Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ mcpp self config --mirror CN # 切换至国内镜像,默认使用 GLOBAL 上
| 宿主运行时适配(不 vendor 驱动) | [`compat.glx-runtime`](pkgs/c/compat.glx-runtime.lua) · [`compat.vulkan-runtime`](pkgs/c/compat.vulkan-runtime.lua)(mcpp 产物跑在自带 glibc 下,裸 soname 的 `dlopen` 够不到宿主驱动;用符号链接农场 + `runtime.library_dirs` 打通。注意 farm 只放带版本号的 soname —— `library_dirs` 同时进链接行) |
| 恒开的 interface define | [`compat.curl`](pkgs/c/compat.curl.lua) 的 `CURL_STATICLIB`:`cflags` 恒开但包私有,feature `defines` 可达消费端但需点名 —— `default = { implies = … }` 无条件生效,恰好两者兼得 |
| 单包多 major(形态随版本切换) | [`compat.catch2`](pkgs/c/compat.catch2.lua)(3.x 编 `src/catch2/` 出静态库;2.x 走 `single_include/` header-only) |
| 外部构建系统(`install()` 从源码构建) | [`compat.openblas`](pkgs/c/compat.openblas.lua)(Make) · [`compat.openssl`](pkgs/c/compat.openssl.lua)(Perl Configure + Make,静态 libssl/libcrypto) |
| 外部构建系统(`install()` 从源码构建) | [`compat.openblas`](pkgs/c/compat.openblas.lua)(Make) · [`compat.openssl`](pkgs/c/compat.openssl.lua)(Perl Configure + Make,静态 libssl/libcrypto) · [`compat.gmp`](pkgs/c/compat.gmp.lua)(GNU configure + Make,静态 libgmp —— 可移植通用 C 内核,linux/macOS) |
| 全源码直编(config 快照 + 源列表,零外部构建系统) | [`compat.ffmpeg`](pkgs/c/compat.ffmpeg.lua)(2281 TU 含 NASM 汇编,28 个目录 glob 声明) |
| 模块层叠在 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` 开关都够不到的硬错误) |
| 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 官方库) |
Expand Down
1 change: 1 addition & 0 deletions mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ members = [
"tests/examples/ffmpeg",
"tests/examples/ffmpeg-module",
"tests/examples/fmtlib.fmt",
"tests/examples/gmp",
"tests/examples/godot-cpp",
"tests/examples/godot-cpp-module",
"tests/examples/godot-cpp-module-v10",
Expand Down
Loading
Loading