ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

【鸿蒙PC适配经验分享 | Zstandard:内核/数据库/包管理新一代 压缩选型落地开源鸿蒙】

【鸿蒙PC适配经验分享 | Zstandard:内核/数据库/包管理新一代 压缩选型落地开源鸿蒙】

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

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

本文记录 Zstandard(zstd)1.5.6 在 HarmonyOS PC(AArch64)上的适配、Conan 制品交付与消费者验证全过程。文中的测试数字均来自实际执行日志,宿主回归、交叉编译与 CI 门禁分层表述,不把未验证的结论写成"全量通过"。

本文适配成果已合入开源鸿蒙 PC 仓库:build_in_harmonyos / archives/z/zstd/1.5.6 ,包含 Conan 配方、test_package 消费者测试与一键复测脚本 run_upstream_tests.sh。

适配 MR 评审与合入记录:【积分赛】fix(zstd): 1.5.6 修复 conandata.yml 源码 sha256 哈希值错误 #3578

一、先看结论

项目结果
上游项目Zstandard(zstd)
上游源码版本v1.5.6
官方源码地址https://github.com/facebook/zstd
源码 SHA-2568c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1
目标平台HarmonyOS PC / AArch64(OHOS_ARCH=arm64-v8a)
适配路径路径 A(基础适配),Conan 配方交付
上游测试2731 项实测,2730 通过,通过率 99.96%
新增测试test_package:dlopen libzstd.so 校验ZSTD_versionNumber符号导出
CI 门禁conan create/ test_package / L0 结构完整性 / L1 测试执行验证 全部通过
交付状态已合入 main,CI 双通道(CI + REL)全绿

一句话总结:zstd 1.5.6 以 Conan 配方交付,上游 2731 项测试在宿主侧实测 99.96% 通过(唯一失败项为 root 环境问题,非库缺陷),并新增 1 项鸿蒙特有消费者测试验证共享库可被dlopen加载。

二、为什么是 Zstandard:fan-in 35 的"压缩机底座"

Zstandard 由 Yann Collet(xxHash、LZ4 作者)与 Meta 开源,BSD-3 许可,2016 年发布。它的设计目标是把"压缩比"和"压缩速度"从二选一变成一把可调的滑尺:

  • 1~22 级压缩等级:从实时场景(每秒数百 MB)到极致压缩(逼近 LZMA 的比率),一个参数自由权衡;
  • 对比 gzip:官方基准下,中等级别的压缩速度可达 gzip 的数倍,压缩比同时更优;
  • 对比 LZMA/xz:压缩比略逊,但速度快一个数量级,解压普遍在 GB/s 量级;
  • 工程友好:流式 API、上下文复用(单线程多流并发)、字典训练(小文件场景压缩比大幅提升)。

开源鸿蒙 PC 社区公布本批星光库时给出的依赖统计中,zstd 的 fan-in(被依赖数)为 35——它是生态中被下游引用最多的基础库之一。这不是偶然,看看各领域对它的采用:

领域代表项目
Linux 内核内核镜像压缩、zram、squashfs、btrfs、f2fs(5.6+ 原生支持)
文件系统/存储Btrfs、ZFS/OpenZFS
数据库RocksDB、MySQL InnoDB 页压缩、PostgreSQL TOAST(PG14+)、ClickHouse、MongoDB
包管理Arch pacman、Fedora RPM、Debian dpkg、conda、Nix
网络/传输Chrome/Firefox 的Content-Encoding: zstd、OpenSSH、rsync
归档格式tar --zstd、zip(方法 20)

从内核到浏览器,从数据库到包管理器,zstd 已经是事实上的新一代压缩选型。对一个 PC 操作系统生态来说,它是数据库、归档工具、传输组件绕不开的"压缩机底座"。

三、它在鸿蒙 PC 生态里的位置

本次适配可以理解为下面这条链路:

zstd 上游源码(github.com/facebook/zstd) -> Conan 配方(conandata.yml + conanfile.py + test_package) -> OHOS NDK ohos.toolchain.cmake 交叉编译(arm64-v8a) -> binary-sign-tool 共享库自签 -> ohpcd 制品仓发布 -> 下游库/应用通过 Conan 消费 libzstd.so -> HarmonyOS PC 上动态加载运行

高 fan-in 意味着适配一次、受益一片:任何依赖 zstd 的数据库类、归档类、传输类三方库,都可以直接站在这个制品上做交叉编译,而不用各自面对一遍 musl libc 和工具链差异。

