Skip to content

Commit 6dd5f68

Browse files
authored
Merge branch 'main' into feat/add-libserial
2 parents 6f36e33 + 239c45f commit 6dd5f68

23 files changed

Lines changed: 747 additions & 0 deletions
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Quill 13.0.0 接入 mcpp 模块生态
2+
3+
日期:2026-10-04。状态:已实施,Linux GCC/LLVM、macOS ARM、Windows 构建运行均通过。验收依据见第 5 节。
4+
5+
## 1. 范围与消费方式
6+
7+
包为 `odygrd.quill@13.0.0`,模块入口保持上游的 `import quill;`。复用正式发布的实验性模块,保留异步日志行为、公开 API 和内置 fmt。没有独立 compat 包、fork、自制 wrapper、额外 feature 或引擎改动。
8+
9+
```toml
10+
[dependencies.odygrd]
11+
quill = "13.0.0"
12+
```
13+
14+
PR 合并发布前,本地使用需要指向索引 checkout;将示例路径替换为自己的仓库路径:
15+
16+
```toml
17+
[indices]
18+
odygrd = { path = "/path/to/mcpp-index" }
19+
```
20+
21+
消费者写 `import std; import quill;`。可通过 `quill::Frontend` 创建 sink/logger,使用无宏 API `quill::info(logger, "answer={}", 42)` 或运行时级别 `quill::log`。使用上游日志宏时额外写:
22+
23+
```cpp
24+
#define QUILL_USE_MODULE
25+
#include <quill/LogMacros.h>
26+
```
27+
28+
随后可调用 `LOG_INFO` 或 `QUILL_LOG_INFO`。13.0.0 消费端显式定义 `QUILL_USE_MODULE`;不依赖包内 defines 自动传播。宏头在此模式下跳过普通类型头,并补充宏所需的 helper,不重复包含完整实现。`QUILL_MODULE`、`FMTQUILL_MODULE` 由上游模块自行定义,消费者无需设置。
29+
30+
两种 API 的行为不完全相同:上游 [`LogFunctions.h`](https://github.com/odygrd/quill/blob/v13.0.0/include/quill/LogFunctions.h) 说明无宏 API 的参数始终求值,存在运行时元数据处理,也不能像宏一样按编译期日志级别完全移除。接入不强制迁移原有宏用法,也不作性能等价承诺。
31+
32+
模块公开面以 13.0.0 的模块入口及它实际导出的声明为准;不承诺所有可选头都能通过 import 使用。没有新增 Syslog/Systemd/Android sink、Prometheus 示例或自定义 codec/formatter 导出。完整 Quill 文本头与模块混用、跨 DLL 共享后端不在此次验收范围内。
33+
34+
## 2. 固定的上游输入
35+
36+
- 上游:[odygrd/quill v13.0.0](https://github.com/odygrd/quill/releases/tag/v13.0.0),MIT;保留根 LICENSE 和 bundled fmt 的声明。
37+
- Tag commit:`eb802a37c7d585840324886a3d8648c9c2159952`。
38+
- 归档:`https://github.com/odygrd/quill/archive/refs/tags/v13.0.0.tar.gz`。
39+
- SHA-256:`88b4a1542125577a4d51cf444c51e34d63618c422ba6a4fa9bd23894b49d696b`;spec 调研时两次独立下载一致,实施中的真实下载通过包摘要校验。
40+
- 解包根为 `quill-13.0.0/`。普通形态为头文件库,模块入口是 [`src/quill.cc`](https://github.com/odygrd/quill/blob/v13.0.0/src/quill.cc),采用 CRLF。
41+
- [`CMakeLists.txt`](https://github.com/odygrd/quill/blob/v13.0.0/CMakeLists.txt) 的 `QUILL_BUILD_MODULE` 标为 experimental,编译 `src/quill.cc` 并链接 `Threads::Threads`。
42+
- 内置格式化库位于 `include/quill/bundled/fmt/`,使用 `fmtquill` 命名空间,无需依赖 `fmtlib.fmt` 或 `compat.fmt`。
43+
44+
调研时 GitHub Releases API 的 latest 为 13.0.0;实施时该 API 返回 403,改用 `git ls-remote --tags ... 'refs/tags/v13*'` 确认仍只有 `v13.0.0`。在线 latest 文档/master 出现的 13.1.0 内容未混入固定版本实现。
45+
46+
## 3. 接入方案与适配边界
47+
48+
采用内联 Form B 描述符 [`pkgs/o/odygrd.quill.lua`](../../pkgs/o/odygrd.quill.lua):
49+
50+
| 字段 | 实现 |
51+
|---|---|
52+
| `namespace` / `name` | `odygrd` / `quill` |
53+
| `language` / `import_std` | `c++23` / `false`;保留上游 global module fragment,消费者仍可导入 std |
54+
| `modules` | `{ "quill" }` |
55+
| `include_dirs` | `{ "*/include" }`,服务模块内部包含及消费端宏头 |
56+
| `sources` | `{ "*/src/quill.cppm" }`,只编译一个入口 |
57+
| `targets` / `deps` | `quill` lib / 空依赖 |
58+
| Linux 链接 | `ldflags = { "-pthread" }` |
59+
| 三平台下载 | 相同版本、归档和摘要,使用纯字符串 GLOBAL URL |
60+
61+
安装钩子检查源文件可读且恰有一条 `export module quill;`,以其内容生成同目录 `src/quill.cppm`。原 `.cc` 保留但不加入编译源集。507 个上游文件内容保持不变,适配仅作用于新增的 `.cppm`;读取后统一按 LF 匹配,兼容安装环境对 CRLF 的文本转换。
62+
63+
macOS ARM 的 PR CI 暴露两处上游模块入口问题,安装钩子执行两项精确替换,匹配次数不是一次即失败:
64+
65+
- x86 intrinsic 包含增加 x86 目标架构条件。Clang 在 ARM 上也能找到 `x86gprintrin.h`,仅靠 `__has_include` 会触发无效汇编约束和不存在的 x86 builtin。
66+
- 在 global module fragment 中为 Apple 预包含 Mach 头,以及后端使用的 `unistd.h`、`fcntl.h`、`sys/file.h`、`sys/mman.h`、`sched.h`、`time.h` 和遗漏的 `<charconv>`。否则 Mach 类型、`timeval`、`timespec` 等在全局模块和 Quill 模块中重复归属,编译报错。
67+
68+
失败证据见 [PR CI 的 macOS job](https://github.com/mcpplibs/mcpp-index/actions/runs/37198494639/job/111425198293)。适配不修改 Quill 头文件、导出列表或日志实现。后续 CI 的 [macOS 系统头错误](https://github.com/mcpplibs/mcpp-index/actions/runs/37198733789/job/111425892513) 和 [Windows 换行匹配错误](https://github.com/mcpplibs/mcpp-index/actions/runs/37198733789/job/111425892875) 分别对应系统头补全和换行规范化;仓库中的 [安装钩子检查](../../tests/check_quill_install.lua) 验证 CRLF/LF 生成相同结果,以及输入不可读、模块声明或替换位置缺失/重复时,在任何写入或安装目录操作前失败;该检查已接入 CI lint。
69+
70+
扩展名适配参考 [`fmtlib.fmt`](../../pkgs/f/fmtlib.fmt.lua),避免 Clang 将 `.cc` 当普通翻译单元。实际 GCC、LLVM 构建图均只编译 `.cppm`,分别生成 `quill.gcm`、`quill.pcm`;未增加 `scan_overrides` 或完整生成式 wrapper。没有执行 CMake,`QUILL_BUILD_MODULE=ON` 不是本包的构建开关。
71+
72+
线程选项仅在 Linux 最终链接时传入,已检查两套构建图的 `ldflags`。不能只给模块或消费者一方增加影响 PCM 配置的 `-pthread` 编译选项:调研中的宿主 Clang 曾复现配置不一致,分开编译与链接后通过。当前 mcpp GCC/LLVM 构建无需额外线程编译选项。
73+
74+
上游对 MinGW 有 `ucrtbase` 分支,未将其泛化为所有 Windows 编译器的链接需求;本次 Windows CI 使用 MSVC ABI 工具链并已通过,未验证 MinGW。未建立 CN 镜像,不声明猜测的地址;以后若增加镜像,须上传相同归档字节并核对摘要与可达性。
75+
76+
选择依据:复用模块及安装钩子参考 [Taskflow](2026-10-04-add-taskflow-spec.md),保留上游模块名参考 [`khronos.vulkan-hpp`](../../pkgs/k/khronos.vulkan-hpp.lua),内置 fmt 与 build/test 分别验证参考 [spdlog](2026-07-15-add-spdlog-plan.md)。普通头文件 `compat.quill` 无法提供所需 import;独立 Form A 适配仓会增加维护责任,目前均无必要。
77+
78+
## 4. 持久文件与测试契约
79+
80+
- 描述符:`pkgs/o/odygrd.quill.lua`。
81+
- 测试成员:[`tests/examples/quill-module/mcpp.toml`](../../tests/examples/quill-module/mcpp.toml),仅一条 odygrd 本地索引重定向;根 workspace 已登记。
82+
- 测试入口:[`tests/quill.cpp`](../../tests/examples/quill-module/tests/quill.cpp)。
83+
- 辅助 TU:[`src/log_worker.cpp`](../../tests/examples/quill-module/src/log_worker.cpp)。
84+
- 中英文目录:`docs/descriptor-examples.md`、`docs/zh/descriptor-examples.md`。README 已链接这两份完整目录,无需改变其结构。
85+
86+
一个测试可执行文件、两个消费 TU,均使用 `import std; import quill;`,覆盖:
87+
88+
1. 主 TU 启动后端、创建 FileSink/logger;辅助 TU 在工作线程查询同名 logger,断言与主 TU 的指针相同。
89+
2. 宏 `LOG_INFO` 输出整数和字符串;不包含任何 Quill 头的辅助 TU 通过 `quill::info` 输出 `std::vector<int>`,通过 `quill::log` 输出运行时级别记录。
90+
3. 两个 TU 分别提交 Debug 日志,Info 阈值下断言它们均未输出。
91+
4. producer 通过 `std::jthread` join,随后 flush/stop,再读回文件,断言三条有效消息的格式化内容和行数;不依赖时间戳、并发顺序或任意 sleep。
92+
5. 每次创建独享临时目录;断言失败返回非零,异常写 stderr;结束后停止后端并清理目录。测试超时 30 秒。
93+
94+
## 5. 实际验证与复现
95+
96+
模块实现提交 `2b17c5587d1b0410272621b9f3940f1bfd97841e` 的 [PR CI 验收](https://github.com/mcpplibs/mcpp-index/actions/runs/37199001009) 已通过,包含 Linux GCC/LLVM、macOS ARM、Windows 的真实构建运行,以及 lint、镜像 URL 和图形安装副作用检查。跨平台结果不是仅由描述符解析推断。
97+
98+
| 检查 | 结果 |
99+
|---|---|
100+
| Linux GCC 16.1.0、LLVM 22.1.8/libc++ | 开发构建、最终安装补丁后的隔离测试均为 `1 passed; 0 failed` |
101+
| macOS ARM、Windows MSVC ABI | PR CI 各 `1 passed; 0 failed` |
102+
| Linux Release(`-O2`) | GCC、LLVM 各 `1 passed; 0 failed` |
103+
| GCC 增量与独立消费工程 | 增量测试通过;独立 `mcpp run --cache off` 编译、链接和运行断言通过 |
104+
| 冷安装 | 独立测试目录实际下载、解包和运行安装钩子;不将 `--cache off` 本身作为重装证据 |
105+
| 安装文件比较 | 507 个上游文件内容不变,仅新增带模块入口适配的 `.cppm` |
106+
| 安装钩子边界 | LF/CRLF 输出一致;不可读输入、缺失/重复模块声明、缺失/重复替换位置五个负向用例均通过 |
107+
| Lua、schema 和索引 lint | Lua 语法、三平台描述符解析、镜像 URL、包身份、保留 namespace、全仓跨包引用/版本一致性/重复版本检查通过 |
108+
109+
在仓库根目录使用 Bash 复现。先将 `MCPP_ROOT` 设置为已解包的 mcpp 2026.10.1.2 发布目录;`MCPP_HOME` 可指定已有 GCC/LLVM 工具链目录,默认使用用户目录下的 `.mcpp`。这些设置仅作用于当前 Shell,不切换全局默认版本。安装钩子检查仅需要 Lua 5.4,不需要上游归档、网络或临时调查文件。
110+
111+
```sh
112+
: "${MCPP_ROOT:?请设置 mcpp 2026.10.1.2 发布目录}"
113+
export MCPP="$MCPP_ROOT/bin/mcpp"
114+
export MCPP_HOME="${MCPP_HOME:-$HOME/.mcpp}"
115+
export MCPP_INDEX_MIRROR=GLOBAL
116+
export MCPP_VENDORED_XLINGS="$MCPP_ROOT/registry/bin/xlings"
117+
test "$("$MCPP" --version)" = "mcpp 2026.10.1.2" || exit 1
118+
lua5.4 tests/check_quill_install.lua
119+
"$MCPP" xpkg parse --all-os pkgs/o/odygrd.quill.lua
120+
"$MCPP" test -p quill-module --cache off --timeout 30
121+
"$MCPP" test -p quill-module --toolchain llvm@22.1.8 --cache off --timeout 30
122+
"$MCPP" test -p quill-module --timeout 30
123+
"$MCPP" test -p quill-module --profile release --cache off --timeout 30
124+
"$MCPP" test -p quill-module --toolchain llvm@22.1.8 --profile release --cache off --timeout 30
125+
```
126+
127+
## 6. 验证边界
128+
129+
上游仍将模块标为实验性。当前覆盖 Linux x86_64、macOS ARM 和 Windows MSVC ABI 工具链;未验证 MinGW、跨 DLL、完整 Quill 文本头与模块混用,以及全部可选 sink/codec/metrics,不承诺性能指标。未上传 CN 镜像。
130+
131+
升级上游或工具链时应重新执行同一套跨平台测试。若需要超出模块入口的小范围适配、改动日志实现或 mcpp 引擎,应保留失败复现并重新审查范围,不以跳过平台或静默改成头文件包代替验收。
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Taskflow 4.1.0 模块接入
2+
3+
## 范围与消费方式
4+
5+
以最小必要改动接入上游 CPU 模块,包名为 `taskflow.taskflow@4.1.0`,入口保持 `import tf;`。不提供独立 compat 包、CUDA feature 或自行维护的 API wrapper。
6+
7+
```toml
8+
[dependencies.taskflow]
9+
taskflow = "4.1.0"
10+
```
11+
12+
消费者使用 `import std; import tf;`。模块只提供上游实际导出的 API,预处理宏不随模块导出,版本查询使用 `tf::version()`。模块与文本头文件混用不在本次验收范围内。
13+
14+
## 上游与包结构
15+
16+
- 上游:[taskflow/taskflow v4.1.0](https://github.com/taskflow/taskflow/releases/tag/v4.1.0),MIT。
17+
- Tag commit:`45366fe5bc4f2f8ec9aa590b40c504e296886865`。
18+
- 归档:`https://github.com/taskflow/taskflow/archive/refs/tags/v4.1.0.tar.gz`。
19+
- SHA-256:`2107f90e315e48a676922010b036357ff2b0c6b9160ce17fa9396e5860b1d715`,独立下载摘要一致。
20+
- 归档根目录为 `taskflow-4.1.0/`,没有符号链接;Linux、macOS、Windows 使用相同归档及校验值。
21+
- 描述符为内联 Form B,采用 C++23,`import_std = false`,include 根为归档根目录。
22+
- 显式编译 `tf.core.cppm`、`tf.algorithm.cppm`、`tf.utility.cppm`、`tf.cppm`;不通配 modules 目录,因为 `tf_with_cuda.cppm` 同样提供主模块 `tf`。
23+
- 未配置 CN 镜像,使用纯字符串上游 URL;需要镜像时应上传相同归档字节。
24+
25+
该形态参考 `khronos.vulkan-hpp` 的上游模块复用方式,安装期适配参考 `compat.muduo`,Linux 线程链接配置参考 `chriskohlhoff.asio`。
26+
27+
## 必要适配
28+
29+
安装钩子逐项检查目标文件可读且替换位置恰好出现一次,不匹配立即失败。下载归档保持上游原样,适配只发生在解包后的三个模块文件中。
30+
31+
| 文件 | 适配 | 验证依据 |
32+
|---|---|---|
33+
| `modules/tf.core.cppm` | 移除 `HasGraph`、`ProfileData` 两条失效导出 | 4.1.0 头文件中不存在这两个名字,原模块在 Clang 下直接编译失败 |
34+
| `modules/tf.core.cppm`、`modules/tf.cppm` | 将总头文件包含及版本函数导出移至 core,主接口先导入 core 再导入 algorithm | GCC 16.1.0 消费原模块时找不到 `tf::Executor`、`tf::Taskflow`;宿主 GCC 16.2.1 独立复现,组合调整后通过 |
35+
| `modules/tf.utility.cppm` | 显式包含 `<algorithm>` | libc++ 下 `iterator.hpp` 使用的 `std::max` 缺少声明 |
36+
37+
逐文件摘要比较确认其余上游文件未改变,包括所有头文件及调度实现。没有独立 fork,也未修改 mcpp 引擎或现有 CI 配置。
38+
39+
Linux 最终链接使用 `-pthread`。不单独给依赖模块的编译命令增加该参数,否则 LLVM 消费者与 PCM 的线程配置不一致。实际构建命令确认链接参数到达消费者。
40+
41+
## 测试与索引登记
42+
43+
`tests/examples/taskflow-module` 通过单条 `taskflow` 索引重定向消费当前 checkout。一个测试 main 与一个辅助 TU 共同链接,覆盖:
44+
45+
- `import std; import tf;` 的多 TU 消费。
46+
- 两个 worker 执行两条 DAG 分支并汇合,检查结果为 42。
47+
- 1024 个元素的 `reduce`,检查结果为 1024。
48+
- `next_pow2` 与 `tf::version()`。
49+
50+
断言失败返回非零退出码,运行时间由 mcpp 测试超时约束。成员已登记到根 workspace,中英文描述符目录已有对应条目。
51+
52+
## 验证结果
53+
54+
使用 CI 固定的 mcpp `2026.10.1.2`:
55+
56+
```sh
57+
mcpp test -p taskflow-module --cache off --timeout 30
58+
mcpp test -p taskflow-module --toolchain llvm@22.1.8 --cache off --timeout 30
59+
mcpp xpkg parse --all-os pkgs/t/taskflow.taskflow.lua
60+
```
61+
62+
- Linux GCC 16.1.0、LLVM 22.1.8/libc++:各 `1 passed; 0 failed`,GCC 增量运行通过。
63+
- 冷安装、Lua 语法、三平台描述符解析通过。
64+
- 镜像 URL、包身份、保留 namespace、全仓跨包引用、平台版本一致性、重复版本检查通过。
65+
- workspace 与描述符变更均能由现有 CI 选择规则命中 `taskflow-module`。
66+
- macOS、Windows 尚待 PR CI 构建和运行验证;描述符解析不代表运行验收。

‎.github/workflows/validate.yml‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,8 @@ jobs:
531531
# release that republished an old tag would leave no other trace.
532532
- name: Lint duplicate versions
533533
run: lua5.4 tests/check_duplicate_versions.lua pkgs/*/*.lua
534+
- name: Check Quill install hook boundaries
535+
run: lua5.4 tests/check_quill_install.lua
534536
# The compatibility measurement's classifier decides a PUBLISHED figure
535537
# -- which members "run", which "build", and which were correctly
536538
# "refused" -- and the only thing that exercised it was the four-hour
@@ -1454,6 +1456,22 @@ jobs:
14541456
mine="${kept# }"
14551457
fi
14561458
1459+
# `mp-units-module`: the reverse case. `mpusz.mp-units` requires
1460+
# libc++ on linux because GCC 16.1 cannot import its modules
1461+
# (`recursive lazy load`, mpusz/mp-units#717), so the gcc leg would
1462+
# only reach that refusal. Lift once xim ships a GCC that works.
1463+
if [ "${{ matrix.platform }}" = "linux" ] && [ "${{ matrix.toolchain }}" = "default" ]; then
1464+
kept=""
1465+
for m in $mine; do
1466+
case "$m" in
1467+
mp-units-module)
1468+
echo "skipping '$m' on the gcc leg: the package requires libc++" ;;
1469+
*) kept="$kept $m" ;;
1470+
esac
1471+
done
1472+
mine="${kept# }"
1473+
fi
1474+
14571475
echo "MEMBERS=$mine" >> "$GITHUB_ENV"
14581476
echo "shard ${{ matrix.shard }}/${{ matrix.shards }}: ${mine:-<none>}"
14591477

0 commit comments

Comments
 (0)