欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/

欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper

项目值
目标库vinyl 9.0.1(Vinyl Cache,varnish 系高性能 HTTP 缓存/加速器)
适配环境HUAWEI MateBook Pro(HAD-W32)· HarmonyOS 6.1.0.117(SP68C00E100R13P3)· aarch64 真机
仓库 / 分支OpenHarmonyPCDeveloper/build_in_harmonyos · feat/vinyl-9.0.1
PR / Issue!18188 / #4665

摘要:本文记录把 varnish 系高性能 HTTP 缓存 vinyl 9.0.1 适配到鸿蒙 PC(aarch64 真机)并合入主仓库的完整过程。这次适配"反直觉":库运行时代码 0 修改,13 个可移植性补丁全部集中在它私有测试工具链 vtest2 的线程取消机制在平台上缺失的部分(用信号模拟取消重建 pthread_cancel,含 musl TCB cleanup 的内联汇编处置)与一系列 HMDFS 文件系统语义坑位。上游全量 VTC 测试共 1012 项(其中 core 929 + vmod 82 + contrib 1),真机逐项全量实测:920 PASS / 40 SKIP / 52 FAIL(除 SKIP 94.65%,含 SKIP 90.91%)——52 项 FAIL 全部为平台限制(其中 UDS MAC 拒绝 49 + HMDFS chmod 被忽略 1 + TUI 超时 2),0 项适配问题失败;消费者用例(真实公开 API + 结果断言)1/1 通过。CI 共走 5 轮(4 轮作废/失败 + 1 轮绿),AI 评审首轮 5 项意见闭环 + 终推复审 0 阻塞 4 建议,本地独立审计 3 轮通过,PR !18188 于 2026-10-28 合入 main。

vinyl 是 varnish-cache 的直接继任者,库本体(epoll 事件循环、worker pool、HTTP/2、VCC 编译器)是标准可移植 C 代码——920 项通过的测试证明了它在鸿蒙 PC 上运行时路径完整可用。真正的难度在别处:它的私有测试框架 vtest2 依赖 pthread_cancel 做线程超时取消,而平台压根不提供这个 API;为了让 1012 项测试套件跑起来,必须用 POSIX 信号"重实现"整套取消机制——重实现过程中还踩中 musl 把 pthread_cleanup 条目放在调用者栈上的暗坑(基线 28 项测试段错误)。另有 49 项用例被平台 MAC 策略直接封死 unix socket,CI 环境缺失的文档工具链又制造了一次首红。下文是这场"测试框架适配"的完整实录:每个坑、每次误判、每处修复都可溯源。

声明(细节见对应章节):

  • make check 全量 1012 项未集成进 conanfile build()(全量耗时远超 CI 构建预算,且本平台 jobserver 不可用);全量执行采用逐项 harness(与 make check 等价,每项独立日志),已在 test_package/MANIFEST.yml 如实声明(§4.1)。
  • sphinx HTML 文档站点不构建(制品仓无 sphinx 配方;配方将 sphinx-build 检查降级并跳过 doc/ 子目录,28 个 man 页保留、由 docutils 正常生成,§3.6)。
  • 52 项 FAIL 全部为平台限制(内核 MAC 策略 / HMDFS 语义 / harness 超时),非适配缺陷,逐项定性附证据(§4.1)。

1. 背景:为什么做这个库

1.1 vinyl 是什么

vinyl-cache(Vinyl Cache)是 varnish 系的高性能 HTTP 缓存/加速器:继承 varnish-cache 的架构(epoll 驱动事件循环、多进程 worker pool、VCL 配置语言 + 内置 VCC 编译器、vmod 动态模块)。产物为 libvinylapi 公开 API 动态库 + vinyld 缓存守护进程(sbin)+ 一组 CLI 工具(vinylstat / vinyltop / vinyllog / vinyladm / vinylhist / vinylncsa)。上游源:https://vinyl-cache.org/downloads/vinyl-cache-9.0.1.tgz(sha256=2e8ec67cd213ea6864c763939d64912025557342fad2a5ffda6c7c5b59bdeb17,与官方 release 页一致;2026-11-08 真机 curl HEAD 200)。

1.2 为什么值得适配(三层论证)

  1. 生态价值:varnish 系是 Linux 生态 HTTP 加速/缓存的经典方案,鸿蒙 PC 的开发者生态里缺本地 HTTP 缓存代理组件;vinyl 以库(conan 配方 + 预编译二进制)形式补齐 aarch64-OHOS 制品仓的这个位置。
  2. 有真实先例:varnish 系在 Linux 生产环境长期运行(epoll/worker pool 路径成熟),内核 ABI 与 GNU/Linux aarch64 兼容,移植到鸿蒙 PC 是可达目标而非投机——920 项通过的测试(含 epoll/worker pool/HTTP2 路径全覆盖)是验证结果。
  3. “高难度挑战”:难度集中在测试工具链与平台语义,而非库本体——vtest2 私有测试工具链强绑定 pthread_cancel(平台不提供、无跨平台抽象层,命中 C 条件①);修复需内联汇编读 musl TCB 头(命中 C 条件③,R8 声明例外);全量测试成本极高(1012 项逐项执行远超 CI 构建预算,命中 C 条件④)。依赖链反而小(外部运行时依赖 3 个),所以整体难度画像清晰、可审查。

2. 环境与差异前导

2.1 环境表(真机实测)

项值实测方式
设备HUAWEI MateBook Pro(型号 HAD-W32)param get const.product.name / param get const.product.model
系统HarmonyOS 6.1.0.117(SP68C00E100R13P3)param get const.product.software.version
内核HongMeng Kernel 1.12.0 #1 SMP(2026-04-29 构建)uname -a
架构aarch64uname -m
构建工具链Conan 2.29.1(OHOS 适配版,来自社区 PyPI 源)conan --version
编译器clang 15 + libc++,C++17,Release(CI profile:os=OHOS/6.0,arch=armv8,可执行文件 /data/service/hnp/bin/clang{,++})conan profile show -pr ci/conan/profiles/ohos-aarch64
目标三元组aarch64-unknown-linux-ohosconfigure 实际行为
上游源https://vinyl-cache.org/downloads/vinyl-cache-9.0.1.tgz(curl HEAD 200)curl -sI
构建耗时≈5.5 分钟(干净源码全量重建 + 消费者测试;no-leak 仿真日志起点 18:11: → 终止 ≈18:17,分钟级精度)no-leak 仿真日志首行时间戳 + 文件终止时间

口径说明:profile 里 os.version=6.0 是 OHOS API 版本口径;系统行的 HarmonyOS 6.1.0.117 是"关于本机"操作系统版本——两者口径不同,不构成矛盾。

2.2 上游假设 vs 鸿蒙 PC 现实(差异表)

