Skip to content

feat(libaio): 收录 compat.libaio 0.3.113,并把描述符目录从 README 挪进 docs/ - #277

Merged
Sunrisepeak merged 1 commit into
mainfrom
feat/add-libaio
Aug 29, 2026
Merged

feat(libaio): 收录 compat.libaio 0.3.113,并把描述符目录从 README 挪进 docs/#277
Sunrisepeak merged 1 commit into
mainfrom
feat/add-libaio

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

1. compat.libaio 0.3.113

libaio 是 Linux 原生异步 I/O 系统调用的用户态封装(io_setup / io_submit / io_getevents / io_cancel / io_destroy,外加 io_prep_*io_queue_* 便利层)。

形态 A(C 源码 compat):直接取上游 src/Makefilelibaio_srcs,12 个 TU,无 configure、无生成步骤、无 submodule。

Linux only,而且是强意义上的:struct iocb 就是内核的结构体,每个 TU 都是 syscall(__NR_io_*, …),不存在别的平台段可写。xpm 只有 linux,消费者用 [target.'cfg(linux)'.dependencies] 门控,与 compat.wil 互为镜像。

上游 https://pagure.io/libaio tag libaio-0.3.113(最新 release)
License LGPL-2.1-or-later
GLOBAL https://releases.pagure.org/libaio/libaio-0.3.113.tar.gz
CN https://gitcode.com/mcpp-res/libaio/releases/download/0.3.113/libaio-0.3.113.tar.gz
sha256 2c44d1c5fd0d43752287c9ae1eb9c023f04ef848ea8d4aafa46e9aedb678200b(连算两次一致;CN 回拉逐字节相同)

GLOBAL 用 releases.pagure.org 的发布文件而非 pagure.io/…/archive/…:后者直接 404,且 pagure 与 GitLab 同类,归档即时生成、sha 会漂移。

三个需要交代的决策

① 只暴露一个公开头。 上游 make install 只装 libaio.h,但 tarball 把它放在 src/ 里与私有头并列 —— 其中一个叫 syscall.h,上了 include 路径就会遮蔽 glibc 的同名头。所以 include_dirs 只指向一个 generated_files 转发头(compat.gmp 的先例),包自身的源码经它拿到真头文件,而它们引号形式的 #include "syscall.h" 按「包含者所在目录优先」解析 —— 整包不需要任何指向 src/-I。已实测消费者侧 #include <syscall.h> 拿到的确实是 glibc 的。

c_standard = "gnu11" 是个陷阱。 -std=c11 会定义 __STRICT_ANSI__,glibc 随之藏掉 syscall()sigset_t,连公开头都会在 io_pgetevents 处解析失败。写 gnu11 看起来是解法,mcpp xpkg parse 也通过,但查产出的 compile_commands.json:mcpp 2026.8.27.2 收下这个字符串后仍然发 -std=c11,静默降级无提示。生效的写法是 cflags 里的 -D_GNU_SOURCE

顺带一提:pkgs/c/compat.freetype.lua 也声明了 gnu11,同样拿不到 gnu 模式。它目前 CI 是绿的,本 PR 不动它,只在设计文档里记一笔。

③ 符号版本。 io_getevents / io_cancel 在上游没有普通定义 —— 真名是 io_getevents_0_4 之类,短名经 .symver … @@LIBAIO_0.4 发布。链可执行文件时 ld.bfd 与 lld 都能解析(两者都实测过),kind = "lib" 走的正是这条路;直接拿这些对象建 .so 则需要上游的 src/libaio.map,与上游自己的 libaio.a 完全同理。也试过删 compat-0_1.c 以消除 @LIBAIO_0.1 —— 没用,三个 @@LIBAIO_0.4 一样会挡住,故保留以与上游对象集一致。

feature 评估:无

判据是「有没有额外的、可门控的可编译源码」。没有:src/struct_offsets.c 是构建期断言(其注释明说不进目标文件),harness/ 是自带 main() 的测试套件 —— 而 mcpp 的 lib 目标对象全量入链,包里带 main() 必与消费者冲突,连做 feature 的资格都没有。

测试成员 tests/examples/libaio

断言全是真实内核 AIO 行为,不 mock:上游 struct_offsets.c 的三条 static_assert(本包不编那个 TU,把检查搬进测试)、io_prep_pwrite 填出的 iocb 字段、写路径提交→收事件→pread 确认落盘、offset 512 处的读回比对、双请求批量提交用 data cookie 区分、错误契约(对已关闭 fd 提交返回 -EBADFerrno 不被改动)、io_cancel、以及 io_queue_init/io_set_callback/io_queue_run 的回调层。

验证(mcpp 2026.8.27.2,与 CI 同版本)

$ mcpp xpkg parse pkgs/c/compat.libaio.lua
sources 12 · includes 1 · generated libaio-0.3.113/mcpp/include/libaio.h (312 bytes) · parse OK

$ rm -rf tests/examples/libaio/{target,.mcpp} && mcpp test -p libaio
aio ... ok (0.06s)
test result ok. 1 passed; 0 failed
  • 包确实被编译:obj/compat_libaio/libaio-0.3.113/src/ 下 12 个 .o,最终二进制里 nm 可见 io_setup / io_submit / io_getevents@@LIBAIO_0.4
  • 断言确实可失败:把一条 memcmp 断言反过来 → FAIL (exit 134);改回冷跑仍绿。
  • 六个本地 lint 全过。

