欢迎加入开源鸿蒙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 SMPuname -a(实测)
架构aarch64uname -m(实测)
Conan2.29.1(OHOS 适配版,os=OHOS 为有效枚举)conan --version(实测)
编译器clang 15(hnp,/data/service/hnp/bin/clang),libc++ / c++17 / Releaseci/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-256079ffbff8a7111bbc89022107cbabf3bbfd614d5fc9d7cc675991196aca12482conandata.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)
3subproject 取源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 注入)
6CI 构建环境 python任意 venv 均可用CPython venv 在鸿蒙 PC 上 ensurepip 必炸(No module named 'encodings'),env 注入通道被 venv 源码焊死坑 6(venv 深坑,误判)

3. 适配过程

3.0 侦察(动手前)

  1. W0 依赖预检:glib/2.84.0、pixman/0.46.4、zlib/1.3.1 逐一 conan download <pkg> -r=ohpcd --only-recipe → 全部已发布,无需自编译依赖(W0 不过关禁止动手)。
  2. 构建系统识别:meson(configure 是其兼容包装层)→ 补丁打在 meson.build / subprojects/*.wrap,不是 configure 脚本。
  3. 目标面决策:全特性 qemu = 35+ target × 完整图形栈(gtk/sdl/vnc/opengl 后端),OHOS 侧无对应显示后端 → 裁剪至 --target-list=riscv64-softmmu 单 TCG 目标(纯软件模拟,无 KVM/HVF 依赖)+ 24 项 --disable-*(显示/加速/压缩/用户态网络/密钥等)。
  4. 上游测试策略: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 模块找不到是必然结果。
  • 误判(自曝)→ 纠正(三轮递进):
    1. v1(shutil.which 探测 + PYTHONHOME 注入):判断为"PYTHONHOME 未设/环境传播缺失",探测基础解释器并注入 PYTHONHOME → #59984 dump 仍 PYTHONHOME = (not set)——注入没到崩溃进程;
    2. v2(os.path.isfile 确定性探测):换确定性探测再注入 → #60862 dump 仍 (not set)。至此三轮(v1 前原始失败 + v1 + v2)dump 恒定 not set → 停止调参,读 CPython 3.12 venv 标准库源码:venv/__init__.py 的 _call_new_python() 在 spawn 子进程前无条件 os.environ.pop('PYTHONHOME')——env 注入通道被 venv 自己焊死,路线结构性不可行(本案转折点:问题不在"注入得对不对",在"通道根本不通");
    3. 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');
    4. v4(PIP 社区镜像注入):PIP_INDEX_URL 指向社区 PyPI 镜像 → #61974 全过。
  • 经验:
    • 同症状 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-replicationbdrv_make_empty() 截断临时 qcow2 文件 → Failed to empty json:{...}: Permission denied(block.c:8284)→ SIGABRT宿主文件权限行为差异
qemu:test-io-channel-socketAF_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-charTAP 止于 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-pbkdfcrypto 后端(nettle/gnutls)已禁用(--disable-nettle --disable-gnutls),无可执行子测试
qemu:test-io-channel-commandPATH 中无 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)
1L1qemu-img --versionqemu-img version 11.1.1
2L1qemu-system-riscv64 --versionQEMU emulator version 11.1.1
3L1qemu-io --versionqemu-io version 11.1.1
4L1qemu-nbd --version输出含 11.1.1(该工具 banner 无 “version” 字样)
5L2qemu-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#5998409-24 20:46CI-005venv 修复 v1(which 探测 + PYTHONHOME 注入)❌venv ensurepip No module named 'encodings';dump 实证 PYTHONHOME=(not set) + sys.base_prefix 指向无 stdlib 目录;源码 141.9MB 下载成功(elapsed 807.9s)
2#6045609-25 02:41CI-022同上❌source() 官方源 egress Connection reset by peer (104) ×2 → 源码下载失败(elapsed 45.9s)——同配方不同失败 = CI egress 非确定性;→ conandata.yml 增镜像 URL 列表(官方优先)
3#6086209-25 14:55CI-036venv 修复 v2(isfile 探测)+ conandata 双 URL❌venv 仍 PYTHONHOME=(not set)(三轮恒定 not set → 读 CPython venv 源码定位焊点);下载成功(elapsed 187.5s)
4#6186509-26 17:08—venv 修复 v3(pymbin home-landmark,零环境变量)❌venv 已过(wraps 生效,pip 开始批量拉包)→ 新瓶颈:PyPI files.pythonhosted.org ReadTimeout → qemu.qmp==0.0.6 不可得(python egress 面)
5#6197409-26 18:24→18:39CI-028+ PIP 社区镜像注入✅ PASSConan test_package 通过 / L0 结构完整性 通过 / L1 测试执行验证 通过(终态 CI 绿,~15min)
6#6269409-27 14:14→14:34CI-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 往返)
CI6 个有价值轮: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 条)

  1. 静默回退识别:构建系统"平台不识别"先分形态——硬报错 vs 静默回退;静默回退用"归一化 + 保留原值"(host_os_orig),给下游 Linux 专属探测留真宿主信号;
  2. 同症状 3 次读源码:env 注入类修复同症状 3 轮无果 → 停止调参,读解释器/构建系统标准库源码找"焊点"(本案 venv 模块 pop 焊点);
  3. 崩溃 dump > 错误信息:No module named 'encodings' 是果,dump 的 sys.base_prefix 指向无 stdlib 目录是因——诊断以 dump 为准;
  4. 网络 egress 面清单:源码 URL / subproject 取源 / python pip 依赖 = 3 个独立网络面,逐一给镜像/hash 钉死策略,修一个不等于修完;
  5. 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 后续工作

  1. 依赖扩链:nettle/3.10.2.1 + libslirp/4.9.3 已在工作树预验证(W3 跑法 2680 边全绿 + 消费者 5/5,L0i 5 依赖实测)——按 R37 版本号后缀(11.1.1.1)另提 PR 发布;启用后 3 个 crypto skip 用例转入可执行面;
  2. 多目标与显示后端:x86_64/arm 等 softmmu 目标扩展、OHOS 图形栈对接显示后端,属后续独立任务(不在本 PR 范围);
  3. qemu-edid 小工具:--version/--help 面在本地 W3 实测异常(4.5),不影响核心 4 交付物(CI L2 整体 pass),待后续定位。

参考链接

Logo

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

更多推荐