把上游代码/构建系统里"在鸿蒙 PC 上不成立"的隐含假设全部列出,每一项都对应 §3 的一个坑或 §4.1 的一条平台限制——后文按此表逐个展开,不藏任何一个:

#上游假设鸿蒙 PC 现实影响落点
D1pthread_cancel 可用未提供(pthread.h 无声明、libc 无符号)测试框架超时取消机制失效§3.5(最大坑)
D2config.guess/sub 认识三元组aarch64-unknown-linux-ohos 不识别configure 平台检测失败§3.2 坑 1
D3硬链接可用EOPNOTSUPPbuild 规则 ln 失败§3.2 坑 2
D4ncurses 依赖提供 -lncurses制品仓 ncurses/6.4 仅 libncursesw.aconfigure 的 -lncurses 探测失败§3.2 坑 3(shim)
D5上游代码不触发新警告OHOS clang 对 fread 等产生 unused-result 警告(上游 -Werror)make 失败§3.3
D6测试代码变量读取有活路conan Release 工具链注入 -DNDEBUG,编译掉 assert()-Werror,-Wunused-but-set-variable 致死§3.3
D7安装规则带 $(DESTDIR)上游 install-data-local 规则不带 $(DESTDIR)状态目录落绝对路径 /var(Permission denied)§3.3
D8mktemp -d 安全临时目录可写toybox mktemp -d 建 2700 目录 + HMDFS 按目录映射属主 uid(.conan2 缓存树 = 20001006)+ chmod 为 no-opconfig.status 建不出临时目录§3.4(坑:本地侥幸通过)
D9python3-docutils 预装(rst2man/rst2html 硬检查)CI 环境未预装CI 首红(真实死因)§3.6(坑:本地假阳性)
D10sphinx-build 可用制品仓无配方(conan list sphinx/* → 0)sphinx HTML 文档站点跳过§3.6
D11UDS unix socket 可用平台 MAC 拒绝 bind/connect(EPERM)49 项 VTC 失败§4.1(无解)
D12chmod 生效no-op(E046:rc=0 但模式不变)1 项 VTC(b00084)§4.1(无解)
D13make -j jobserver 可用mkfifo EPERM(E074)串行构建(-j1)§3.1 配方 make 参数
D14/tmp 可写只读(E002)必须设置 $TMPDIR§4.1 测试环境
D15terminfo 齐全仅 xterm-256color需 cp 补 xterm§4.1 测试环境

15 项差异的处理分布:10 项由补丁/配方解决(D1–D10,其中 D4/D5/D6/D7 是配方 generate() 层处理,其余走补丁);D11/D12 用户空间无解,构成 52 项 FAIL 的主体;D13 以串行构建绕开(配方 make -j1);D14/D15 由测试环境配置满足。下面 §3 对"需要动手"的 7 个坑逐一展开,其中 4 个主坑按"现象 → 定位 → 修复 → 结论"四段式写。

3. 适配过程

3.1 侦察与全局

动手前先做两件事(W0 依赖预检 + 测试策略),决定了后面所有工作的形状。

依赖预检(W0):vinyl 的依赖链很小,适配前逐个 conan download ... -r=ohpcd --only-recipe 实测,4 项全部已在制品仓(CI 绿轮 #106723 的 L0i 门禁日志里也是 4 个 [ok]),无适配阻塞:

vinyl/9.0.1(autotools,shared)
├── pcre2/10.48         运行时依赖(包内静态库,VCC 正则)
├── libedit/20240817    运行时依赖(包内静态库,vinyladm/vinyltop 行编辑)
├── ncurses/6.4         运行时依赖(包内仅 libncursesw.a,见 §3.2 坑 3)
└── docutils/0.23       构建依赖(tool_requires,bin/ 注入构建 PATH 提供 rst2man/rst2html,见 §3.6)

测试策略:上游测试入口是 make check(vtest2 框架,1012 个 .vtc)。两个现实约束:① 全量 1012 项逐项跑,耗时远超 CI 构建预算,无法集成进 conanfile build();② 本平台 HMDFS 禁 mkfifo(EPERM),make 的 jobserver 并行通道不可用,make check 本身也跑不动。策略定为:全量执行采用逐项 harness(./vinyltest -v -i <X.vtc>,与 make check 相同的 CWD/参数,每项独立日志留证),口径在 test_package/MANIFEST.yml 如实声明;CI 侧由 test_package 消费者用例承担实质验证(R34)。

坑位地图:13 个补丁对应 7 个坑(§3.2 三个基础坑 + §3.3–§3.6 四个主坑),补丁 → 坑的映射:

坑补丁主题难度
10009 / 0010config.guess/sub 三元组识别低
20001 / 0002硬链接 → cp低
3(无补丁,配方 generate())ncurses 库名 shim低
①(无补丁,配方 generate())编译参数 + 安装模型(statedir/TMPDIR)中
②0011(hunk 2)config.status 临时目录中(隐蔽:本地侥幸通过)
③0003–0008pthread_cancel → 信号模拟取消高(最大坑,含 musl TCB 暗坑)
④0011(hunk 1)/ 0012 / 0013文档工具链(rst2man/sphinx)中(隐蔽:本地 W3 假阳性)

3.2 基础适配(三个低难度坑,快讲)

坑 1:三元组识别(补丁 0009/0010)。上游 config.guess/sub 不认识 aarch64-unknown-linux-ohos,configure 平台检测直接失败。修复是标准 autotools 平台检测适配:两个脚本各加一个 case 分支,把 aarch64-*-linux-ohos 映射为 aarch64-pc-linux-gnu(内核 ABI 兼容 GNU/Linux aarch64)。这是全项目最"无聊"的补丁,没有之一。

坑 2:硬链接(补丁 0001/0002)。上游 build 规则用 ln 硬链接生成 vtest → vinyltest 两个入口名;HMDFS 不支持硬链接(EOPNOTSUPP 实测)。把 ln 改成 cp(Makefile.am 与 Makefile.in 同步改,补丁 0002 是 0001 的 .in 镜像)。

坑 3:ncurses 库名 shim(配方 generate(),非补丁)。制品仓 ncurses/6.4 包内只有宽字符版 libncursesw.a,而 vinyl configure 探测 -lncurses。在配方 generate() 里做 shim:在构建目录(build_folder 私有路径,R49)内建 libncurses.a → libncursesw.a 符号链接,并把该目录加进 -L。不碰上游文件、不污染系统路径,configure 探测自然通过。

3.3 主坑①:编译参数与安装模型(无补丁,配方 generate())

这个坑是三个小坑的集合,且都属于"本地验证能过、干净构建才死"的隐蔽型——根因是 conan fork 工具链的注入模型与上游假设不一致。

现象(干净 conan create 时按序出现):

  1. OHOS clang 对 fread 等函数产生 unused-result 警告,上游 -Werror 把警告变致命错误;
  2. 上游测试代码(vbm_test.c 等)的变量读取点全在 assert() 内,而 Release 工具链(conan fork toolchain 注入)带 -DNDEBUG,把 assert 编译掉 → 变量"set but unused",-Werror,-Wunused-but-set-variable 致死;
  3. install 阶段 install-data-local 规则建状态目录 ${localstatedir}/lib/vinyl-cache,该规则不带 $(DESTDIR);conan 安装模型是 prefix=/ + DESTDIR=<pkg> → 状态目录落绝对路径 /var,Permission denied;
  4. 附一个隐患:本机 /tmp 只读(E002),config.status 模板里 ac_tmp=$TMPDIR/.,TMPDIR 未设时落根目录不可写(报错 could not setup config files machinery)。

定位:三处共因都是"上游假设普通 Linux 工具链环境",而 conan fork 工具链在 C 侧注入 -O3、Release 注入 -DNDEBUG,安装模型是 prefix=/ + DESTDIR 重定向。本地验证构建之所以能过:① 本地构建无 NDEBUG,assert 还活着;② 本地安装靠 DESTDIR staging 重定向;③ CWD 在 uid 映射一致的目录。也就是说"本地通过"只验证了参数空间的一半——这条教训在 §3.4/§3.6 又演了两次,是全篇最重要的方法论。

修复(全部在配方 generate()/build() 内,不碰上游代码):

  • -fPIC(共享库必需);
  • -Wno-error=unused-result——只降权该警告类(不全局撤 -Werror,保留上游的警告纪律);
  • -Wno-error=unused-but-set-variable——同样只降权该类(成因:-DNDEBUG 编译掉 assert 读取点);
  • --with-statedir=<package_folder>/var/lib/vinyl-cache——用上游官方 configure 选项把状态目录指进包内(空目录入包无害,运行时状态目录由 vcl/命令行 --state-dir 决定);
  • build() 内设 TMPDIR=<build_folder>/tmp(conan 构建目录天然可写;本 conan fork 无 extra_env 通道,走 os.environ、子进程继承已实证,R33 偏离已在 PR 披露)。

结论:干净 conan create configure/make/install 全过,状态目录随包落到 <pkg>/var/lib/vinyl-cache(p/ 树可见)。这三处是"工具链模型 vs 上游假设"的错位,全部在配方层解决——这也是 Conan 配方的边界感:平台差异优先进配方,只有机制本身缺失才动上游。

3.4 主坑②:config.status 临时目录(补丁 0011 hunk 2)

现象:干净 conan create 时 config.status 建不出临时目录,configure 报 cannot create a temporary directory in .(上游 configure 的原文错误消息),直接死在平台检测之后的第一步。

定位(核心是两组对照实测 + 一次误判):

  • 实测一:toybox 的 mktemp -d 创建 2700 权限目录,而 HMDFS 的目录属主 uid 按目录映射(.conan2 缓存树映射为 20001006,home tmp 树映射为 20020090)——当 CWD 在 .conan2 树时,2700 目录的映射属主 ≠ 进程自身 uid,进程不可写(Permission denied);
  • 实测二:chmod 在 HMDFS 上是 no-op(E046:rc=0 但模式不变)——"建了再修权限"的路走不通;
  • 对照:普通 mkdir 被 HMDFS 强制成 2771(组可写),进程可正常写入;
  • 误判(自曝):早期本地验证构建里这一步侥幸通过了——当时 CWD 在 home tmp 树,uid 映射恰好一致,700 目录属主就是自己。如果拿"本地通过"当判据,这个补丁根本不会存在。识别手段只有一个:在干净环境(conan 缓存树 CWD)重跑 conan create,让问题 100% 复现。"本地通过"只证明参数命中了环境的幸运角落,不证明配方正确——§3.6 的 CI 首红是同一教训的完整版。

修复(补丁 0011 hunk 2,改 configure 内嵌的 config.status 模板):

-  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  tmp=`(umask 077 && mkdir -p "./conf$$-vinyl") 2>/dev/null` &&

改普通 mkdir -p(HMDFS 强制 2771、可写),保留原有 fallback 结构(失败时仍走原 ./conf$$-$RANDOM 路径),临时目录清理沿用原 trap。

结论:conan 干净构建(CWD 在 .conan2 缓存树)config.status machinery 通过;对上游普通 Linux 行为无损(umask 077 下 mkdir -p 的 700 语义与原 mktemp -d 等价)。这个坑沉淀了一条通用知识(manifest.yaml knowledge_gained ①):HMDFS 下"mktemp -d 2700 + 目录映射属主 uid"是一切 autotools 包 config.status 的通用陷阱,不是 vinyl 专属——下一个在鸿蒙 PC 上编 autotools 包的人可以直接抄这个判定过程。

3.5 主坑③:pthread_cancel → 信号模拟取消(补丁 0003–0008,最大坑)

这是本次适配的主难度,也是路径 C 判定的核心:平台不提供 pthread_cancel(pthread.h 无声明、libc 无符号),而 vtest2 的 reset/stop 路径用"pthread_cancel + pthread_join"模式做线程超时取消——5 个线程体(logexp / dispatch / dispatch_wrk / sess / syslog)+ 5 个 pthread_cancel 调用点。不重建这套机制,测试框架既编译不过也链接不过,1012 项测试一项都跑不了。

现象:vtest2 首次构建即链接失败(pthread_cancel 符号缺失)。这不是"换个等价 API"能绕的——平台上这个机制压根不存在。

修复(协议设计):用 POSIX 信号重建(SIGUSR2 + sigsetjmp/siglongjmp)。SIGUSR2 在 vtest2 里无其他用途(全框架只用了 SIGPIPE),且 pthread_kill 与 POSIX 信号在所有 vtest2 构建目标上都存在,替换本身可移植:

  • vtc_thread_cancel(tp):首次调用从主线程装 SIGUSR2 handler(不带 SA_RESTART,才能中断 read/accept/poll 等阻塞 I/O),然后 pthread_kill(tp, SIGUSR2);
  • 线程体协议:开头 sigprocmask 屏蔽 SIGUSR2 → sigsetjmp(jmp, 1)(save-sigmask=1,longjmp 时恢复屏蔽掩码)→ arm → 工作体 → disarm;
  • handler 把目标线程 longjmp 出阻塞 syscall,线程体在取消路径上干净退出(显式 vtc_logclose 后 return),模拟 pthread_cancel()+cleanup 的语义。

补丁分布:0003(vtc.h 协议声明)+ 0004/0006/0007/0008(5 个线程体包裹)+ 0005(vtc_misc.c 取消核心)。0005 核心代码(真实补丁摘录):

static void
vtc_cancel_sig(int sig)
{
	(void)sig;
	if (vtc_cancel_armed) {
		vtc_cancel_armed = 0;	/* consumed once: no re-entry */
		vtc_cancel_discard_cleanups();
		siglongjmp(vtc_cancel_jmp, 1);
	}
	vtc_cancel_pending = 1;	/* pre-arm edge: arm() retries */
}

