如果你做过原生 C/C++ 在移动/嵌入式类系统上的落地,多半经历过同一种疲惫:同一个开源库,在 Linux 上 cmake && make 很顺滑,一旦换成交叉编译,立刻变成"每个库一套脚本、每个库一坑"。鸿蒙(HarmonyOS / OpenHarmony 语境下也常写作 OHOS)这条线也不例外------图像、网络、压缩、国际化、字体渲染......依赖一多,可复现构建和依赖拓扑就会从"工程问题"升级成"团队治理问题"。
近两年社区里出现了两条很不一样的"框架化"答案:
-
一条是把问题放进 vcpkg 这种"通用 C/C++ 包管理器 + port 目录"的世界观里,再为 OHOS 补齐 triplet 与工具链识别(当前Qt 团队维护的 fork 分支走得很靠前)。
QT官方维护的vcpkg 项目地址 :https://git.qt.io/jobor/vcpkg.git -
另一条是沿用 OpenHarmony 生态里更"原生"的 Lycium 系思路:用 HPKBUILD 这类声明式脚本把"准备---编译---打包---归档"固化下来;lycium_plusplus 则更像把这套能力做成"可规模化运营的三方库工厂"。
lycium_plusplus 项目地址 :https://atomgit.com/OpenHarmonyPCDeveloper/lycium_plusplus
如果两种都不选,只是单纯针对某一库简单移植,也可以按照传统方式只使用工具链交叉编译。如:[鸿蒙PC三方库移植]:移植libpng到鸿蒙PC平台的完整指南。
前言
在 HarmonyOS / OpenHarmony上做原生 C/C++,迟早会撞上同一堵墙:开源三方库数量多、构建系统各不相同(CMake、Autotools、Meson 等),交叉编译参数稍有偏差,往往要到链接期甚至运行期才爆雷。更麻烦的是依赖链------压缩、TLS、图像、国际化、字体渲染彼此牵连,若用手写 shell 逐库维护,很容易长成团队里谁都不敢动的"私有包管理器",CI 也难以复现。
Qt 官方在公开博文中描述过一种非常典型的状态:CI 与开发机需要大量面向 HarmonyOS 的第三方库,过去只能依赖"按库处理 + 按库 workaround"的长脚本;在引入带 OHOS 能力的 vcpkg 分支后,这类工作流被压缩成更接近一条命令的体验。
与此同时,OpenHarmony 生态里还有另一条同样"工业化"的路线:lycium_plusplus ------把大量库的适配目录、依赖解析、多架构循环与 HNP 打包放在同一套流水线里运营。
这篇文章的目的不是站队,而是把两条路的假设、产物形态、团队成本、适用人群讲清楚:你更像"CMake 工程里消费一堆 .a/.so 的通用原生开发者",还是更像"面向 OpenHarmony 设备/发行形态,需要 HNP 包与批量治理的适配维护者"。
本文做三件事:先交代为什么要框架化 ;再分别把两条路线的机制、步骤、产物与踩坑 讲透;最后给一张对照表与选型建议。文中技术细节来自公开博文、仓库说明与社区常见实践的综合整理,便于读者自行核对各仓库最新分支。
一、背景:三方库移植到底在解决什么
把"移植"拆开,通常至少四层:
| 层次 | 典型问题 |
|---|---|
| 交叉编译正确性 | 目标 ABI、编译器 target triple、汇编与 Intrinsic 选择、链接与 rpath、与宿主机构建的混用风险 |
| 依赖解析与顺序 | 例如 curl → openssl → zlib;版本约束与构建顺序若手工维护,极易出错 |
| 交付形态 | 仅产出给业务工程链接的 .a/.so,还是要进入设备或发行规范下的安装包(如 HNP) |
| 长期维护 | 上游版本、CVE、CI 缓存、镜像可达性、供应链审计、团队知识沉淀 |
没有框架时,常见结局是:每个库一套脚本、每台机器一点差异、排障靠口口相传。框架的价值,是把可重复的部分沉淀为基础设施,把不可重复的部分尽量压缩到"平台差异 + 少数库的补丁"。
二、路径一方案:vcpkg(含面向 OHOS 的 triplet 扩展)
2.1 vcpkg 是什么,为什么会被拿到鸿蒙场景里
vcpkg 是微软开源的 C/C++ 包管理器,核心资产是大量 port (构建配方)与依赖解析能力。它提供统一入口处理源码获取、打补丁、配置、编译与安装,并与 CMake 通过 scripts/buildsystems/vcpkg.cmake 深度集成。除桌面主机外,社区长期维护 Android、iOS 等交叉目标;将 HarmonyOS/OHOS 纳入同一套"triplet + toolchain"叙事,本质上是希望:不必为每个库重写构建系统 glue,而是让平台差异集中在 triplet、toolchain 与少量 port 补丁上。
2.2 鸿蒙原生 C/C++ 场景下的典型痛点(vcpkg 试图对准的靶子)
- 构建系统碎片化:同一依赖可能走 CMake、Autotools、Meson,交叉探测逻辑各不相同。
- 手工流程难规模化:shell 脚本 + 每库 workaround 难以在 CI 与多开发者机器上复现。
- 平台差异隐蔽 :OHOS SDK 的 toolchain、ABI、动态库命名(如 无版本后缀的 soname 策略)与 Linux/Android 并不完全等价,需要集中治理而非散落各处。
2.3 Qt 官方的技术路线