2. README「参考示例」段落重构

这张表长到了约 22 KB,占 28 KB 英文 README 的绝大部分,把它周围的所有内容都埋掉了。

  • 完整目录移到 docs/descriptor-examples.mddocs/zh/descriptor-examples.md(内容原样搬运,libaio 自己的条目写在这里),并登记进 docs/README.md / docs/zh/README.md;
  • README 只留每种常见形态一行、一句话说明的六行小表 + 一个链接;
  • 更新 docs/package-types.md(中英)里指向旧锚点的反向引用;
  • 顺手修掉表里一条早已失效的链接:pkgs/o/opencv.luapkgs/o/opencv.opencv.lua

README:28693 → 6151 字节(中文 25591 → 5330)。全部相对链接已逐个检查可达。

设计文档:.agents/docs/2026-08-29-add-libaio-plan.md

…log out of the README

libaio is the userspace wrapper over Linux's native AIO syscalls. Shape A
(C-source compat): upstream's own `libaio_srcs` list from src/Makefile,
twelve TUs, no configure step. Linux-only in the strong sense — `struct
iocb` IS the kernel's, so there is no other platform section to write and
consumers gate it with `[target.'cfg(linux)'.dependencies]`.

Three things the descriptor had to answer:

* Upstream installs exactly one header, `libaio.h`, but the tarball keeps
  it in `src/` next to the private ones — one of which is `syscall.h` and
  would shadow glibc's for every consumer TU. So `include_dirs` names a
  `generated_files` forwarder and nothing else; the package's own sources
  reach the real header through it while their quote-form includes still
  resolve next to the including `.c`, so no `-I` into `src/` is needed.

* `-std=c11` sets __STRICT_ANSI__, which hides `syscall()` and `sigset_t`
  and makes even the public header fail to parse. `c_standard = "gnu11"`
  looks like the fix and is a trap: mcpp 2026.8.27.2 accepts the string
  and still emits `-std=c11`. `-D_GNU_SOURCE` in `cflags` is what works.

* `io_getevents`/`io_cancel` have no ordinary definitions upstream — the
  short names come from `.symver … @@LIBAIO_0.4`. Verified to resolve for
  an executable under both ld.bfd and lld; building a `.so` straight out
  of these objects still needs upstream's libaio.map, exactly as with
  upstream's own libaio.a.

No features: the only sources not compiled are a build-time assertion TU
(restated as static_asserts in the test) and the harness, which carries a
main() and so cannot be a feature at all.

CN mirror published at gitcode mcpp-res/libaio, byte-identical to GLOBAL.
Verified with the CI-pinned mcpp: `mcpp test -p libaio` green from cold,
12 objects actually compiled, and the assertions confirmed failable.

Also, in the same pass: the "Reference examples" table had grown to ~22 KB
of the 28 KB README and buried everything around it. The full catalog now
lives in docs/descriptor-examples.md (+ zh), with libaio's own entry; the
README keeps a six-row table of one starting point per shape and links
out. README 28693 -> 6151 bytes. Fixes a stale pkgs/o/opencv.lua link
along the way.
@Sunrisepeak
Sunrisepeak merged commit 27b5c28 into main Aug 29, 2026
11 checks passed
Sunrisepeak pushed a commit that referenced this pull request Aug 29, 2026
moodycamel::ConcurrentQueue — the lock-free MPMC queue, plus its blocking
sibling and a flat C API over both. Shape B (header-only): the three public
headers sit at the tarball root, so `include_dirs = {"*"}` plus an anchor TU
is the package; consumers write `#include <concurrentqueue.h>` exactly as
upstream's README shows.

The one compilable optional component — `c_api/`'s two extern "C" wrapper
TUs — sits behind a default-off `c-api` feature (the compat.cjson `utils`
precedent). Windows needs `MOODYCAMEL_STATIC` on BOTH sides: the header
defaults to `__declspec(dllimport)`, which is wrong for the package's own
TUs (they define the functions, and `cflags` never reaches a .cpp — hence
`cxxflags`) and for a static-archive consumer (hence the feature's
interface `defines`). The macro is only read under `#ifdef _WIN32`, so
defining it everywhere is inert on linux/macos. Verified in the emitted
compile_commands.json that all four TUs carry it.

Tests: tests/examples/concurrentqueue asserts FIFO order, bulk round-trips,
move-only elements, a blocking consumer that REALLY waits (empty-queue
wait_dequeue_timed must burn its 50ms timeout), and a 4x4 MPMC race checked
for exact-once delivery. tests/examples/concurrentqueue-c-api consumes the
feature and round-trips integers through the void* C API. Both members
register in the workspace manifest.

Verified locally with mcpp 2026.8.27.1 (CI pins 2026.8.27.2; the release
CDN times out from this host): both members green from cold; the gate is
real — a TU referencing moodycamel_cq_create against the default build
fails to LINK (undefined reference), and the default build's object dir
holds the anchor alone. No CN mirror: no GITCODE_TOKEN on this host, so the
descriptor uses the plain-string upstream url fallback and the descriptor
catalog entry lands in docs/descriptor-examples.md (+ zh), per the post-#277
README layout.

Co-authored-by: gong <gzj17607270093@163.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant