Skip to content

Commit 2be5893

Browse files
feat: add marzer.tomlplusplus 3.4.0 (official source + CN mirror + generated_files cppm) (#64)
* feat: Add compat.tomlplusplus v3.4.0 Add toml++ as a C++23 module package (import tomlplusplus). - Add pkgs/c/compat.tomlplusplus.lua (module wrapper, MIT) - Add tests/examples/tomlplusplus with import-based test - Declares modules = { "tomlplusplus" } for import support - Uses fork's src/modules/tomlplusplus.cppm as source - SHA256: cefd81c09ae8eade62f254ba0903e4585944cc86e84c320a92116a95cb725862 toml++ is a TOML v1.0.0 config file parser and serializer for C++17+. Fork: https://github.com/yspbwx2010/tomlplusplus @ v3.4.0-mcpp * fix: Add required version field to test mcpp.toml mcpp 0.0.81 (CI version) requires package.version field. Successfully tested with mcpp 0.0.81: - Build: ✓ Downloaded compat.tomlplusplus v3.4.0 from GitHub - Compile: ✓ C++23 module + test binary (5.78s) - Run: ✓ Output 'toml++ test: OK' * refactor(tomlplusplus): official upstream source + CN mirror + generated_files Reworks the package per review feedback (#64 review comment), following the nlohmann.json precedent. - Rename compat.tomlplusplus -> marzer.tomlplusplus (pkgs/m/), matching the `<namespace>.<lib>` convention used by nlohmann.json. - Drop the fork from the trust path: sources now come from upstream's own v3.4.0 release tarball (marzer/tomlplusplus), not yspbwx2010/tomlplusplus. - Add a real CN mirror: gitcode mcpp-res/tomlplusplus @ 3.4.0, byte-identical to the GLOBAL asset (same sha256), replacing the CN=GLOBAL placeholder. - Carry upstream's master-only src/modules/tomlplusplus.cppm via the `generated_files` mechanism as a [==[ ]==] multi-line string, so no fork is needed to obtain the module unit. - Replace the ad-hoc bin example with a `mcpp test --workspace` member under tests/examples/marzer.tomlplusplus/, registered in [workspace].members. The embedded cppm is byte-identical to upstream master except for one dropped line: `using TOML_NAMESPACE::get_line;`. get_line was added to impl/source_region.hpp after v3.4.0 and does not exist in the pinned headers ('get_line' has not been declared in 'toml'), so re-exporting it cannot compile. Documented in the descriptor. * docs(tomlplusplus): README entry + design doc per add-mcpp-index-package skill Steps 8/9 of the repo's add-mcpp-index-package SOP: register the package in the README's 'C++23 module wrapper' row alongside nlohmann.json, and record the shape decision, the CN mirror, the feature evaluation (none — header-only, options are compile-time defines that the features table cannot carry), and the get_line deviation with its negative-verification evidence. --------- Co-authored-by: sunrisepeak <speakshen@163.com>
1 parent af923e5 commit 2be5893

6 files changed

Lines changed: 327 additions & 1 deletion

File tree

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# 收录 toml++(marzer.tomlplusplus)3.4.0
2+
3+
> PR: https://github.com/mcpplibs/mcpp-index/pull/64
4+
> 日期:2026-07-16
5+
> 背景:PR #64 原以 fork 形态提交,按 review 意见([comment](https://github.com/mcpplibs/mcpp-index/pull/64#issuecomment-4907425691))
6+
> 参照 `nlohmann.json` 重做。本文记录形态判定、镜像、验证结论与注意事项。
7+
8+
## 1. 来源与形态判定
9+
10+
- 来源:**(a) 第三方上游库**。上游 [marzer/tomlplusplus](https://github.com/marzer/tomlplusplus) 不提供 mcpp 支持。
11+
- 版本:`v3.4.0`(截至 2026-07-16 的最新 release tag)。
12+
- License:MIT
13+
- 布局:tarball 顶层 wrap 目录为 `tomlplusplus-3.4.0/`,头文件位于 `include/toml++/`,**header-only**
14+
- 形态:**C++23 module(generated wrapper)** —— 与 `nlohmann.json` 同类。
15+
16+
判定依据:release tarball **不含** 任何 `.cppm`:
17+
18+
```console
19+
$ tar tzf tomlplusplus-3.4.0.tar.gz | grep -iE 'cppm|modules'
20+
tomlplusplus-3.4.0/.gitmodules # 仅 git submodule 配置,非模块单元
21+
```
22+
23+
而上游**确实**已编写官方模块单元 `src/modules/tomlplusplus.cppm`(`export module tomlplusplus;`),
24+
但它只存在于 `master` 分支,未进入 v3.4.0。因此采用 `generated_files` 内嵌该 cppm,
25+
基础头文件仍 pin 在可复现的 v3.4.0 release tag —— **信任链上不引入 fork**
26+
27+
## 2. 关键注意事项:master 的 cppm 不能原样内嵌
28+
29+
⚠️ 这是本次收录最容易踩的坑,与 `nlohmann.json`(可 VERBATIM 内嵌)不同。
30+
31+
上游 master 的 cppm 面向 master 的头文件编写,其中一行:
32+
33+
```cpp
34+
using TOML_NAMESPACE::get_line;
35+
```
36+
37+
`get_line` 是 v3.4.0 **之后**才加入 `include/toml++/impl/source_region.hpp` 的。对 pinned 的 v3.4.0 头文件做
38+
负向验证,确认其确实不存在:
39+
40+
```console
41+
$ grep -rn "get_line" tomlplusplus-3.4.0/ # 整个 tarball 无任何命中
42+
43+
$ cat probe.cpp
44+
#include <toml++/toml.hpp>
45+
namespace probe { using toml::get_line; }
46+
int main(){}
47+
48+
$ g++ -std=c++17 -fsyntax-only -Iinclude probe.cpp
49+
probe.cpp:2:31: error: 'get_line' has not been declared in 'toml'
50+
51+
$ # 对照组:同一探针换成 toml::parse,编译通过 —— 证明头文件本身无恙
52+
```
53+
54+
**结论**:内嵌版本删除该行,其余**逐字节一致**(已用 `diff` 对内嵌内容与上游 master 减去该行的结果做校验,结果 IDENTICAL)。
55+
差异已在描述符注释中写明。
56+
57+
**演进条件**:待上游发布 >3.4.0 且随 release 附带 `src/modules/tomlplusplus.cppm` 时,可切回
58+
`sources = { "*/src/modules/tomlplusplus.cppm" }` 并删除 `generated_files`,`get_line` 会随之回归。
59+
60+
## 3. 描述符
61+
62+
- 路径:`pkgs/m/marzer.tomlplusplus.lua`(目录取**完整包名首字母** `m`)。
63+
- 命名:`marzer.tomlplusplus`,遵循 `nlohmann.json``<命名空间>.<库>` 约定。
64+
- `include_dirs = { "*/include" }`:cppm 的 global-module fragment 内 `#include <toml++/toml.hpp>` 由此解析;
65+
同时保留用户直接 `#include` 的能力。`*` 吸收 `tomlplusplus-3.4.0/` wrap 层。
66+
- `generated_files` 的 key 为 verdir 相对路径(无 glob),与 `nlohmann.json` 一致。
67+
- 多行字符串采用 `[==[ ]==]`(而非 `[[ ]]`):与 `nlohmann.json` 保持一致,且对 payload 中可能出现的
68+
`[[`/`]]` 更稳妥。已确认 payload 不含 `]==]`
69+
- 版本号采用裸版本 `"3.4.0"`;URL 中保留上游 `…/v3.4.0.tar.gz` 拼写。
70+
71+
## 4. feature 评估
72+
73+
**不实现 feature**。toml++ 为 header-only,无“额外的可编译源码”可供门控;其可选行为(如 `TOML_EXCEPTIONS`
74+
`TOML_ENABLE_FORMATTERS`)均为编译期 **define**,而 `features` 表当前仅能门控 `sources`,无法携带 define。
75+
与 Eigen 的 `EIGEN_MPL2_ONLY` 属同类限制,待 mcpp 支持 define/cflags 后再评估。
76+
77+
## 5. CN 镜像
78+
79+
- 新建 gitcode 仓库 `mcpp-res/tomlplusplus`(经 `gtc repo create` + init commit 建立 `main` 分支)。
80+
- release tag `3.4.0`,资产 `tomlplusplus-3.4.0.tar.gz`,上传的是**与 GLOBAL 完全相同**的 tarball。
81+
- 字节一致性验证:
82+
83+
```console
84+
CN sha: 8517f65938a4faae9ccf8ebb36631a38c1cadfb5efa85d9a72e15b9e97d25155
85+
GLB sha: 8517f65938a4faae9ccf8ebb36631a38c1cadfb5efa85d9a72e15b9e97d25155
86+
cmp : byte-identical
87+
```
88+
89+
- sha 稳定性:GLOBAL 重复下载两次,sha 一致(无 GitLab 式重打包漂移)。
90+
91+
## 6. 验证结论
92+
93+
测试工程 `tests/examples/marzer.tomlplusplus/`,已登记进根 `mcpp.toml``[workspace].members`
94+
(本仓测试面已由 `run_example.sh` 迁移至 `mcpp test --workspace`,故不再新增 `src/main.cpp` 式 bin 例子)。
95+
断言覆盖 parse、typed access、array/table 节点、`_toml` 字面量、serialize→reparse 往返。
96+
97+
| 检查 | 结果 |
98+
|---|---|
99+
| `mcpp test`(GLOBAL) |`parse ... ok` — 1 passed |
100+
| `mcpp test`(`MCPP_INDEX_MIRROR=CN`,清 `target .mcpp mcpp.lock` 后真实重新下载) |`parse ... ok` — 1 passed |
101+
| CN vs GLOBAL 字节比对 | ✅ byte-identical |
102+
| 全量 lint(46 descriptor,含 `check_mirror_urls.lua`) | ✅ all valid |
103+
| `mcpp xpkg parse`(CI pin 0.0.91 与本地 0.0.93) | ✅ OK |
104+
| 内嵌 cppm vs 上游 master 减 get_line |`diff` IDENTICAL |
105+
106+
## 7. 其它
107+
108+
- PR #64 原分支落后 `main` 10 个提交,已 rebase 到最新 `main` 后强推(`maintainerCanModify` 为 true)。
109+
-`pkgs/c/compat.tomlplusplus.lua``tests/examples/tomlplusplus/` 已删除。

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ mcpp self config --mirror CN # 切换至国内镜像,默认使用 GLOBAL 上
3636
| C 源码 compat(含 `features`) | [`compat.cjson`](pkgs/c/compat.cjson.lua) · [`compat.zlib`](pkgs/c/compat.zlib.lua) |
3737
| header-only(含 `features`) | [`compat.eigen`](pkgs/c/compat.eigen.lua) |
3838
| 外部构建系统(`install()` 从源码构建) | [`compat.openblas`](pkgs/c/compat.openblas.lua)(Make) · [`compat.opencv`](pkgs/c/compat.opencv.lua)(CMake) |
39-
| C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) |
39+
| C++23 module wrapper | [`nlohmann.json`](pkgs/n/nlohmann.json.lua) · [`marzer.tomlplusplus`](pkgs/m/marzer.tomlplusplus.lua) |
4040

4141
### 新增一个包
4242

mcpp.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ members = [
1717
"tests/examples/gui-stack",
1818
"tests/examples/imgui",
1919
"tests/examples/imgui-window",
20+
"tests/examples/marzer.tomlplusplus",
2021
"tests/examples/nlohmann.json",
2122
"tests/examples/openblas",
2223
"tests/examples/opencv",

pkgs/m/marzer.tomlplusplus.lua

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
-- Form B inline descriptor for toml++ (marzer/tomlplusplus) — a TOML config
2+
-- file parser and serializer for C++17 (and later), exposed as the C++23
3+
-- module `tomlplusplus` so users can write `import tomlplusplus;` out of the
4+
-- box (no opt-in, no `#include` needed).
5+
--
6+
-- Why generated: the released v3.4.0 source tarball is header-only and ships
7+
-- NO module interface unit. Upstream HAS authored an official one at
8+
-- `src/modules/tomlplusplus.cppm` (`export module tomlplusplus;`), but it
9+
-- lives on the `master` branch only and is not in any release tag yet (v3.4.0
10+
-- 404s for that path). So we provide it ourselves via mcpp's `generated_files`,
11+
-- embedding upstream's official tomlplusplus.cppm. The base headers stay
12+
-- pinned to the reproducible v3.4.0 release tag, straight from upstream —
13+
-- no fork in the trust path.
14+
--
15+
-- ONE deviation from upstream master's cppm, deliberate and minimal:
16+
-- `using TOML_NAMESPACE::get_line;` is dropped. `get_line` was added to
17+
-- `impl/source_region.hpp` AFTER v3.4.0 and does not exist in the pinned
18+
-- headers, so re-exporting it would not compile. Every other line is verbatim.
19+
--
20+
-- Evolution: once a toml++ release (>3.4.0) ships src/modules/tomlplusplus.cppm,
21+
-- switch `sources` to "*/src/modules/tomlplusplus.cppm", drop `generated_files`,
22+
-- and the get_line re-export comes back with it.
23+
--
24+
-- include_dirs exposes the tarball's include/ so the module unit's global-module
25+
-- fragment `#include <toml++/toml.hpp>` resolves (and `#include` remains
26+
-- available to users who want it). The upstream path is a GLOB — the leading
27+
-- `*` absorbs the archive's `tomlplusplus-3.4.0/` wrap layer — while the
28+
-- generated cppm path is verdir-relative (no glob), like nlohmann.json.
29+
package = {
30+
spec = "1",
31+
namespace = "marzer",
32+
name = "marzer.tomlplusplus",
33+
description = "TOML config file parser and serializer for C++, exposed as C++23 module tomlplusplus",
34+
licenses = {"MIT"},
35+
repo = "https://github.com/marzer/tomlplusplus",
36+
type = "package",
37+
38+
xpm = {
39+
linux = {
40+
["3.4.0"] = {
41+
url = {
42+
GLOBAL = "https://github.com/marzer/tomlplusplus/archive/refs/tags/v3.4.0.tar.gz",
43+
CN = "https://gitcode.com/mcpp-res/tomlplusplus/releases/download/3.4.0/tomlplusplus-3.4.0.tar.gz",
44+
},
45+
sha256 = "8517f65938a4faae9ccf8ebb36631a38c1cadfb5efa85d9a72e15b9e97d25155",
46+
},
47+
},
48+
macosx = {
49+
["3.4.0"] = {
50+
url = {
51+
GLOBAL = "https://github.com/marzer/tomlplusplus/archive/refs/tags/v3.4.0.tar.gz",
52+
CN = "https://gitcode.com/mcpp-res/tomlplusplus/releases/download/3.4.0/tomlplusplus-3.4.0.tar.gz",
53+
},
54+
sha256 = "8517f65938a4faae9ccf8ebb36631a38c1cadfb5efa85d9a72e15b9e97d25155",
55+
},
56+
},
57+
windows = {
58+
["3.4.0"] = {
59+
url = {
60+
GLOBAL = "https://github.com/marzer/tomlplusplus/archive/refs/tags/v3.4.0.tar.gz",
61+
CN = "https://gitcode.com/mcpp-res/tomlplusplus/releases/download/3.4.0/tomlplusplus-3.4.0.tar.gz",
62+
},
63+
sha256 = "8517f65938a4faae9ccf8ebb36631a38c1cadfb5efa85d9a72e15b9e97d25155",
64+
},
65+
},
66+
},
67+
68+
mcpp = {
69+
schema = "0.1",
70+
language = "c++23",
71+
import_std = false,
72+
modules = { "tomlplusplus" },
73+
include_dirs = { "*/include" },
74+
-- Upstream's official module unit (master @ src/modules/tomlplusplus.cppm),
75+
-- reproduced verbatim apart from the get_line drop documented above.
76+
-- Verdir-relative path, no glob.
77+
generated_files = {
78+
["mcpp_generated/tomlplusplus.cppm"] = [==[
79+
/**
80+
* @file tomlpp.cppm
81+
* @brief File containing the module declaration for toml++.
82+
*/
83+
84+
module;
85+
86+
#define TOML_UNDEF_MACROS 0
87+
#include <toml++/toml.hpp>
88+
89+
export module tomlplusplus;
90+
91+
/**
92+
* @namespace toml
93+
* @brief The toml++ namespace toml::
94+
*/
95+
export namespace toml {
96+
/**
97+
* @namespace literals
98+
* @brief The toml++ namespace toml::literals::
99+
*/
100+
inline namespace literals {
101+
using TOML_NAMESPACE::literals::operator""_toml;
102+
using TOML_NAMESPACE::literals::operator""_tpath;
103+
}
104+
105+
using TOML_NAMESPACE::array;
106+
using TOML_NAMESPACE::date;
107+
using TOML_NAMESPACE::date_time;
108+
using TOML_NAMESPACE::inserter;
109+
using TOML_NAMESPACE::json_formatter;
110+
using TOML_NAMESPACE::key;
111+
using TOML_NAMESPACE::node;
112+
using TOML_NAMESPACE::node_view;
113+
using TOML_NAMESPACE::parse_error;
114+
using TOML_NAMESPACE::parse_result;
115+
using TOML_NAMESPACE::path;
116+
using TOML_NAMESPACE::path_component;
117+
using TOML_NAMESPACE::source_position;
118+
using TOML_NAMESPACE::source_region;
119+
using TOML_NAMESPACE::table;
120+
using TOML_NAMESPACE::time;
121+
using TOML_NAMESPACE::time_offset;
122+
using TOML_NAMESPACE::toml_formatter;
123+
using TOML_NAMESPACE::value;
124+
using TOML_NAMESPACE::yaml_formatter;
125+
using TOML_NAMESPACE::format_flags;
126+
using TOML_NAMESPACE::node_type;
127+
using TOML_NAMESPACE::path_component_type;
128+
using TOML_NAMESPACE::value_flags;
129+
using TOML_NAMESPACE::array_iterator;
130+
using TOML_NAMESPACE::const_array_iterator;
131+
using TOML_NAMESPACE::const_table_iterator;
132+
using TOML_NAMESPACE::default_formatter;
133+
using TOML_NAMESPACE::inserted_type_of;
134+
using TOML_NAMESPACE::optional;
135+
using TOML_NAMESPACE::source_index;
136+
using TOML_NAMESPACE::source_path_ptr;
137+
using TOML_NAMESPACE::table_iterator;
138+
139+
using TOML_NAMESPACE::at_path;
140+
using TOML_NAMESPACE::operator""_toml;
141+
using TOML_NAMESPACE::operator""_tpath;
142+
using TOML_NAMESPACE::operator<<;
143+
using TOML_NAMESPACE::parse;
144+
using TOML_NAMESPACE::parse_file;
145+
146+
using TOML_NAMESPACE::is_array;
147+
using TOML_NAMESPACE::is_boolean;
148+
using TOML_NAMESPACE::is_chronological;
149+
using TOML_NAMESPACE::is_container;
150+
using TOML_NAMESPACE::is_date;
151+
using TOML_NAMESPACE::is_date_time;
152+
using TOML_NAMESPACE::is_floating_point;
153+
using TOML_NAMESPACE::is_integer;
154+
using TOML_NAMESPACE::is_key;
155+
using TOML_NAMESPACE::is_key_or_convertible;
156+
using TOML_NAMESPACE::is_node;
157+
using TOML_NAMESPACE::is_node_view;
158+
using TOML_NAMESPACE::is_number;
159+
using TOML_NAMESPACE::is_string;
160+
using TOML_NAMESPACE::is_table;
161+
using TOML_NAMESPACE::is_time;
162+
using TOML_NAMESPACE::is_value;
163+
164+
using TOML_NAMESPACE::preserve_source_value_flags;
165+
}
166+
]==],
167+
},
168+
sources = { "mcpp_generated/tomlplusplus.cppm" },
169+
targets = { ["tomlplusplus"] = { kind = "lib" } },
170+
deps = { },
171+
},
172+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# toml++ test project: consumes the C++23 module `tomlplusplus` and asserts
2+
# parse + typed access + round-trip serialization under `mcpp test`.
3+
[package]
4+
name = "tomlplusplus-tests"
5+
version = "0.1.0"
6+
7+
[indices]
8+
marzer = { path = "../../.." }
9+
10+
[dependencies.marzer]
11+
tomlplusplus = "3.4.0"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Behavioral test: parse → typed access → array/table nodes → _toml literal →
2+
// serialize-and-reparse round-trip, all through the C++23 module surface
3+
// (`import tomlplusplus;`, no #include).
4+
import std;
5+
import tomlplusplus;
6+
7+
int main() {
8+
auto cfg = toml::parse(R"(
9+
[server]
10+
host = "localhost"
11+
port = 8080
12+
tags = ["a", "b"]
13+
)");
14+
15+
// typed access — value<std::string> so this compares strings, not pointers
16+
bool ok = cfg["server"]["port"].value<int>() == 8080
17+
&& cfg["server"]["host"].value<std::string>() == "localhost"
18+
&& cfg["server"]["tags"].as_array()->size() == 2;
19+
20+
// the _toml literal re-exported through toml::literals
21+
using namespace toml::literals;
22+
auto lit = "x = 1"_toml;
23+
ok = ok && lit["x"].value<int>() == 1;
24+
25+
// round-trip: serialize via the exported operator<<, then re-parse
26+
std::ostringstream os;
27+
os << cfg;
28+
auto again = toml::parse(os.str());
29+
ok = ok && again["server"]["port"].value<int>() == 8080
30+
&& again["server"]["tags"].as_array()->size() == 2;
31+
32+
return ok ? 0 : 1;
33+
}

0 commit comments

Comments
 (0)