四、适配难点拆解

4.1 musl libc:GNU 扩展不能想当然

HarmonyOS 用户态使用 musl libc,与 glibc 的差异是所有三方库适配的第一道坎。zstd 的场景比较典型:

  1. 先核查事实,再打补丁。上游同类库常踩的坑是 GNU 扩展qsort_r(musl 不提供)。我们对 1.5.6 全树grep qsort_r,结果无命中——zstd 仅使用标准 C90 的qsort()/mergesort(),不存在此依赖。配方中保留的_patch_gnu_qsort_r()沿用自已发布的 1.5.7 配方,在 1.5.6 上未命中模式,走else分支仅打 warning,是防御性 no-op,不影响构建与功能。
  2. 平台宏不是万能药。项目规范 R8(最高优先级)明确"源码和 patches/ 补丁不得引入平台条件编译宏",要求通过 POSIX 接口适配。评审中也指出:即使确需兼容,也建议改为 CMakecheck_c_source_compiles做能力检测、用target_compile_definitions传递功能宏,而不是硬编码__OHOS__这类平台名。这条经验对任何库都适用:判断"能力",而不是判断"平台"。


4.2 交叉编译下的测试策略:宿主回归 + 设备消费者,双层验证

OHOS 目标是 arm64,CI 宿主是 x86_64,交叉编译出的测试二进制无法在宿主执行——这是所有 C/C++ 库适配都要回答的问题:"你的 99% 通过率是怎么跑出来的?"我们的答案分两层:

  • 宿主侧原生回归:在 Ubuntu 24.04(x86_64)上以ZSTD_BUILD_TESTS=ON原生构建,完整跑上游tests/套件。这一层的有效性有依据:zstd 1.5.6 仅使用标准 C90 排序接口、不依赖平台特有符号,宿主原生测试可完整覆盖库逻辑。
  • 设备侧消费者测试:新增test_package,在设备上通过dlopen加载libzstd.so、dlsym校验ZSTD_versionNumber符号存在并被实际调用,验证"交叉编译产物在真机可加载、符号可消费"。同时给test()加上cross_building保护:交叉编译场景只验编译+链接,避免在宿主上执行 arm64 二进制导致exec format error。

这两层合起来,才构成"库逻辑正确"和"制品可用"的完整证据链。

4.3 共享库签名:从"编译通过"到"能被加载"

编译出的.so在 OHOS 上还不能直接用——平台要求共享库经过签名。配方的_sign_shared_libs()完成两步:

llvm-objcopy 移除 .codesign 段 -> binary-sign-tool 对 libzstd.so 自签

这一步不处理,dlopen就会在加载阶段失败。它是"构建成功"与"制品可消费"之间最容易被忽略的一环。

4.4 制品可复现性:URL、哈希与镜像

配方固定官方源 github.com(R39 规则),CI 自动改写镜像 fallback。本次源码 SHA-256 实测为8c29e06c...403c1,与 gh-proxy、kkgithub 多镜像返回的哈希一致——多镜像哈希比对是排除"下载被污染"质疑的关键动作。

五、CI 失败排查实录:一个 sha256 引发的全链路阻塞

这次适配的直接导火索是 CI 失败:source()下载源码后哈希校验不通过,构建在第一步就挂掉。

排查路径:

  1. 定位:conandata.yml中记录的 sha256(0f6096...)是一个无效哈希值;
  2. 验证:本地实际下载源码计算哈希,再与 CI 多镜像源(gh-proxy、kkgithub)返回的哈希比对,三者一致;
  3. 修复:将正确值8c29e06c...同步写入conandata.yml与manifest.yaml,CI 恢复全绿。

经验:哈希类失败先本地对源,再怀疑代码。无效哈希会让所有构建门禁在第一步全灭,表象是"CI 全挂",根因却只是一行配置。

六、测试与验证

6.1 上游测试实测明细(宿主侧)

测试套件运行命令用例数通过失败通过率
make check(playTests.sh shortest)./playTests.sh41410100%
fuzzer./fuzzer -v -i5005005000100%
zstreamtest./zstreamtest -v -T20s9859850100%
zstreamtest(newapi)./zstreamtest --newapi -t1 -T20s115911590100%
cli-tests./cli-tests/run.py4140197.6%
fullbench./fullbench -i1/-i1 -P0220100%
invalidDictionaries./invalidDictionaries110100%
legacy./legacy110100%
poolTests./poolTests110100%
合计—27312730199.96%