void
vtc_thread_cancel(pthread_t tp)
{
	static int inited;
	struct sigaction sa;

	if (!inited) {
		sigemptyset(&sa.sa_mask);
		sa.sa_flags = 0;	/* no SA_RESTART: interrupt blocking I/O */
		sa.sa_handler = vtc_cancel_sig;
		(void)sigaction(SIGUSR2, &sa, NULL);
		inited = 1;
	}
	return (pthread_kill(tp, SIGUSR2));
}

协议看起来"语义等价"了,但跑全量时它还不是——下面两个子问题,一个是我踩出来的(musl TCB 段错误),一个是 AI 评审指出来的(pre-arm 窗口)。

子坑 A:musl TCB cleanup 悬空 → 基线 28 项段错误(自曝,反汇编定位)

信号模拟取消就位后,全量执行暴露新问题:基线 28 项测试(27 core + 1 vmod)全部 signal=11(段错误),崩溃点一致落在 pthread_exit 开头。定位四步:

  1. 崩溃指令统一是 blr x10 @ pthread_exit+0x50——在 LIFO 执行一个函数指针;
  2. 结合 musl 实现怀疑 cleanup 条目:pthread_cleanup_push 把 {func, arg, prev} 条目写在调用者栈上,并链入 TCB 头;
  3. 关键推理:siglongjmp 展开栈后,这些栈上条目悬空(指向已被复用的栈槽),pthread_exit 开头 LIFO 执行残留条目时解引用垃圾函数指针跳飞——段错误;
  4. 实证:反汇编 /lib/ld-musl-aarch64.so.1,_pthread_cleanup_push 与 pthread_exit 的 TCB 头偏移一致 = TPIDR_EL0 - 280(musl aarch64 平台事实,无可移植 API 获取)。

修复:handler 在 siglongjmp 前清空 TCB cleanup 头(补丁 0005,全项目唯一内联汇编,R8 声明例外,conandata.yml patch_description + notes.md 双处声明):

#if defined(__aarch64__)
	void *tp;

	asm volatile("mrs %0, tpidr_el0" : "=r"(tp));
	*(void **)((char *)tp - 280) = NULL;
#endif

为什么"清空"是安全的:longjmp 后仍链着的条目必然全部悬空(push/pop 同函数配对、都在 sigsetjmp 点之上),清空 = 丢弃;它们本要释放的资源(per-session http 状态)泄漏至进程退出,对测试进程可接受。

结论:基线 28 项段错误全转 PASS(与基线逐项 diff 确认:27 core + directors_c00013),1012 项全量自此可运行。内联汇编被 #if defined(__aarch64__) 包裹,仅影响测试框架、不随库发布。

子坑 B:AI 评审指出的两处协议缺陷(评审修复)

PR 提交后,atomgit-bot AI 评审首轮指出信号模拟取消还有两处协议级缺陷——均采纳修复,修复后全量 1012 项回归重跑 + W3 全绿:

  1. pre-arm 取消丢失窗口(P2):pthread_cancel 是状态型请求(挂起至首个取消点),信号模拟是边沿型事件——pthread_create 到线程体 arm 的窗口内投递的取消请求,会被 handler 静默消费(armed=0),取消丢失,调用点 pthread_join 挂死至 harness 超时。修复:vtc_cancel_pending(TLS)记录 pre-arm 请求,vtc_cancel_arm() 解除屏蔽后 discard_cleanups + longjmp 补偿重试,恢复状态型语义;同时 handler longjmp 前置 armed=0(一次性消费),longjmp 后的二次信号(收尾路径双 cancel)变 no-op,不再二次跳死亡栈帧。
  2. logexp 早退路径未 disarm(P3):i==2 && err_arg 早退原跳过 disarm,armed 残留=1 且 SIGUSR2 未屏蔽——reset 路径并发 cancel 可在 pthread_exit 窗口内 longjmp 到正在销毁的栈帧(UB)。修复:对齐"所有退出分支 disarm"契约。

