欢迎加入开源鸿蒙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-256 | 8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1 |
| 目标平台 | 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 的场景比较典型:
- 先核查事实,再打补丁。上游同类库常踩的坑是 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,不影响构建与功能。 - 平台宏不是万能药。项目规范 R8(最高优先级)明确"源码和 patches/ 补丁不得引入平台条件编译宏",要求通过 POSIX 接口适配。评审中也指出:即使确需兼容,也建议改为 CMake
check_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()下载源码后哈希校验不通过,构建在第一步就挂掉。
排查路径:
- 定位:
conandata.yml中记录的 sha256(0f6096...)是一个无效哈希值; - 验证:本地实际下载源码计算哈希,再与 CI 多镜像源(gh-proxy、kkgithub)返回的哈希比对,三者一致;
- 修复:将正确值
8c29e06c...同步写入conandata.yml与manifest.yaml,CI 恢复全绿。
经验:哈希类失败先本地对源,再怀疑代码。无效哈希会让所有构建门禁在第一步全灭,表象是"CI 全挂",根因却只是一行配置。
六、测试与验证
6.1 上游测试实测明细(宿主侧)
| 测试套件 | 运行命令 | 用例数 | 通过 | 失败 | 通过率 |
|---|---|---|---|---|---|
make check(playTests.sh shortest) | ./playTests.sh | 41 | 41 | 0 | 100% |
| fuzzer | ./fuzzer -v -i500 | 500 | 500 | 0 | 100% |
| zstreamtest | ./zstreamtest -v -T20s | 985 | 985 | 0 | 100% |
| zstreamtest(newapi) | ./zstreamtest --newapi -t1 -T20s | 1159 | 1159 | 0 | 100% |
| cli-tests | ./cli-tests/run.py | 41 | 40 | 1 | 97.6% |
| fullbench | ./fullbench -i1/-i1 -P0 | 2 | 2 | 0 | 100% |
| invalidDictionaries | ./invalidDictionaries | 1 | 1 | 0 | 100% |
| legacy | ./legacy | 1 | 1 | 0 | 100% |
| poolTests | ./poolTests | 1 | 1 | 0 | 100% |
| 合计 | — | 2731 | 2730 | 1 | 99.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 -V | v1.5.6 版本横幅正常 |
./fuzzer -v -i500 | All fuzzer tests completed(500/500) |
./zstreamtest -v -T20s | OK |
./zstreamtest --newapi -t1 -T20s | OK(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.shConan 交叉构建入口(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 的下游库的真机端到端验证(随各下游库自身的适配交付)。
九、踩坑清单
- 哈希类 CI 失败先本地对源:无效 sha256 会让
source()第一步全灭,先下载实测哈希、多镜像比对,再怀疑别的; - 平台宏不是适配的正解:R8 禁止平台条件编译宏,
check_c_source_compiles能力检测优于__OHOS__平台名判断; - 打补丁前先核查上游源码:全树
grep qsort_r无命中才敢下结论;防御性补丁必须有安全的 no-op 出口; - root 环境会伪造"失败":
chmod 000对 root 无效,环境问题不等于库缺陷,报告里要把口径写清楚; - 交叉编译的测试必须分层:宿主回归证明"库逻辑",消费者测试证明"制品可用",
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