官方make check退出码 0(PASS)。

唯一失败项:cli-tests/file-stat/compress-file-to-dir-without-write-perm.sh。该用例chmod 000 out后期望 zstd 因无写权限而失败;本次以 root 运行,root 绕过 Unix 写权限校验导致 zstd 写入成功,用例"期望失败"未成立。属宿主 root 环境问题,非库缺陷(OHOS 应用以非 root 运行,该用例在非 root 环境通过)。剔除该环境项后,库功能用例通过率 2730/2730 = 100%。

6.2 新增消费者测试

项目说明
新增文件test_package/test.c
验证内容dlopen加载 libzstd.so,dlsym校验ZSTD_versionNumber符号存在并被实际调用
执行方式由 CI 在设备侧自动执行,MANIFEST.yml声明,以 hnp 环境的 bash 运行./test_probe
结果1/1 通过

6.3 HarmonyOS PC 真机实测(HiShell)

在 HarmonyOS PC 真机上实测上游测试套件:测试二进制经 OHOS NDK arm64 交叉编译、binary-sign-tool 自签后在真机 HiShell 执行。

测试真机结果
./zstd -Vv1.5.6 版本横幅正常
./fuzzer -v -i500All fuzzer tests completed(500/500)
./zstreamtest -v -T20sOK
./zstreamtest --newapi -t1 -T20sOK(20 秒窗口完成 781 项,宿主机同命令为 1159 项,限时模式完成数随设备性能浮动)
./fullbench -i1全部 API 基准通过,compress 540.4 MB/s / decompress 1750.8 MB/s


七、复现指南

上游测试已封装为一键脚本(下载 + sha256 校验 + 构建 + 跑测):

archives/z/zstd/1.5.6/run_upstream_tests.sh

Conan 交叉构建入口(profile 以仓库ci/conan/profiles为准):

conan create archives/z/zstd/1.5.6 \ -pr:h=ci/conan/profiles/ohos-aarch64 \ -pr:b=ci/conan/profiles/ohos-aarch64 \ --build=missing

构建通过后 CI 会依次执行 L0 结构完整性门禁、L1 测试执行验证门禁、制品签名与上传。

八、边界说明:哪些结论成立,哪些还在路上

严谨的适配报告必须划清"已验证"与"未覆盖"的边界:

已验证:

  • 宿主侧(x86_64)上游全量测试回归:2731 项,99.96%;
  • 交叉编译(OHOS arm64-v8a)构建、链接与制品签名;
  • CI 设备侧 test_package:libzstd.so 可dlopen加载、核心符号可消费;
  • CI 双通道(CI + REL)门禁全绿。
  • HarmonyOS PC 真机(HiShell)实测:fuzzer / zstreamtest / fullbench 全部通过;

未覆盖:

  • 上游全量测试套件在真机 arm64 上的原生运行(交叉编译测试二进制需设备侧 shell 支持,属后续可扩展项);
  • 依赖 zstd 的下游库的真机端到端验证(随各下游库自身的适配交付)。

九、踩坑清单

  1. 哈希类 CI 失败先本地对源:无效 sha256 会让source()第一步全灭,先下载实测哈希、多镜像比对,再怀疑别的;
  2. 平台宏不是适配的正解:R8 禁止平台条件编译宏,check_c_source_compiles能力检测优于__OHOS__平台名判断;
  3. 打补丁前先核查上游源码:全树grep qsort_r无命中才敢下结论;防御性补丁必须有安全的 no-op 出口;
  4. root 环境会伪造"失败":chmod 000对 root 无效,环境问题不等于库缺陷,报告里要把口径写清楚;
  5. 交叉编译的测试必须分层:宿主回归证明"库逻辑",消费者测试证明"制品可用",test_package记得加cross_building保护。

结语

zstd 的适配本质是一次"基础库交付"的完整实践:上游 2731 项测试守住库逻辑,musl 兼容核查守住平台正确性,签名与消费者测试守住制品可用性。对 fan-in 高达 35 的"压缩机底座"来说,这一次适配的收益会随下游生态持续放大——数据库、包管理、归档与传输类三方库,都可以直接站在这个制品上继续往前走。

同库 1.5.7 配方中的成熟做法(qsort_r 防御性补丁、签名流程)已在本次 1.5.6 适配中复用,后续版本的适配成本只会越来越低。

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

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进