第三条 AI 评审意见(“#if defined(__aarch64__) 仅约束架构不约束 libc”)经评估不采纳并已在 PR 回复理由:本配方仅构建 OHOS aarch64/musl(三元组固定 aarch64-unknown-linux-ohos),-280 偏移是该 libc 反汇编实证的平台事实;musl 无可移植宏可检测,强加守卫反增脆弱。

3.6 主坑④:文档工具链与 CI 首红(补丁 0011 hunk 1 + 0012/0013)

这是"本地假阳性 → CI 首红"的完整案例,也是本 PR 时间线上最戏剧化的一段。

现象:PR 推上 CI 后,#104274(2026-10-26 14:20)与 #104429(15:43)两轮均死在 configure 阶段——上游 configure 对三个文档工具的硬检查:

# 上游 configure 原文(补丁前):
as_fn_error $? "rst2man is needed to build Vinyl Cache, please install python3-docutils." ...
as_fn_error $? "sphinx-build is needed to build Vinyl Cache, please install python3-sphinx." ...

死点在最前端的 rst2man 检查。

定位(含误判自曝):本地 W3 为什么全绿、CI 却红?——本机泄漏。本机 ~/usr/local/bin 里躺着早先 pip 预装的 rst2man + sphinx-build 全家,而 CI profile 的 PATH 恰好硬编码了这个路径:本地构建"借用"了机器上的工具,W3 的绿是假阳性。CI worker 是干净环境,没有 python3-docutils,configure 在第一个检查就死。识别手段:用去掉泄漏 PATH 行的同款 profile + --build=vinyl* 强制源码重建做 no-leak 全量 CI 仿真,并 env -i 实测 CI 基础 PATH 确无 rst2man——本地立刻复现 CI 的红。

修复(能走官方机制的走机制,缺失的才补丁):

  1. rst2man/rst2html → tool_requires docutils/0.23:制品仓已发布(recipe + OHOS 二进制均可消费,conan download 实测),conan 自动将其 bin/ 注入构建 PATH——no-leak 仿真实证:干净 PATH 下 configure 从 docutils 包解析到 rst2man,28 个 man 页正常生成;
  2. sphinx-build → 降级(补丁 0011 hunk 1):制品仓无 sphinx 配方(conan list sphinx/* → 0),硬错误降为 configure WARNING;
  3. 跳过 sphinx/graphviz 子目录(补丁 0012/0013):doc/Makefile.{am,in} 的 SUBDIRS 清空——sphinx 子目录需 sphinx-build、graphviz 子目录需 dot(亦缺失);doc/ 自身无 install 产物,changes.html 仍由 docutils rst2html 构建,包内容零损失。

结论:no-leak 全量仿真 conan create exit 0 + test_package 1/1,包内 man 页实测 man1×8 + man3×10 + man7×10 = 28 个,与旧 11 补丁包逐文件一致(无内容回退)。已知限制如实披露:sphinx HTML 文档站点不构建(doc/ 无任何 install 产物,属文档站点而非库功能)。

时间线(当天):14:20 CI 首红 → 15:43 复跑同死 → 18:17 本地 no-leak 仿真绿 → 22:06 推送 13 补丁修复 → 22:11 CI #105430 又红(worker 磁盘满 ENOSPC,基础设施故障,作废)→ 次日 10:09 #106723 绿。这个"本地绿 ≠ CI 绿"的教训与 §3.4 同源:干净环境是唯一的判据。

4. 验证(分层)

口径声明:本节分层给证据——4.1 上游测试(1012 项全量实测,真机逐项 harness);4.2 消费者用例(1 项,L2 真实公开 API + 结果断言);4.3 产物核验(库/符号面/man 页);4.4 CI 与评审记录(5 轮 CI + 2 轮 AI 评审 + 3 轮本地审计 + 合入);4.5 复现速查(3 条命令可直接跑)。各层数字口径独立,不互相折算:1012 项是上游测试口径,1 项是消费者口径,两者相加的 1013 只在 4.4 的合入语境里出现一次。

4.1 上游测试:1012 项全量实测

按 R51 三步法:清点 → 实跑 → 如实回填。

① 清点(声明 N):上游测试入口 make check(vtest2 框架),.vtc 文件共 1012 个 = core 929(bin/vinyltest/vtest2/tests/,a.vtc~v.vtc)+ vmod 82(bin/vinyltest/vmod/tests/)+ contrib 1(contrib/,vinylstatdiff)。本次实测 N’ = 1012,无少报。

② 实跑(方式与口径):全量执行采用逐项 harness——./vinyltest -v -i <X.vtc>,与 make check 相同的 CWD/参数,每项独立日志留证。不直接用 make check 的原因:HMDFS 禁 mkfifo(jobserver 不可用,E074)+ 全量 1012 项耗时远超 CI 构建预算。口径已在 test_package/MANIFEST.yml 如实声明。测试环境要求:$TMPDIR 必须设置(/tmp 只读)、terminfo 需 cp xterm-256color → xterm、vmod 测试需 LD_LIBRARY_PATH 指向 libvinylapi .libs 目录。

③ 结果(如实回填):

目录总数PASSSKIPFAIL
core9298404049
vmod827903
contrib1100
合计10129204052

通过率:920/972 = 94.65%(除 SKIP);920/1012 = 90.91%(含 SKIP)。

52 项 FAIL 逐项定性(全部平台限制,0 适配问题失败项):

类别数量定性代表项
UDS unix socket MAC 拒绝49(core 46 + vmod 3)平台 MAC/策略层直接拒绝 unix socket bind/connect(EPERM):server socket 监听 44 + daemon CLI socket 5;另有 python socket.bind EPERM 独立实测佐证。内核/策略层封锁,用户空间无解a00002-06、c00087-94、d00032-38、r03159、unix_c00000 等
HMDFS chmod 被忽略1(b00084)chmod no-op(E046:rc=0 但模式不变),用例 find -perm 模式匹配失败b00084
TUI 作业超时2(u00008/u00009)vinyltop 交互 TUI 被 harness 60s 作业超时杀死(signal=9);TUI 需终端会话,headless 不适用u00008、u00009

40 项 SKIP 为上游显式条件跳过(测试框架退出码 77 语义,feature 前置条件不满足),与上游行为一致,非适配引入。

归属判定:三类失败均为平台内核/策略层 + 文件系统语义 + harness 超时限制,非 OHOS 适配层引入——1012 项全部实际执行、920 项通过(epoll/worker pool/HTTP2 路径全覆盖),库运行时代码 0 修改,适配改动集中在测试框架(vtest2 取消机制)与构建系统,不改变 920 通过项所验证的库代码路径行为。

关键回归验证(两轮全量):

  • 基线(信号模拟取消修复前)的 28 项段错误(signal=11)经 §3.5 修复后全部转 PASS(与基线逐项 diff:27 core + directors_c00013);
  • AI 评审修复后全量回归重跑(2026-10-23,1012 项逐项 harness,与基线同口径):918 PASS / 40 SKIP / 54 FAIL——基线 52 项平台限制失败全部复现(逐项集合对照:无 FAIL→PASS、无缺失),新增 2 项 v00003/v00022 为时延敏感用例(后端健康轮询 Poll timeout / CLI 交互 4.7s),隔离重跑各 3/3 PASS(共 6/6),判定负载抖动非回归(同 r01801 先例口径,已记入 test-report.md)。

证据留档:reports/test-report.md(逐项明细 + 证据)+ 每项独立日志(本地,gitignore 不入 PR)。

4.2 消费者用例(新增 1 项,L2:真实公开 API + 结果断言)

test_package/test.c 模拟业务上层组件(HTTP 服务)调用 libvinylapi 的对外公开 API(安装头位于 <pkg>/include/vinyl-cache/):用 VSB 字符串缓冲构造一个 HTTP 响应,再用 VSHA256 计算其内容摘要——验证编译通过、链接通过(-lvinylapi)、运行通过,且摘要与独立参考值一致(可检出 VSB/VSHA256 语义回归)。完整代码(真实文件,AI 评审后含硬断言版本):

/*
 * 消费者用例:模拟业务上层组件(HTTP 服务)调用 vinyl 对外公开 API
 * (libvinylapi,安装头位于 <pkg>/include/vinyl-cache/):
 *   - VSB 字符串缓冲:构造 HTTP 响应
 *   - VSHA256:计算内容摘要
 * 验证目标:编译通过、链接通过(-lvinylapi)、运行通过,且摘要与
 * 独立参考值一致(可检出 VSB/VSHA256 语义回归)。
 */
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include <vdef.h>
#include <vsb.h>
#include <vsha256.h>

int
main(void)
{
	struct vsb *vsb;
	VSHA256_CTX ctx;
	unsigned char digest[VSHA256_LEN];
	char hex[VSHA256_LEN * 2 + 1];
	unsigned int i;
	static const char body[] = "hello from vinyl consumer";
	/* 独立参考值:下方组装出的精确响应串
	 * ("HTTP/1.1 200 OK\r\n" + "Content-Length: 25\r\n\r\n" + body)
	 * 的 SHA256,用独立实现于用例编写时计算。 */
	static const char expect[] =
	    "503956e52411410a23993982a6bfe62003ad4de400acbea3ec2383fe46ad14a8";

	vsb = VSB_new_auto();
	if (vsb == NULL) {
		fprintf(stderr, "consumer: VSB_new_auto failed\n");
		return 1;
	}
	VSB_printf(vsb, "HTTP/1.1 200 OK\r\n");
	VSB_printf(vsb, "Content-Length: %u\r\n\r\n",
	    (unsigned int)(sizeof(body) - 1));
	VSB_cat(vsb, body);
	if (VSB_finish(vsb) != 0) {
		fprintf(stderr, "consumer: VSB_finish failed\n");
		VSB_destroy(&vsb);
		return 1;
	}

	VSHA256_Init(&ctx);
	VSHA256_Update(&ctx, VSB_data(vsb), (size_t)VSB_len(vsb));
	VSHA256_Final(digest, &ctx);

	for (i = 0; i < VSHA256_LEN; i++)
		(void)snprintf(hex + 2 * i, 3, "%02x", digest[i]);
	if (strcmp(hex, expect) != 0) {
		fprintf(stderr, "consumer: sha256 mismatch:\n"
		    "  got  %s\n"
		    "  want %s\n", hex, expect);
		VSB_destroy(&vsb);
		return 1;
	}

	printf("consumer: %.*s\n  sha256=%s\n",
	    (int)VSB_len(vsb), VSB_data(vsb), hex);

	VSB_destroy(&vsb);
	return 0;
}

设计要点:参考值 503956e5...46ad14a8 是用独立实现对用例将组装出的精确响应串算出的 SHA256——AI 评审指出"test.c 无断言、测试不能失败"后补上:摘要不符即非零退出,VSB/VSHA256 的语义回归从此可被检出(R34 实质验证)。

实测输出(真机运行,rc=0):

consumer: HTTP/1.1 200 OK
Content-Length: 25

hello from vinyl consumer
  sha256=503956e52411410a23993982a6bfe62003ad4de400acbea3ec2383fe46ad14a8

conan 侧收束输出(no-leak 全量仿真日志):

[100%] Built target test_vinyl
    Start 1: test_vinyl
1/1 Test #1: test_vinyl .......................   Passed    0.03 sec
100% tests passed, 0 tests failed out of 1

在这里插入图片描述

图1:conan create 全绿收束
证明配方自包含——干净源码构建成功 + 消费者用例 1/1 通过(支撑 §3 收束 + §4.2)

4.3 产物核验

包内产物(p/ 树,2026-11-08 真机实测):lib/libvinylapi.so(.so.3 / .so.3.1.0 版本链)+ include/vinyl-cache/ 公开头 + bin/(CLI 工具)+ sbin/(vinyld)+ share/man/(28 个 man 页:man1×8 + man3×10 + man7×10)+ var/lib/vinyl-cache/(状态目录空目录,§3.3)。

符号面核验(nm -D libvinylapi.so.3,2026-11-08 实测,消费者所用 10 个符号全部导出):

0000000000050d04 T VSB_new_auto@@LIBVINYLAPI_3.0
00000000000512e8 T VSB_printf@@LIBVINYLAPI_3.0
000000000005103c T VSB_cat@@LIBVINYLAPI_3.0
0000000000051494 T VSB_finish@@LIBVINYLAPI_3.0
00000000000514e0 T VSB_data@@LIBVINYLAPI_3.0
00000000000514e8 T VSB_len@@LIBVINYLAPI_3.0
0000000000051570 T VSB_destroy@@LIBVINYLAPI_3.0
0000000000051fa8 T VSHA256_Init@@LIBVINYLAPI_3.1
0000000000051fc4 T VSHA256_Update@@LIBVINYLAPI_3.1
0000000000052a30 T VSHA256_Final@@LIBVINYLAPI_3.1

构建耗时:干净源码全量重建 + 消费者测试 ≈5.5 分钟(no-leak 仿真日志,分钟级精度)。

4.4 CI 与评审记录

CI 完整轮次(5 轮:4 作废/失败 + 1 绿):

轮次时间(+08:00)结果死因/说明
#10393010-26 11:53失败(作废)网络/基础设施故障,非配方问题
#10427410-26 14:20失败configure 死于 rst2man 硬检查(旧 SHA,11 补丁)——真实首红,死因见 §3.6
#10442910-26 15:43失败同上(旧 SHA 复跑)
—10-26 22:06—推送 13 补丁修复(5fd03e1533)
#10543010-26 22:11失败(作废)worker 磁盘满 OSError ENOSPC,38s 死在并行下载线程池初始化,未进 configure——基础设施故障
#10672310-27 10:09绿conan test_package 通过 + L0/L1 门禁通过,全部步骤 ✅

AI 评审(atomgit-bot,两轮):

  • 首轮 5 项意见:4 采纳修复(pre-arm 取消丢失窗口 P2 / logexp 早退未 disarm P3 / test.c 未释放 VSB P3 / test.c 无断言 P3)+ 1 回复不采纳(__aarch64__ 守卫,理由见 §3.5 子坑 B);另有 1 条行内意见(0006 主线程未屏蔽 SIGUSR2)由 P2 统一吸收修复(同根因,pending 标志后三种投递时序全闭环),2 条 diff 评论已标记 resolved;
  • 终推后复审(10-27 11:46):0 阻塞 + 4 建议(P2×2:vtest2 siglongjmp 锁泄漏/自死锁风险;P3×2:vtc_cancel_arm pending 分支、mktemp 可预测性)——均为测试框架层潜在风险观察项,测试框架不随库发布,不阻断合入。

本地独立审计(W4,3 轮全 pass):

轮次时间范围判定P0/P1/P2/P3
R110-2321 文件(评审修复后重审)pass0/0/0/6
R210-2623 文件最终态(含 0012/0013)pass0/0/0/6
R310-2723 文件pass0/0/1/4(P2 为 R8 声明例外观察项)

审计由上下文隔离子任务执行(避免自审盲区),报告附 23 文件 sha256 证据;R3 结果已发 PR 讨论区(10-27 12:32)。

合入记录:PR !18188 于 2026-10-28 17:21:35(+08:00)合入 main(审批人 ningyu405,squash merge,head 5fd03e1533372c7e18479641c1a3bb4d040ea816);关联 Issue #4665(【高难度挑战】vinyl 9.0.1,10-23 提交)随 PR 合入自动关闭。
在这里插入图片描述

图2:PR !18188 合入页

4.5 复现速查(3 条命令,均可在本文环境直接跑)

以下命令路径均为本文环境(HUAWEI MateBook Pro,用户 currentUser)的绝对路径,命令来自真实构建日志;期望输出已与实测日志核对(耗时数字会浮动,以 PASS/行内容为判定)。

① 全量构建 + 消费者测试(对应 §3 收束 / §4.2;构建约 5–6 分钟):

/storage/Users/currentUser/.local/bin/conan create /storage/Users/currentUser/ohpc-contest/vinyl-9.0.1/build_in_harmonyos/archives/v/vinyl/9.0.1 -pr:h=/storage/Users/currentUser/ohpc-contest/vinyl-9.0.1/build_in_harmonyos/ci/conan/profiles/ohos-aarch64 -pr:b=/storage/Users/currentUser/ohpc-contest/vinyl-9.0.1/build_in_harmonyos/ci/conan/profiles/ohos-aarch64 --build=missing --user=ohpcd --channel=stable

期望输出(尾部,与 no-leak 仿真日志一致):

vinyl/9.0.1@ohpcd/stable: Package '28a4bdb887734fbd11bc65c772fe6e2f0acd7d15' built
...
1/1 Test #1: test_vinyl .......................   Passed    0.03 sec
100% tests passed, 0 tests failed out of 1

口径说明:conan create 语义即从干净源码重建被测包,--build=missing 仅作用于依赖(4 个依赖均从 ohpcd 制品仓下载,不从源码构建)。

② 上游证据链复跑(代表性单项)(对应 §4.1;全量 1012 项需逐项 harness 运行,单项 6 秒):

export TMPDIR=/storage/Users/currentUser/tmp/vtc-repro && cd /storage/Users/currentUser/.conan2/p/b/vinyl4bd431604e6ee/b/build-release/bin/vinyltest && ./vinyltest -v -i /storage/Users/currentUser/.conan2/p/b/vinyl4bd431604e6ee/b/bin/vinyltest/vtest2/tests/a00000.vtc

期望输出(尾部,2026-11-08 实跑 rc=0):

#    top  TEST /storage/Users/currentUser/.conan2/p/b/vinyl4bd431604e6ee/b/bin/vinyltest/vtest2/tests/a00000.vtc passed (5.668)

a00000.vtc 是 vtest 框架自测(core 套件首项)。换任意其他 .vtc(如 b 系列、c 系列)同法复跑;UDS 类的 49 项会按 §4.1 定性以 EPERM 失败——那正是平台限制的复现。

③ 产物/符号面核验(对应 §4.3):

nm -D /storage/Users/currentUser/.conan2/p/b/vinyl4bd431604e6ee/p/lib/libvinylapi.so.3 | grep -E 'VSB_new_auto|VSB_printf|VSB_cat|VSB_finish|VSB_data|VSB_len|VSB_destroy|VSHA256_Init|VSHA256_Update|VSHA256_Final'
ls /storage/Users/currentUser/.conan2/p/b/vinyl4bd431604e6ee/p/share/man/man1 | wc -l && ls /storage/Users/currentUser/.conan2/p/b/vinyl4bd431604e6ee/p/share/man/man3 | wc -l && ls /storage/Users/currentUser/.conan2/p/b/vinyl4bd431604e6ee/p/share/man/man7 | wc -l

期望输出(2026-11-08 实测):10 行符号(VSB_*@@LIBVINYLAPI_3.0 ×7 + VSHA256_*@@LIBVINYLAPI_3.1 ×3,与 §4.3 代码块一致)+ man 页数 8 10 10。

口径映射:① 验证"配方自包含 + 消费者 1/1"(§4.2 的 1 项);② 验证"上游测试真机可跑"(§4.1 的 1012 项之代表性单项);③ 验证"产物完整"(§4.3 的 10 符号 + 28 man 页)。

5. 知识沉淀

本次适配沉淀 3 条通用知识(落点:manifest.yaml knowledge_gained 字段,随配方入仓):

#知识来源坑复用价值
①HMDFS 按目录映射属主 uid:toybox mktemp -d 建的 2700 目录在 .conan2 缓存树不可写(普通 mkdir 强制 2771 组可写、chmod 无效 E046)§3.4 config.status 临时目录一切 autotools 包在鸿蒙 PC 上都会遇到 config.status 临时目录问题,判定过程(2700/2771 对照 + 映射 uid 实测)可直接复用
②conan fork toolchain 安装模型 = prefix=/ + DESTDIR=<pkg>:上游不带 $(DESTDIR) 的绝对路径安装规则(如 ${localstatedir})必须用官方 configure 选项重定向到包内§3.3 statedir一切 autotools 包在 conan 安装模型下都会遇到同类问题,"先找官方选项重定向、再考虑补丁"的顺序可复用
③Release 工具链注入 -DNDEBUG 会编译掉上游测试代码 assert() 内的变量读取点 → -Werror,-Wunused-but-set-variable 致死,须按警告类降权§3.3 编译参数conan Release 构建上游带测试代码的包时的通用编译期陷阱

草稿状态说明:本次 PR 未提交 knowledge/drafts/ 的 E 编号草稿——路径 C 的 PR 文件白名单只有 archives/ 目录,知识按归档规范沉淀在 manifest.yaml knowledge_gained;适配期间遇到的错误模式均命中既有知识库条目(E002 /tmp 只读、E046 HMDFS chmod 忽略、E074 jobserver/mkfifo、E1129 per-file 补丁规范),无新增错误模式需入库。路径 C 特有的经验(信号模拟取消协议设计 + musl TCB 处置,§3.5)完整记录在 notes.md 与 PR 正文,供评审与后续同类适配参考。

6. FAQ

Q1:为什么 make check 没集成进 conanfile build()?
两个原因:① 全量 1012 项耗时远超 CI 构建预算;② 本平台 HMDFS 禁 mkfifo(EPERM),make 的 jobserver 并行通道不可用,make check 本身跑不动。全量执行改为逐项 harness(与 make check 等价:相同 CWD/参数,每项独立日志),并在 test_package/MANIFEST.yml 如实声明 upstream_test_in_build: false 与原因。CI 侧由消费者用例承担实质验证(R34)。

Q2:52 项 FAIL 是不是适配问题?
不是。逐项定性全部为平台限制:UDS unix socket 被平台 MAC 拒绝 49 项(另有 python socket.bind EPERM 独立实测佐证,内核/策略层封锁,用户空间无解)、HMDFS chmod 被忽略 1 项(E046:rc=0 但模式不变)、TUI 作业超时 2 项(vinyltop 需终端会话,headless 不适用)。判定依据:库运行时代码 0 修改,920 项通过(含 epoll/worker pool/HTTP2 路径),适配改动集中在测试框架与构建系统,不改变通过项所验证的库代码路径行为。

Q3:内联汇编读 TCB 偏移 -280 安全吗?可移植吗?
它是 musl aarch64 的平台事实(反汇编 /lib/ld-musl-aarch64.so.1 实证:_pthread_cleanup_push 与 pthread_exit 的 TCB 头偏移一致),无可移植 API 获取——这正是它只能写成内联汇编的原因。安全边界:#if defined(__aarch64__) 包裹 + 本配方仅构建 OHOS aarch64/musl(三元组固定)+ 仅影响测试框架、不随库发布 + R8 例外已在 conandata.yml patch_description 与 notes.md 双处声明。AI 评审"仅约束架构不约束 libc"的意见经评估不采纳(理由见 §3.5 子坑 B)。

Q4:消费者 1/1 通过能证明什么?不能证明什么?
能证明:libvinylapi 公开 API(VSB/VSHA256)的编译、链接、运行链路完整,且语义与独立参考值一致(有硬断言,回归可检出)。不能证明:vinyld 守护进程的完整运行时功能——daemon 的 CLI socket 路径被平台 UDS MAC 限制封死(49 项 FAIL 的主体),这部分边界在 §4.1 如实披露。

Q5:13 个补丁为什么一处 __OHOS__ 平台宏都没有?
因为全部补丁都是标准可移植性修复:三元组映射是 shell case 分支(0009/0010)、硬链接改 cp 是构建规则(0001/0002)、信号模拟取消用的是所有 POSIX 平台都有的 pthread_kill/信号机制(0003-0008)、临时目录/sphinx/SUBDIRS 是构建脚本层(0011/0012/0013)。唯一例外是 0005 的 #if defined(__aarch64__) 内联汇编块(musl TCB 偏移,R8 声明例外,仅测试框架不随库发布)。

7. 总结

7.1 量化盘点

项数据
补丁13 个(其中初版 11 个 + CI 首红修复新增 2 个:0012/0013;0011 后扩为 2 hunk,其中 hunk 1 为 CI 修复新增)
库运行时代码修改0(13 个补丁全部落在测试框架 / 构建系统 / configure)
上游测试全量 1012 项实测(920 PASS / 40 SKIP / 52 FAIL;除 SKIP 94.65%,含 SKIP 90.91%)
52 FAIL 归属全部平台限制(UDS 49 + chmod 1 + TUI 2),0 适配问题失败项
消费者用例1/1(100%,真实公开 API + 独立参考值硬断言)
CI5 轮(2 轮配方相关失败:rst2man 首红 ×2 + 2 轮基础设施作废:网络/磁盘满,第 5 轮 #106723 绿)
AI 评审首轮 5 项(4 采纳 + 1 回复不采纳,另 1 行内由 P2 吸收);终推复审 0 阻塞 + 4 建议
本地独立审计3 轮全 pass(P0=0 / P1=0)
知识沉淀3 条(manifest knowledge_gained)
结果PR !18188 于 2026-10-28 17:21:35 合入 main;Issue #4665 同刻关闭

7.2 可复用方法(从本次适配提炼,按迁移价值排序)

  1. 干净环境交叉验证(来自 §3.6 假阳性 + §3.4 侥幸通过):本地 W3 绿不等于配方对——本机 PATH 泄漏能让文档工具链检查假通过,uid 映射巧合能让临时目录问题潜伏。判据只有一个干净环境:去泄漏 profile + --build=包* 强制源码重建 + env -i 验证基础 PATH。任何"本地过了但环境里有可疑便利"的信号,都值得做一次 no-leak 仿真。
  2. 逐项 harness 等价执行(来自 §4.1):上游测试套件庞大、且平台约束(jobserver 不可用)让 make check 跑不动时,按"相同 CWD/参数、每项独立日志"逐项跑 harness,口径如实写进 MANIFEST——既保住全量覆盖,又不骗 CI。
  3. tool_requires 补齐构建工具链依赖(来自 §3.6):构建期用的外部工具(rst2man 这类)不要假设环境预装,配方里显式声明 tool_requires 让 conan 注入 PATH;能走官方机制(依赖注入)解决的,才降级/跳过检查(补丁 0011 hunk 1 + 0012/0013 的"降级+跳过"双保险)。
  4. 边沿补偿协议(来自 §3.5 子坑 B):用边沿型信号机制替代状态型 pthread_cancel 时,必须补 pre-arm 窗口的 pending 记录 + arm 时补偿重试 + handler 一次性消费,否则取消语义在时序上不等价——这是信号模拟取消这类移植的通用设计检查点。
  5. 反汇编实证平台事实(来自 §3.5 子坑 A):musl TCB 偏移没有可移植 API,唯一可靠来源是反汇编 libc 实证(两个函数对同一偏移达成一致)+ 声明例外 + 架构宏守卫。平台事实类代码的三件套:实证、声明、守卫。

7.3 过程清单(做完的,供同类任务对照)

  • W0 依赖预检(4 依赖 conan download 实测全可消费)
  • 上游测试三步法(清点 1012 → 逐项 harness 实跑 → 如实回填)
  • 13 个可移植性补丁(0 处 __OHOS__;唯一 __aarch64__ 为 R8 声明例外)
  • 消费者用例(L2 真实公开 API + 独立参考值硬断言,1/1)
  • no-leak 全量 CI 仿真(exit 0 + man 页 28 个逐文件一致)
  • W4 独立审计 3 轮(上下文隔离子任务,附 sha256 证据)
  • AI 评审闭环(首轮 5 项 + 复审 4 建议)
  • PR 提交(积分模板六板块)→ CI 5 轮 → 合入
  • 知识沉淀 3 条(manifest knowledge_gained)

7.4 后续工作

  • sphinx HTML 文档站点:待 ohpcd 制品仓有 sphinx 配方后可恢复(当前 0011 hunk 1 + 0012/0013 跳过,doc/ 无 install 产物,包内容无损失);
  • daemon 运行时全路径验证:49 项 VTC 被平台 UDS MAC 限制封死,vinyld 的 CLI socket 全路径待平台策略放开后补验;
  • make -j 并行:待平台支持 mkfifo(E074)后可去掉 -j1 串行;
  • 2 项时延敏感用例(v00003/v00022):负载抖动型不稳定(隔离重跑 6/6 PASS),后续可考虑在 harness 层加重试。

参考链接

  • PR !18188:https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos/merge_requests/18188
  • Issue #4665(路径 C 候选申请,已关闭):https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos/issues/4665
  • 代码仓库:https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos
  • 上游官网:https://vinyl-cache.org/
  • 上游源码(sha256=2e8ec67cd213ea6864c763939d64912025557342fad2a5ffda6c7c5b59bdeb17):https://vinyl-cache.org/downloads/vinyl-cache-9.0.1.tgz
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