QT的公开技术路线把改动刻意做得小而聚焦,大致两块:
(1)vcpkg-tool 侧
在工具里把 ohos 识别为合法平台标识符。历史材料里常把 OHOS 与 HarmonyOS 放在同一语境表述,SDK 内 toolchain 文件命名也沿用这一习惯。
(2)vcpkg registry 侧
- 提供委托给 HarmonyOS SDK native 工具链的 OHOS toolchain;
- 提供三组社区 triplet:
arm64-ohos、arm-ohos、x64-ohos; - 增强平台检测,使 port 的
"supports"一类表达式能包含或排除 OHOS; - 对部分库追加 portfile 级补丁 (公开资料中曾点名 libpng、fontconfig、ICU 等;具体列表以分支为准)。
长期方向上,Qt 方面曾表达希望将这些改动合并进微软上游 vcpkg / vcpkg-tool,使 OHOS 与 Android、iOS 类似,成为标准社区 triplet 目标,从而减少团队对 fork 的长期依赖。
2.4 环境准备
参考博文:https://www.qt.io/blog/building-libraries-for-harmonyos-with-vcpkg
使用 vcpkg 为鸿蒙(HarmonyOS / OHOS)下载与安装三方库实践指南
| 组件 | 建议 |
|---|---|
| HarmonyOS / OHOS SDK | 含 native 工具链 ;公开材料常见写法为 API 12+ |
| CMake | 3.20+ |
| Ninja | 生成构建系统 |
| Git | 克隆 fork 与上游源码 |
若企业内网访问 git.qt.io 不稳定,可配置代理;社区也有人把 registry 同步到 GitCode 等镜像 以加速 clone------切换源后务必用 git remote / git log 核对分支与提交是否与官方语义一致。
2.5 从零搭建:vcpkg-tool + registry
上游 vcpkg-tool 在合入完成前可能仍不识别 OHOS ,因此公开流程往往要求先从带 ohos 分支的 vcpkg-tool 源码构建可执行文件,再克隆带 ohos 分支的 vcpkg registry,把构建出的 vcpkg 二进制放进 registry 根目录,并设置 VCPKG_ROOT。
构建 vcpkg-tool(示例命令,路径请按本机调整):
bash
git clone https://git.qt.io/jobor/vcpkg-tool.git -b ohos ~/vcpkg-tool
cd ~/vcpkg-tool
cmake -S . -B build -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF
ninja -C build
准备 registry 并放入 vcpkg 可执行文件:
bash
git clone https://git.qt.io/jobor/vcpkg.git -b ohos ~/vcpkg
cd ~/vcpkg
cp ~/vcpkg-tool/build/vcpkg ./
export VCPKG_ROOT=~/vcpkg
clone 偏慢时,可尝试浅克隆(注意后续 git pull 与部分工作流的限制),或者先fork到gitcode一份。
设置 SDK 根目录(示例):
bash
export OHOS_SDK_ROOT=/path/to/your/ohos-sdk/linux
关键点 :$OHOS_SDK_ROOT 下应存在类似路径:
native/build/cmake/ohos.toolchain.cmake
若该路径不对,CMake 交叉阶段通常会很快失败,错误信息里会直接提示找不到 OHOS SDK------此时优先检查环境变量是否写成 OHOS_SDK_ROOT、路径是否指向了包含 native 的那一层。
2.6 安装库与两种消费心智:classic vs manifest
以 classic 模式举例:把包装进统一前缀,便于多工程共享:
bash
vcpkg install --triplet arm64-ohos libpng libjpeg-turbo
产物默认落在 $VCPKG_ROOT/installed/<triplet>/,包含头文件、库与许多库的 CMake config。
Qt 6.11 起,configure 还可配合 manifest 模式在配置阶段自动安装依赖,适合"源码树声明依赖、配置即拉取"的工作流;选项细节以对应 Qt 版本官方文档为准。
2.7 在 CMake 工程里接入
bash
cmake -S . -B build \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_TARGET_TRIPLET=arm64-ohos
vcpkg.cmake:注入安装前缀、查找路径与工具链协同逻辑。VCPKG_TARGET_TRIPLET:声明正在为哪一个 OHOS ABI 产出。
若同时构建 Qt,可配置 QT_USE_VCPKG=ON,由 Qt 构建系统自动定位 vcpkg toolchain。
2.8 可用 triplet 与产物特征(对发布策略有直接影响)
| Triplet | OHOS ABI |
|---|---|
arm64-ohos |
arm64-v8a |
arm-ohos |
armeabi-v7a |
x64-ohos |
x86_64 |
这些 triplet 会产出动态链接库 ,且往往带无版本后缀的 soname 。这意味着团队要提前约定:库随应用打包时的冲突风险、升级策略、运行时查找路径(rpath / LD_LIBRARY_PATH)等,不能默认"和桌面 Linux 发行版习惯一致"。
2.9 上游化未落地前,团队应盯住的维护面
- fork 与上游差异的更新节奏;
- 安全补丁与 CVE 在 port 层的同步方式;
- 二进制缓存与供应链审计(来源、哈希、可复现构建)。
2.10 实践侧常见问题(排障向,非官方文档替代)
(1)下载 GitHub 资源超时
可将 tarball 预先放入 downloads/,或配置可用的下载镜像 / 代理模板;不同网络环境下镜像域名会变化,以团队合规与可用性为准。
(2)安装成功但提示 zip: not found
vcpkg 可能在安装后尝试 zip 打包以写入二进制缓存;缺 zip 时缓存步骤失败,未必影响 已安装到 installed/ 或 packages/ 的库。需要二进制缓存时,在构建机上安装 zip 即可。
(3)Could not find the OHOS SDK / 无法探测编译器
绝大多数是 OHOS_SDK_ROOT 未设置或指错目录。修正后重试。
(4)注意!个别 port 尚未完整覆盖 OHOS
以 OpenSSL 一类库为例,一线常见处理包括:在 portfile 中为 VCPKG_TARGET_IS_OHOS 增加分支,用 vcpkg_cmake_get_vars 把探测到的编译器 target 同步到 VCPKG_C_FLAGS / VCPKG_CXX_FLAGS(例如追加 --target=...),避免 Clang 在交叉场景下"默认按宿主机构建"。若日志显示误用 x86_64 汇编路径,可能还需要在配置选项侧禁用 asm / SSE2 等,强制走与目标 ABI 一致的实现路径------这类修改应优先尝试回馈上游或 fork 维护方,避免私有 fork 无限分叉。
(5)验证产物是否指向目标架构
可用 SDK 自带的 llvm-readelf 查看 ELF 头:Class: ELF64、Machine: AArch64 等可作为快速静态检查;更稳妥是再写最小链接用例做编译链接验证。
(6)鸿蒙 PC 上跑 curl 等可执行文件与 .so
除编译与依赖路径外,还可能涉及 binary-sign-tool 签名 与权限策略;未签名时可能出现 operation not permitted 一类现象。这与 vcpkg 本身无关,但决定"产物是否能在目标系统上落地"。
三、路径二方案:lycium_plusplus(OpenHarmony 三方库的"工厂流水线")

