Skip to content

[ci] 没有任何 job 构建大链接包 — argv 上限类缺陷对全部 18 个 CI job 不可见 #346

Description

@Sunrisepeak

背景

PR #345 在 18/18 CI job 全绿之后,被本地跑真实 mcpp-index workspace 抓到一个回归:

ninja: fatal: posix_spawn: Argument list too long

opencv-module / opencv-module-dnn / opencv-module-unifont 三个成员全挂。
根因是 POSIX 上 ninja 用 sh -c "<整条命令>",整条命令是一个 argv 项,
撞 MAX_ARG_STRLEN(128 KiB)。已在 #345 里通过「全平台一律走 response file」修掉。

缺口本身

没有任何一个 CI job 构建 opencv/ffmpeg 这一量级的包。 所有 job 构建的都是
mcpp 自身(几十个 TU)或 e2e 里的合成小工程(个位数 TU)。所以:

  • 链接行长度、rspfile 路径、大 obj 集合的 ninja 图规模 —— 全部零覆盖
  • 任何让对象路径变长、或让链接输入变多的改动,CI 都不会有反应
  • 这类缺陷的失败模态还特别差:ninja 的 Argument list too long 不报是哪条边、
    哪个文件、什么原因

修复前的余量是可测的:opencv-module 的内联链接行本来就已经 56 840 字节,
占 128 KiB 上限的 43% —— 也就是说这条线一直悬着,只是没人看。

判据(建议)

不是「把 opencv 加进 CI」(太慢)。需要的是对链接规模本身的断言,而不是对某个大包的构建:

  1. 一个合成 e2e:生成 N 个源文件(N 足够大,比如 3000),断言构建成功
    —— 这直接覆盖 argv/rspfile 路径,且不依赖任何外部包,跑得也快(可用 -O0 空函数)。
  2. 或者更便宜的:在 ninja backend 的单测里断言"链接命令中不含内联 $in"
    (fix(cache): a package's object layout must not depend on the consumer (#344) #345 已加这条),再补一条 e2e 证明 rspfile 真的被 ninja 执行、且产物正确。

方案 1 是真正覆盖"规模"这个轴的那个;方案 2 只覆盖"形状"。建议至少做 1。

关联

同一族已经第三次了 —— 三次都是靠真实大包在生态侧崩出来,而不是靠 CI。

Activity

  1. speak-agent commented on Aug 5, 2026

    @speak-agent
    Member

    已补上,tests/e2e/191_link_scale.sh(#362,已合入)。

    采用的是本 issue 判据里的方案 1 —— 合成 e2e 直接压规模轴,不依赖任何外部包:

    • 1400 个 C TU,对象清单 140 303 字节,超过 cmdlimits.cppm 中最大的那条命令行上限(128 KiB)
    • 要求它能链接、能运行;main 同时调用对象清单首尾两端的函数,故响应文件被截断会在链接期报未定义符号,而不是产出一个更小的二进制

    区间被断言,而不是被假定。 对象命名、消歧前缀、文件数都会影响清单实际大小,任何一个把它缩回上限以下,测试都会继续通过而不再覆盖任何东西。所以响应文件字节数被直接与上限比较,落回时测试报告「它已不再覆盖它存在的理由」:

      ok: object list is 140303 bytes (1401 objects), past the 131072-byte command-line ceiling
    

    已验证会红:把生成的 cxx_link 规则退回 #345 之前的内联形态,在同一个工程上逐字复现原始症状 —— ninja: fatal: posix_spawn: Argument list too long。

    实测代价(三平台全过):

    平台 耗时
    linux 16.08s
    macOS 29.00s
    windows 45.55s

    文件名做了填充使每个对象路径约 100 字节 —— 用编译时间(昂贵)换路径长度(免费),这才是文件数这么小就能到 128 KiB 的原因;另一侧的边界是 Windows MAX_PATH,实测未触及。

    190 断言生成规则的形状,191 断言规模,两条轴都有覆盖了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions