qemu 11.1.1 鸿蒙PC aarch64 适配实录(签名、RUNPATH 与一个 venv 深坑)
欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
qemu 11.1.1 鸿蒙PC aarch64 适配实录
| 项 | 内容 |
|---|---|
| 对象 | qemu 11.1.1(上游官方版本,riscv64-softmmu 单目标 + 工具链) |
| 环境 | HUAWEI MateBook Pro(HAD-W32)/ HarmonyOS 6.1.0.117(SP68C00E100R13P3)/ aarch64 / Conan 2.29.1(OHOS 适配版) |
| 仓库 | OpenHarmonyPCDeveloper/build_in_harmonyos(AtomGit) |
| PR | #12013 |
| 交付物 | qemu-system-riscv64 系统模拟器 + qemu-img / qemu-io / qemu-nbd 等 7 个 OHOS 签名可执行 |
摘要
qemu 11.1.1 适配鸿蒙 PC aarch64。核心难点不是编译本身,而是三层:构建系统平台识别(meson 不认识 HarmonyOS,且是"静默回退"形态——不报错的错比报错的错难查一个量级)、OHOS 交付双门槛(未签名 ELF 拒载 rc=126、无 RUNPATH 包迁移 rc=127)、CI 环境的 python venv 焊点(env 注入 3 轮全败,读 CPython 源码才定位到 venv 模块无条件 pop 环境变量)。3 个上游补丁(host_os 归一 / socketcan 探测裁剪 / dtc 取源钉死)+ 配方内签名与 RUNPATH 修复 + venv/pip 双 egress 修复。上游 104 例单测真机实跑 = 95 pass / 5 fail / 4 skip(5 fail 逐例归因宿主环境行为差异,零适配缺陷);消费者测试 5/5(4×L1 版本断言 + 1×L2 qcow2 功能往返);CI 6 个有价值轮 2 绿 4 红(4 红全部定位 venv/网络 egress 根因面,逐轮证据行)。PR #12013 已合并入 main(2026-09-29),关联 Issue #3262 随合并关闭。
**qemu 本体编译不是难点——难点是静默回退的平台识别、交付双门槛、CI python 面三处"编译器不报怨"的失败,每一处都要源码级定位才能收敛。
声明(结论边界):
- 上游 104 例中 5 个失败均为宿主运行环境行为与上游 Linux 假设的差异(EPERM/权限归一化类),与 3 个适配补丁的代码变更无关;本文仅记录观察到的错误现象及其分类,不断言 OS 权限策略的设计意图。
- 交付面 = riscv64-softmmu 单 TCG 目标 + 24 项
--disable-*特性裁剪(显示/加速/压缩/用户态网络/密钥等),不是全特性 qemu。 - 全部结论限定于:HarmonyOS PC aarch64 真机(本设备)+ 本构建配置(3 直接依赖 + 裁剪选项)。
1. 背景:为什么值得做
- 生态价值:qemu 是覆盖面最广的开源模拟器。鸿蒙 PC 上运行 RISC-V 系统(riscv64 开源 Linux 发行版等)需要
qemu-system-riscv64这一 riscv64 系统模拟器底座(TCG 纯软件模拟,无 KVM/HVF 硬件虚拟化依赖);qemu-img/qemu-io/qemu-nbd是磁盘镜像格式工具链(qcow2/raw/vmdk 等)与 NBD 网络块设备的生态入口,被大量上层镜像管理工具消费。 - 依赖面(W0 预检):直接依赖 glib/2.84.0、pixman/0.46.4、zlib/1.3.1 全部已发布制品仓(逐一
conan download --only-recipe验证,禁用conan list判 binary);传递依赖 libffi/3.4.4、pcre2/10.40 由 conan 自动解析。零自编译依赖 → 适配面收敛到 qemu 本体。 - 技术新颖性:meson 宿主平台识别(静默回退形态)+ OHOS ELF 交付双门槛(签名 rc=126 / RUNPATH rc=127)+ CI python venv 焊点(CPython 源码级定位)——三者组合构成本文的高难度挑战面。
2. 环境与差异前置
环境表全部值为当事机器实测(或标注来源):
| 项 | 值 | 测量来源 |
|---|---|---|
| 设备 | HUAWEI MateBook Pro(HAD-W32) | param get const.product.model / const.product.manufacturer(实测) |
| 系统 | HarmonyOS 6.1.0.117(SP68C00E100R13P3) | param get const.product.software.version(实测) |
| 内核 | HongMeng Kernel 1.12.0 #1 SMP | uname -a(实测) |
| 架构 | aarch64 | uname -m(实测) |
| Conan | 2.29.1(OHOS 适配版,os=OHOS 为有效枚举) | conan --version(实测) |
| 编译器 | clang 15(hnp,/data/service/hnp/bin/clang),libc++ / c++17 / Release | ci/conan/profiles/ohos-aarch64(os=OHOS / os.version=6.0 / arch=armv8) |
| 上游源 | qemu-11.1.1.tar.xz(141,888,716 字节 ≈ 141.9MB) | conandata.yml;本机 curl -I 实测 HTTP 200 可达(证据挖掘阶段) |
| SHA-256 | 079ffbff8a7111bbc89022107cbabf3bbfd614d5fc9d7cc675991196aca12482 | conandata.yml |
差异表(6 项,第三节逐项展开;每行对应一个坑位):
| # | 差异点 | 上游假设 | 鸿蒙 PC 实际情况 | 对应 |
|---|---|---|---|---|
| 1 | 宿主平台识别 | meson host_os ∈ linux/darwin/windows 分支 | host_os=HarmonyOS 不在任何 Linux 分支 → 静默回退非 Linux 配置(configure 不报错,产物残缺) | 坑 1(patch 0001) |
| 2 | 内核能力探测 | can_socketcan.c feature 探测引用 Linux PF_CAN | 归一化后宿主真身仍是 HarmonyOS(内核头无 CAN 面),探测必须按真宿主判断 | 坑 2(patch 0002) |
| 3 | subproject 取源 | dtc.wrap 为 [wrap-git] 在线 fetch(github) | CI 环境 github 不可达 → 取源失败 | 坑 3(patch 0003 + build() 删 bundled .wrap) |
| 4 | 二进制执行 | 未签名 ELF 可直接执行 | OHOS 拒载未签名 ELF(执行 rc=126 / EPERM) | 坑 4(package() 批量签名) |
| 5 | 动态库定位 | 系统 linker 路径兜底 | meson 不写 RUNPATH → conan 包迁移后依赖库不可定位(rc=127) | 坑 5(generate() rpath 注入) |
| 6 | CI 构建环境 python | 任意 venv 均可用 | CPython venv 在鸿蒙 PC 上 ensurepip 必炸(No module named 'encodings'),env 注入通道被 venv 源码焊死 | 坑 6(venv 深坑,误判) |
3. 适配过程
3.0 侦察(动手前)
- W0 依赖预检:glib/2.84.0、pixman/0.46.4、zlib/1.3.1 逐一
conan download <pkg> -r=ohpcd --only-recipe→ 全部已发布,无需自编译依赖(W0 不过关禁止动手)。 - 构建系统识别:meson(
configure是其兼容包装层)→ 补丁打在meson.build/subprojects/*.wrap,不是 configure 脚本。 - 目标面决策:全特性 qemu = 35+ target × 完整图形栈(gtk/sdl/vnc/opengl 后端),OHOS 侧无对应显示后端 → 裁剪至
--target-list=riscv64-softmmu单 TCG 目标(纯软件模拟,无 KVM/HVF 依赖)+ 24 项--disable-*(显示/加速/压缩/用户态网络/密钥等)。 - 上游测试策略:
meson test --suite unit可离线全量(104 例);qtest/avocado 全量需 guest 磁盘镜像 + KVM/TCG 机器执行 → 不在 OHOS CI 可执行面(4.1 如实声明)。
3.1 依赖树
qemu/11.1.1(conan package_type=application,validate() 限 OHOS + armv8)
├── glib/2.84.0 制品仓预编译(PkgConfigDeps 生成 .pc + rpath 注入)
├── pixman/0.46.4 制品仓预编译
├── zlib/1.3.1 制品仓预编译
└── 传递依赖(conan 自动解析):libffi/3.4.4、pcre2/10.40(glib 依赖)
3.2 坑 1:meson 宿主识别——HarmonyOS 静默落入非 Linux 分支
- 现象:configure 不报错,但生成的构建配置按"非 Linux"处理(Linux-only 模块静默缺失)——不报错的错比报错的错难查一个量级:没有错误行可以 grep,只能靠"产物少了什么"反推。
- 定位:
uname输出 HarmonyOS 字样 → meson 将host_os映射为HarmonyOS→ 不在meson.build的任何 Linux 分支 → 走 else 路径。对比"报错型"平台不识别(config.guess 类),此形态无失败日志,定位靠模块清单 diff。 - 方案(patch 0001,最小改动):
host_os == 'HarmonyOS'时归一化为'linux',同时保留host_os_orig记录原值——归一化给构建系统看,原值给"真宿主判断"留信号(坑 2 直接消费)。 - 经验:构建系统"平台不识别"先分形态——硬报错(好查)vs 静默回退(难查);静默回退用"归一化 + 保留原值",不能直接抹掉原值(抹掉后下游 Linux 专属探测会跟着误判)。
- 入档:与坑 3 合并入档
E6401(phase=configuration,见第五节)。
3.3 坑 2:socketcan 探测——归一化不能抹掉"真宿主"
- 现象:host_os 归一化后,meson feature 探测仍编译
can_socketcan.c——该探测引用 Linux CAN 的PF_CAN,鸿蒙 PC 内核头无此面 → 探测编译失败。 - 定位:
can_socketcan.c是 feature_check 探针,其成立条件应是"宿主内核真支持 CAN";归一化后host_os恒为'linux',单条件判断失真。 - 方案(patch 0002):
host_os == 'linux' and host_os_orig == 'linux'双条件——归一化值管构建分支,原值管内核能力判断,各司其职。 - 经验:归一化型补丁必须留"真宿主"信号(
host_os_orig),否则所有 Linux 专属探测要逐个打补丁;双条件是本案最小正确形态。
3.4 坑 3:subproject 取源——wrap-git 是隐式网络依赖
- 现象:CI 构建在 meson subproject 阶段失败:
dtc.wrap为[wrap-git]指向 github,CI 环境 github 不可达。 - 定位:清点
subprojects/*.wrap——dtc是 wrap-git(在线 fetch,隐式网络依赖);其余 4 个 subproject(keycodemapdb / berkeley-testfloat-3 / libvfio-user / berkeley-softfloat-3)源码已 bundled 在树内,但其.wrap文件仍在(保留即可能仍走 fetch 路径)。 - 方案(双路径):① patch 0003:
dtc.wrap[wrap-git]→[wrap-file],钉死官方 dtc v1.6.1 tarball +source_hash(取源确定性);②build()显式删除 4 个 bundled subproject 的.wrap(CI 日志逐字:Using bundled subproject keycodemapdb (removing keycodemapdb.wrap)等 4 行)——用树内源码,不走网络。 - 经验:meson wrap-git 是隐式网络依赖,闭环境必须 wrap-file + hash 钉死;bundled subproject 的
.wrap要显式移除,“源码在树内"不等于"不会去 fetch”。 - 入档:与坑 1 合并入档
E6401。
3.5 坑 4:未签名 ELF——rc=126 不是权限问题
- 现象:打包产物在鸿蒙 PC 上执行一律 rc=126(EPERM)——初看像文件权限/SELinux 问题,实际是签名拒载。
- 定位:执行失败码 126 = “found but not executable”;对产物做签名状态检查 → 无 OHOS 签名节(
.codesign)→ OHOS 拒载未签名 ELF(与既有知识条目 E077 同族)。 - 方案:
package()阶段_sign_all_elfs()——按\x7fELF魔数递归扫描bin/libexec/lib(跳过符号链接与数据文件,按魔数不按扩展名),每个 ELF 两步:llvm-objcopy --remove-section .codesign(清旧签)→binary-sign-tool sign -selfSign 1(自签)。W3 日志逐字(qemu-img 为例):qemu/11.1.1: RUN: "/data/service/hnp/bin/llvm-objcopy" --remove-section .codesign "…/p/bin/qemu-img" qemu/11.1.1: RUN: "/data/service/hnp/bin/binary-sign-tool" sign -inFile "…/p/bin/qemu-img" -outFile "…/p/bin/qemu-img" -selfSign 1 - 经验:OHOS 交付 ELF 必须签名,rc=126 易误判为权限问题(先看签名状态再看权限);签名是交付前最后一道门槛,属
package()阶段而非build()。 - 入档:与坑 5 合并入档
E6402(phase=linking;E6402 similar_to 既有条目 E077)。
3.6 坑 5:无 RUNPATH——包迁移后 rc=127
- 现象:
conan create打包后,二进制在包目录外执行 rc=127(error while loading shared libraries: libpixman-1.so.0)。 - 定位:
readelf -d→ 无 RUNPATH 节——meson 未写入;系统 linker 路径兜底对 conan 包内依赖不成立(lib 在 conan 包目录,不在系统搜索路径)。 - 方案:
generate()对每个依赖向LDFLAGS追加-Wl,-rpath,<dep.package_folder>/lib(pixman/glib/zlib 逐个注入,conan 包目录为动态路径,generate 期解析)——包迁移不变量:RUNPATH 指向随包走的 lib 目录。 - 经验:交叉/包化 ELF 不能依赖系统 linker 兜底;RUNPATH 必须在
generate()注入且指向 conan 包目录;验证 =readelf -d | grep RUNPATH(本文 4.7 ③ 即该命令)。 - 入档:与坑 4 合并入档
E6402。
3.7 坑 6:venv 深坑——env 注入 3 轮全败,读 CPython 源码才找到焊点(误判)
- 现象(CI 首轮 #59984):qemu 的 meson 构建用 python venv 安装构建期依赖(
qemu.qmp等)→mkvenv的ensurepip子进程崩溃:Fatal Python error: init_fs_encoding: ... ModuleNotFoundError: No module named 'encodings'。崩溃 dump 逐字(#59984 日志):PYTHONHOME = (not set) sys._base_executable = '/data/service/hnp/…/bin/python3' sys.base_prefix = '/storage/Users/currentUser/usr/local' sys.path = ['…/usr/local/lib/python312.zip', '…/usr/local/lib/python3.12', '…/lib-dynload']sys.base_prefix指向一个没有 stdlib 的目录——encodings模块找不到是必然结果。 - 误判(自曝)→ 纠正(三轮递进):
- v1(
shutil.which探测 + PYTHONHOME 注入):判断为"PYTHONHOME 未设/环境传播缺失",探测基础解释器并注入 PYTHONHOME → #59984 dump 仍PYTHONHOME = (not set)——注入没到崩溃进程; - v2(
os.path.isfile确定性探测):换确定性探测再注入 → #60862 dump 仍(not set)。至此三轮(v1 前原始失败 + v1 + v2)dump 恒定not set→ 停止调参,读 CPython 3.12venv标准库源码:venv/__init__.py的_call_new_python()在 spawn 子进程前无条件os.environ.pop('PYTHONHOME')——env 注入通道被 venv 自己焊死,路线结构性不可行(本案转折点:问题不在"注入得对不对",在"通道根本不通"); - v3(pymbin home-landmark,零环境变量):放弃 env 通道,改为二进制级修复——用指向基础 python 真实 home 的 pymbin 包装(home-landmark 定位,不依赖任何环境变量)→ venv 创建成功、ensurepip/pip 开始运行 → 新瓶颈:pip 批量拉取 setuptools/wheel/pip +
qemu.qmp==0.0.6走 PyPI(files.pythonhosted.org)→ CI egress 超时(#61865 日志逐字:ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443)→Could not provide build dependency 'qemu.qmp==0.0.6'); - v4(PIP 社区镜像注入):
PIP_INDEX_URL指向社区 PyPI 镜像 → #61974 全过。
- v1(
- 经验:
- 同症状 3 次 → 读源码:env 注入类修复同症状 3 轮无果,应停止第 4 次探测,直接读解释器标准库找"焊点";
- 崩溃 dump > 错误信息:错误信息说
No module named 'encodings'(果),dump 的sys.base_prefix指向无 stdlib 目录(因)——诊断以 dump 为准; - python 构建依赖是第二网络面:源码 URL 修好 ≠ CI 网络依赖面修完——pip 的 PyPI egress 是独立一面,需要独立镜像策略(与坑 3 的 subproject egress、#60456 的源码 egress 合计 3 面,见 7.2 方法 4)。
4. 验证(分层,禁止相加)
口径声明:4.1 上游 104 例与 4.4 消费者 5 例分别统计、分别陈述,不做相加;4.2/4.3 标注"不适用"(QEMU 无对应场景,不硬造)。
4.1 上游测试实跑(R51 三步法:清点 → 实跑 → 回填)
清点:tests/unit 注册测试 104 例(meson test --suite unit 可离线全量执行);完整 qtest/avocado 套件需 guest 磁盘镜像 + KVM/TCG 机器执行,不在 OHOS CI 可执行面(声明边界,非缩水)。
实跑(2026-09-21 20:06 testlog,OHOS 设备,3 依赖构建配置):104 例 = 95 pass / 5 fail / 4 skip。
5 fail 逐例(实测证据逐字):
| 失败用例 | 实测证据 | 分类 |
|---|---|---|
| qemu:test-replication | bdrv_make_empty() 截断临时 qcow2 文件 → Failed to empty json:{...}: Permission denied(block.c:8284)→ SIGABRT | 宿主文件权限行为差异 |
| qemu:test-io-channel-socket | AF_UNIX bind → Failed to bind socket to test-io-channel-socket.sock: Operation not permitted(util/qemu-sockets.c:1026)→ SIGABRT | 宿主 socket 行为差异 |
| qemu:test-io-channel-file | 权限断言:实际 mode 0o600(384)≠ 期望 0o660(432)(test-io-channel-file.c:69)→ SIGABRT | 宿主文件权限归一化行为差异 |
| qemu:test-util-filemonitor | 文件监控断言 err == 0 不成立(test-util-filemonitor.c:739)→ SIGABRT | 宿主文件事件监控行为差异 |
| qemu:test-char | TAP 止于 ok 4(/char/mux),第 5 项(chardev socket)直接 SIGABRT、无更多输出 | 与 test-io-channel-socket 同机制 |
归因:5 个失败均为宿主运行环境行为与上游 Linux 假设的差异(EPERM/权限归一化类),与 3 个适配补丁的代码变更无关(补丁改 meson host_os 归一 / socketcan 裁剪 / dtc 取源,失败用例均不走这些路径,完整移植在 OHOS 上同样会触发);同一套件在上游标准 Linux CI 通过(基线对照)。
4 skip(宿主环境限制,非适配缺陷):
| 跳过用例 | 原因 |
|---|---|
| qemu:test-crypto-block / test-crypto-cipher / test-crypto-pbkdf | crypto 后端(nettle/gnutls)已禁用(--disable-nettle --disable-gnutls),无可执行子测试 |
| qemu:test-io-channel-command | PATH 中无 socat(fifo 子测试依赖 socat) |
通过覆盖含核心工具链:check-block-qdict、test-base64、test-bitcnt、test-cutils、test-iov、test-keyval、test-mul64、test-qemu-opts 等。上游测试用例修改 = 0。
4.2 断言 1:1 移植
不适用:qemu 上游测试为 meson test 原样执行(0 源修改),不存在独立断言移植层。
4.3 私有 API
不适用:消费者测试仅使用打包二进制的命令行接口(--version / create / info),无库级私有 API 面。
4.4 消费者测试(test_package/test.sh,5/5)
| 用例 | 级别 | 内容 | 断言锚点(grep) |
|---|---|---|---|
| 1 | L1 | qemu-img --version | qemu-img version 11.1.1 |
| 2 | L1 | qemu-system-riscv64 --version | QEMU emulator version 11.1.1 |
| 3 | L1 | qemu-io --version | qemu-io version 11.1.1 |
| 4 | L1 | qemu-nbd --version | 输出含 11.1.1(该工具 banner 无 “version” 字样) |
| 5 | L2 | qemu-img create -q -f qcow2 1M + info 往返 | file format: qcow2 + virtual size: 1 MiB |
设计要点:脚本零 $(...)/反引号——OHOS /tmp 只读(erofs 加固),/bin/sh 的命令替换会在硬编码 /tmp 物化(忽略 TMPDIR);输出捕获一律重定向 $TMPDIR 文件 + grep 断言,$TMPDIR 五级兜底(TMPDIR → TMP → TEMP → $HOME/tmp → $PWD/tmp)。
L1 声明:4 个 --version 用例仅证明"签名 ELF 可加载、RUNPATH 依赖链可解析、可执行",不能宣称功能完成;实质功能验证由用例 5(qcow2 真实 create+info 往返,L2)承担。
实测输出(W3 日志逐字):
ok: qemu_img_version
ok: qemu_system_riscv64_version
ok: qemu_io_version
ok: qemu_nbd_version
ok: qemu_img_create_qcow2_roundtrip (create + info roundtrip)
[test] summary: pass=5 fail=0 (of 5)
HMBS_TEST_PACKAGE_RESULT={"executed":true,"passed":true,"command":"/bin/sh test.sh","discovered":5,"passedCount":5}

图1:鸿蒙 PC 真机 qemu-img 11.1.1 签名产物执行
4.5 产物核验
- 交付物:包
bin/共 7 个可执行——核心交付 4(qemu-system-riscv64 / qemu-img / qemu-io / qemu-nbd,notes 交付物清单)+ 附带工具 3(qemu-pr-helper / qemu-storage-daemon / qemu-edid); - 构建:本地 W3 预验证跑法(5 依赖扩链,见 7.4)ninja
[2680/2680]边全绿;体积(同跑法实测)qemu-system-riscv64 55,900,800 B、qemu-img 9,906,688 B; - L2 smoke 实测:qemu-img / qemu-io / qemu-nbd / qemu-pr-helper / qemu-storage-daemon / qemu-system-riscv64
--version全 OK;qemu-edid--version/--help面异常(该小工具主功能是 EDID 生成,不影响核心交付物主张;CI L2 整体 pass); - 门禁:L0(结构/依赖/版本/分支)/ L4(patches clean)/ L5(bin 产物非空)全 pass;包内 .so 与系统同名库无冲突(G3 隔离);打包 ELF 全签名(坑 4 流程)。
4.6 CI 与评审
完整轮次表(6 个有价值轮;逐轮附根因证据):
| # | 构建号 | 时间 | Worker | 配方状态 | 结果 | 说明(根因发现) |
|---|---|---|---|---|---|---|
| 1 | #59984 | 09-24 20:46 | CI-005 | venv 修复 v1(which 探测 + PYTHONHOME 注入) | ❌ | venv ensurepip No module named 'encodings';dump 实证 PYTHONHOME=(not set) + sys.base_prefix 指向无 stdlib 目录;源码 141.9MB 下载成功(elapsed 807.9s) |
| 2 | #60456 | 09-25 02:41 | CI-022 | 同上 | ❌ | source() 官方源 egress Connection reset by peer (104) ×2 → 源码下载失败(elapsed 45.9s)——同配方不同失败 = CI egress 非确定性;→ conandata.yml 增镜像 URL 列表(官方优先) |
| 3 | #60862 | 09-25 14:55 | CI-036 | venv 修复 v2(isfile 探测)+ conandata 双 URL | ❌ | venv 仍 PYTHONHOME=(not set)(三轮恒定 not set → 读 CPython venv 源码定位焊点);下载成功(elapsed 187.5s) |
| 4 | #61865 | 09-26 17:08 | — | venv 修复 v3(pymbin home-landmark,零环境变量) | ❌ | venv 已过(wraps 生效,pip 开始批量拉包)→ 新瓶颈:PyPI files.pythonhosted.org ReadTimeout → qemu.qmp==0.0.6 不可得(python egress 面) |
| 5 | #61974 | 09-26 18:24→18:39 | CI-028 | + PIP 社区镜像注入 | ✅ PASS | Conan test_package 通过 / L0 结构完整性 通过 / L1 测试执行验证 通过(终态 CI 绿,~15min) |
| 6 | #62694 | 09-27 14:14→14:34 | CI-007 | 仅 PR 正文模板修复(配方未动) | ✅ PASS | 正文-only 变更后复跑仍绿(CI 稳定,~20min) |
注:09-23 首轮(#57540,构建中被新提交取代,PR 评论流无结果评论)首次暴露 venv 问题;09-23 两次 /rebuild 与 09-24 一次触发均未产生结果评论,不占轮次行。
评审记录(时间线):
- 平台 AI 检视(atomgit-bot):P0/P1=0;
- 平台规则审查(pc-pr-review 11 规则):首轮 FAIL(09-27 13:27)——rule1(PR 模板:上游/适配后测试统计表缺合计行 + 复选框格式解析不到)+ rule12(鸿蒙特有测试:适配后统计表缺失,无法脚本化核验);其余 9 规则 PASS(含 rule7 CI 状态 PASS、rule11 评审意见已全部解决);
- 整改:PR 正文按模板补齐双统计表(含合计行)+ 复选框标准格式 → 复跑 PASS(2026-09-27/28);
- 合并记录:PR #12013 于 2026-09-29合并入 main;关联 Issue #3262 随合并自动关闭。

图2:PR #12013 合入页
4.7 复现速查
前置:build_in_harmonyos 仓库 + OHOS 适配版 conan(社区源)+ 制品仓已发布的 glib/2.84.0、pixman/0.46.4、zlib/1.3.1。
① 全量构建 + 消费者测试(CI 同口径,CI 实测 ~15-20min):
cd build_in_harmonyos
conan create archives/q/qemu/11.1.1 -pr:h=ci/conan/profiles/ohos-aarch64 -pr:b=ci/conan/profiles/ohos-aarch64
期望:test_package 5/5([test] summary: pass=5 fail=0 (of 5))+ HMBS_TEST_PACKAGE_RESULT passed=true + L1/L2/L4/L5 全 pass(CI #61974 同口径)。
② 上游单测套件(需 ① 的 conan 构建树;口径 = 适配期真机实测记录值):
meson test --suite unit
# 期望:104 = 95 pass / 5 fail / 4 skip(5 fail 逐例归因见 4.1;4 skip = crypto×3 + socat×1)
③ 产物版本 / RUNPATH 核验(秒级,与图1 同命令):
BIN=$(ls -dt $HOME/.conan2/p/b/qemu*/p/bin | head -1) # ① 产出的包 bin 目录
$BIN/qemu-img --version
# 期望:qemu-img version 11.1.1(+ Copyright 行)
/data/service/hnp/bin/readelf -d $BIN/qemu-img | grep RUNPATH
# 期望:RUNPATH 含 3 个依赖包 lib 目录(pixman/glib/zlib 序 = generate() rpath 注入序;
# 本地 readelf 实测格式见证据清单 E-54 / ADJ-6)
口径对应:① → 4.4/4.5(消费者 5/5 + L 门禁)② → 4.1(104 = 95/5/4)③ → 4.5(签名 ELF 可执行 + RUNPATH 依赖定位)。这是本文数字的完整复现命令集。
5. 知识沉淀
| 条目 | 知识(错误签名/要点) | 来源坑位 | 复用价值 |
|---|---|---|---|
| E6401(draft) | meson host_os 不识别 HarmonyOS 静默回退 + SDK 工具链 PATH 注入 + wrap-git 闭环境不可达 → 归一化保留原值 / wrap-file 钉 hash / bundled .wrap 移除(phase=configuration) | 坑 1 / 坑 3 | 所有 meson 项目的 OHOS 适配(平台识别 + 取源面) |
| E6402(draft) | 打包 ELF 未签名 rc=126 EPERM + meson 不写 RUNPATH 包迁移 rc=127 → package() 批量签名(objcopy 清签 + binary-sign-tool selfSign)+ generate() rpath 注入(phase=linking) | 坑 4 / 坑 5 | 所有 OHOS aarch64 多 ELF 交付配方(similar_to 既有 E077) |
状态:2 条 draft 随 PR 入仓 knowledge/drafts/(E6401 prerequisite_of E6402),待主编 promote 转正。坑 6(venv 深坑)为 CI 构建环境级问题,已固化为配方内修复(pymbin wraps + PIP 社区镜像注入),未单独立 E 条目。
6. FAQ
Q1:5 个上游失败 = 没适配成功?
不是。4.1 逐例归因:全部为宿主运行环境行为与上游 Linux 假设的差异(EPERM/权限归一化类),3 个补丁的改动路径不覆盖失败用例;同一套件在上游标准 Linux CI 通过。零适配缺陷。
Q2:为什么只交付 riscv64 单目标?
全特性 qemu = 35+ target × 完整图形栈,OHOS 侧无对应显示后端(gtk/sdl/vnc/opengl 全禁)→ 裁剪至 --target-list=riscv64-softmmu 单 TCG 目标(纯软件模拟,无 KVM/HVF 依赖)。多目标扩展属后续独立任务。
Q3:24 项 --disable- 裁剪,功能缩水吗?*
裁剪的是本平台无后端/无依赖面的特性(显示/加速/压缩/用户态网络/密钥等);核心模拟能力(TCG riscv64)+ 磁盘工具链(qemu-img/io/nbd)完整。nettle/libslirp 扩链已在工作树预验证(7.4),启用后 3 个 crypto skip 用例转入可执行面。
Q4:CI 4 红 2 绿,红的都是环境问题?
逐轮证据(4.6 表):#59984/#60862 = venv 机制面(env 通道焊死,两轮修复收敛到源码焊点);#60456 = 源码 egress reset;#61865 = PyPI egress 超时。4 红全部定位到"venv 机制 + 网络 egress"两个根因面,非配方缺陷;后 2 轮绿含一次正文-only 复跑(配方未动仍绿)。
Q5:venv 坑为什么叫"深坑"?
3 轮 env 注入全败才定位到 CPython venv 模块源码焊点(_call_new_python() 无条件 pop('PYTHONHOME'))——env 路线结构性不可行;修复后又暴露 PyPI egress 第二网络面。"同症状 3 次 → 读源码"是本文最值钱的一条方法。
Q6:消费者 5 例能证明什么、不能证明什么?
L1×4 = 签名 ELF 可加载 + RUNPATH 链可解析 + 可执行(不能宣称功能完成);L2×1 = qcow2 create+info 真实功能往返。guest 系统完整启动验证不在本设备可执行面(声明)。
7. 总结
7.1 量化盘点
| 维度 | 数字 |
|---|---|
| 上游补丁 | 3 个(meson host_os 归一 / socketcan 双条件裁剪 / dtc wrap-file 钉 hash) |
| 上游测试 | 104 例 = 95 pass / 5 fail / 4 skip(5 fail 全归因宿主环境行为差异,零适配缺陷) |
| 上游测试修改 | 0 |
| 消费者测试 | 5/5(4×L1 版本断言 + 1×L2 qcow2 往返) |
| CI | 6 个有价值轮:2 绿(#61974 终态 + #62694 复跑)+ 4 红(全部定位 venv/egress 根因面,逐轮证据) |
| 交付物 | 7 个可执行(核心 4 + 附带 3),全部 OHOS 签名 |
| 依赖 | 3 直接(glib/pixman/zlib,制品仓已发布)+ 2 传递(libffi/pcre2) |
| 知识沉淀 | 2 条 draft(E6401/E6402,随 PR 入仓) |
7.2 可复用方法(5 条)
- 静默回退识别:构建系统"平台不识别"先分形态——硬报错 vs 静默回退;静默回退用"归一化 + 保留原值"(
host_os_orig),给下游 Linux 专属探测留真宿主信号; - 同症状 3 次读源码:env 注入类修复同症状 3 轮无果 → 停止调参,读解释器/构建系统标准库源码找"焊点"(本案
venv模块 pop 焊点); - 崩溃 dump > 错误信息:
No module named 'encodings'是果,dump 的sys.base_prefix指向无 stdlib 目录是因——诊断以 dump 为准; - 网络 egress 面清单:源码 URL / subproject 取源 / python pip 依赖 = 3 个独立网络面,逐一给镜像/hash 钉死策略,修一个不等于修完;
- OHOS 交付 ELF 双门槛:签名(rc=126)+ RUNPATH(rc=127)——
package()阶段统一过门槛(魔数扫描 + 清签 + 自签 + rpath 注入),readelf双验证。
7.3 流程 checklist(通用)
- W0 依赖预检(逐项
conan download --only-recipe,禁用conan list判 binary) - 平台识别先分形态:硬报错 vs 静默回退(归一化保留原值)
- meson wrap 取源面清点:wrap-git 全部替换 wrap-file + hash 钉死;bundled
.wrap显式移除 - 网络 egress 3 面清单:源码 / subproject / pip(逐一镜像或钉死)
- 同症状 3 次 → 读源码(停止调参)
- OHOS ELF 双门槛:签名 + RUNPATH(package() 统一处理 + readelf 验证)
- 上游测试三步法:清点 → 实跑(全量、不抽样)→ 回填(失败逐例归因)
- 消费者测试 L1/L2 分级声明(
--version不能宣称功能完成) - CI 红轮不删,逐轮根因证据行
- PR 正文双统计表含合计行(pc-pr-review rule1/rule12 脚本化核验口径)
7.4 后续工作
- 依赖扩链:nettle/3.10.2.1 + libslirp/4.9.3 已在工作树预验证(W3 跑法 2680 边全绿 + 消费者 5/5,L0i 5 依赖实测)——按 R37 版本号后缀(11.1.1.1)另提 PR 发布;启用后 3 个 crypto skip 用例转入可执行面;
- 多目标与显示后端:x86_64/arm 等 softmmu 目标扩展、OHOS 图形栈对接显示后端,属后续独立任务(不在本 PR 范围);
- qemu-edid 小工具:
--version/--help面在本地 W3 实测异常(4.5),不影响核心 4 交付物(CI L2 整体 pass),待后续定位。
参考链接
- PR:https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos/merge_requests/12013
- Issue:https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos/issues/3262
- 仓库:https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos
- 上游源码(截至发稿 实测 HTTP 200 可达):https://download.qemu.org/qemu-11.1.1.tar.xz
- QEMU 官网:https://www.qemu.org/
- CI 终态结果页:https://ohpcd.atomgit.com/ci?id=61974
更多推荐

所有评论(0)