3.1 定位:解决"规模 × 多架构 × 依赖 × 打包"的运营问题
OpenHarmony 上使用 OpenSSL、zlib、curl 等经典 C/C++ 库时,单个库尚可用临时 CMake 解决;当数量上升到百级,且每个库构建方式、依赖、支持架构不同,手工管理几乎不可持续。
lycium_plusplus 在 lycium 框架之上强化了几件事(公开仓库说明与社区解读中的高频表述):
- 依赖关系树 :自动解析
depends,按正确顺序编译; - 多版本 / 外部适配仓 :通过
module.json等机制拉取不在主仓内的适配; - HNP 产物:把"能编出来"推进到"能按生态习惯分发";
- 鸿蒙 PC 本机编译路径:在 HarmonyOS PC 上可走本机工具链,减少交叉编译心智负担。
3.2 典型仓库布局(理解"谁负责调度、谁负责定义包")
结构大致为:
lycium/:核心框架------build.sh(交叉编译主入口)、build_local.sh(鸿蒙 PC 本机入口)、test.sh(设备侧测试)、script/(build_hpk.sh、envset.sh、load_outer_parts.py等)、模板、Docker、文档、output/产物目录等;thirdparty/:大量库的适配目录(社区材料中常提到约 275 个量级,以仓库为准);community/:社区适配库(常见表述 约 132);external_deps/module.json:外部模块清单(常见表述 约 22 个模块级引用,以仓库为准)。
3.3 包定义层:每个库目录里通常有什么
以单个库目录为例,常见必备件包括:
HPKBUILD:元数据 +prepare()/build()/package()/archive()等构建生命周期;HPKCHECK:设备侧测试定义;hnp.json:HNP 包配置;README.OpenSource:开源合规声明;- 按需的
*.patch、中文说明、校验和、OAT 配置等。
新建库时,通常从 lycium/template/ 复制模板再改,降低"漏文件导致构建系统无法工作"的概率。
3.4 总调度:build.sh 在做什么
用户执行 ./build.sh <pkgname> 后,框架侧典型会做:准备工具链、检查构建环境、加载已构建列表、收集社区库、按 module.json 拉外部仓、解析依赖、对每个架构循环执行单包流水线。
单包流水线在脚本层常被描述为四段:
prepare → build → package → archive
依赖解析的直观例子:若 curl 的 HPKBUILD 声明 depends=(openssl zlib),则顺序会是 zlib → openssl → curl,无需人手写拓扑排序。
./build.sh curl
环境与工具链检查
加载 external_deps
解析 HPKBUILD depends
按架构循环 arm32/arm64/x86_64
prepare
build
package
archive: tar.gz + HNP
output//
3.5 交叉 vs 本机:两种入口怎么选
| 特性 | build.sh(常见:Linux/macOS/Cygwin) |
build_local.sh(鸿蒙 PC) |
|---|---|---|
| 编译方式 | 交叉编译为主 | 检测到 HarmonyOS 后走本机编译路径 |
| 工具链 | OpenHarmony SDK Clang 等 | 系统 Clang 等 |
| 典型场景 | CI、服务器批量出包 | 本机调试、减少交叉心智 |
build_local.sh 的常见实现语义是:若系统名以 Harmo 开头,则置本机标志并最终仍调用 build.sh,把"入口差异"收敛到一处。
3.6 环境注入:envset.sh 一类脚本在管什么
不同架构对应不同编译器前缀,常见的:
setarm32ENV():arm-linux-ohos-clang等 → armeabi-v7asetarm64ENV():aarch64-linux-ohos-clang等 → arm64-v8asetx86_64ENV():x86_64setHarmonyOSENV():鸿蒙 PC 本机 clang/clang++
同时会处理 CC、CXX、LD、AR、NM、RANLIB、STRIP、OBJDUMP、打包工具变量等,保证"架构循环"里每一轮都是干净一致的环境。
3.7 设备侧测试:test.sh 与 CItools
OpenHarmony 设备上往往缺 cmake / make / ctest 等,但 HPKCHECK 里的 openharmonycheck() 又依赖这些工具。CItools 提供 busybox、cmake、make、perl 等在 ARM 架构上的预编译或编译指导;配合 test.sh 推送与执行测试,形成"编---装---测"的闭环。
3.8 外部依赖为什么单独成 module.json
有些库由其他团队维护或版本变动频繁,不适合全部塞进主仓。构建开始时由脚本读取 external_deps/module.json,按条目 git clone 到 thirdparty/<name>/,后续流程与主仓内库一致------差别只在代码来源与治理边界。
3.9 排障习惯(社区 FAQ )
- 构建日志:常见路径模式为
thirdparty/<库名>/..._lycium_build.log(以仓库实际为准); - 关注
last_error一类提示; - 复杂失败可进入源码目录手动逐步执行
prepare/build/package以定位; - 回溯
HPKBUILD变量与函数是否与环境假设一致。
四、两条方案路线对照:不是"谁更强",而是"默认优化目标不同"
| 维度 | vcpkg(OHOS triplet 路线) | lycium_plusplus |
|---|---|---|
| 默认用户画像 | 以 CMake / 通用原生工程为中心,把 OHOS 当作又一个交叉目标的开发者 | 面向 OpenHarmony 三方库批量适配、HNP 分发与设备测试的维护者 |
| 核心抽象 | triplet + portfile + 统一 installed/ 前缀 |
HPKBUILD / HPKCHECK + 多架构循环 + HNP |
| 清单与依赖 | 依托全球 vcpkg port 目录;OHOS 覆盖度随上游合入与补丁演进 | 依托仓内 thirdparty + community + external_deps 的可控清单 |
| 产物心智 | "安装到统一前缀,给工程链接" | "可安装包 + 归档 + 设备验证" |
| 与 Qt 的耦合点 | 公开材料强调 Qt 构建与 vcpkg 的集成路径、manifest 等 | 不强绑定 Qt;更贴近 OpenHarmony 原生分发与测试链 |
| 典型风险 | fork 过渡期、个别 port 仍需平台补丁、发布侧签名/权限 | 适配件工程化质量、组织内多仓治理成本 |
一句话:vcpkg 更像"把 OHOS 接进全球 C++ 包管理器的惯性里";lycium_plusplus 更像"在 OpenHarmony 语境里运营一座三方库工厂"。
五、选型建议:用三个问题把会开短
-
主交付链是否强依赖 OpenHarmony 的包形态(HNP)与设备侧测试闭环?
若是,lycium_plusplus 往往更贴近默认工作方式。
-
主工程是否以 CMake/Qt/通用原生栈为主,仅增加 OHOS 目标?
若是,vcpkg 路线通常减少上下文切换,且能复用大量既有 port。
-
更需要"全球配方覆盖面",还是"组织内可控清单与审计边界"?
前者偏 vcpkg;后者偏 lycium_plusplus(尤其当多团队分工维护适配仓时)。
如果你的主战场是「CMake 工程里要把一堆 .so/.a 编出来并链接进去」,vcpkg 通常上手更简单------命令模型统一、和 CMake 集成成熟、还能蹭全球 port 目录的规模效应。
更稳妥的选法不是二选一标签,而是看默认交付物:
优先选 vcpkg(或至少以它为主),若你符合多数条:
业务是 Qt / 通用 C++ 应用,OHOS 只是多出来的一个 triplet 目标;
团队已经熟悉或愿意接受 triplet + vcpkg install + vcpkg.cmake;
你要的是 开发/CI 里可复现的依赖前缀(installed/),再自己接到现有打包/集成流程;
能接受当前阶段仍可能要:跟 Qt 的 ohos fork、上游合并进度,以及个别库要自己补 port/参数(不是"零维护魔法")。
优先选 lycium_plusplus(或至少以它为主),若你符合多数条:
工作核心是 OpenHarmony 官方/社区那套三方库适配与分发(HNP、多架构批量、HPKBUILD 治理、设备侧 HPKCHECK);
你要的是 「编---打 HNP---上设备测」 一整条流水线,而不是只解决链接;
组织上要管 大量库的适配仓、外部 module、社区库 这种"工厂运营"问题。
关于"vcpkg 更简单"的说明:
简单主要体现在使用模型(尤其对 CMake 党)。但要注意两点,避免后面觉得"被坑了":
OHOS 支持链路目前仍常落在 fork + 合入进行中 的现实里,不是"装个官方 vcpkg 就全完事"。
简单的是构建与安装;若你的最终形态强依赖 HNP / 签名 / 设备规范测试,这些往往仍要自己接后半段,而 lycium_plusplus 默认就是为后半段长的。
一句话建议:
偏应用开发、CMake 为主 → 先 vcpkg,把依赖交叉编顺;若后续要完全对齐 OpenHarmony 包形态,再补一条打包/测试流水线(或用 lycium 系补闭环)。
偏三方库适配与发行、要 HNP 与设备回归 → 以 lycium_plusplus 为主更省心,vcpkg 当辅助。
组合用法 也常见:用 vcpkg 解决一部分通用依赖的交叉构建与 CMake 消费,再用 lycium 系流水线做规范化打包、设备回归与内部制品分发------关键是看喜好和习惯 ,以及主战场在哪,而不是教条二选一。
六、总结
鸿蒙三方库移植的难点,表面是编译器与 ABI,实质是依赖治理、产物形态与长期维护 。vcpkg 与 lycium_plusplus 分别把问题接入不同的工业体系:前者把 OHOS 推进到"又一个 triplet 目标"的世界观里,强调与 CMake/Qt 生态的衔接;后者把问题放进 OpenHarmony 的适配目录 + HNP + 设备测试闭环里,强调规模化运营与治理边界。
落地时建议:固定 SDK 与 API 级别、固定 triplet 或固定架构矩阵、在 CI 里固定依赖来源与缓存策略 ,并对关键库做链接与运行期加载回归;若涉及可执行文件与动态库分发,把签名与权限策略提前写进发布清单,避免"编出来却跑不起来"的反噬。
参考与延伸阅读(链接置于文后)
-
Qt 英文博文:Building C/C++ libraries for HarmonyOS with vcpkg
https://www.qt.io/blog/building-libraries-for-harmonyos-with-vcpkg
-
Qt 日文页(同源内容入口)
https://www.qt.io/ja-jp/blog/building-libraries-for-harmonyos-with-vcpkg
-
Qt 侧 vcpkg registry(
ohos分支) -
Qt 侧 vcpkg-tool(
ohos分支) -
社区镜像示例(非 Qt 官方托管,使用前请核对分支与提交)
-
微软上游 vcpkg(通用文档与生态入口;OHOS 合入进度以仓库说明为准)
-
Microsoft Learn:Triplets
-
lycium_plusplus(AtomGit)
-
OpenHarmony 通用 C/C++ 三方库标准化适配(Lycium /
tpc_c_cplusplus语境,方法论文档向) -
鸿蒙 PC / OpenHarmony 跨平台开发者社区(交流向)
-
OpenHarmony 版本与 SDK 获取(请优先以当前官网/版本站为准,避免使用过期的固定下载 URL)
-
鸿蒙 PC三方库构建的"大管家"lycium_plusplus 项目全景解读
最后,欢迎加入开源鸿蒙开发者社区交流:https://harmonypc.csdn.net/