万字长文解读 lycium_plusplus:OpenHarmony C_C++ 三方库编译利器
万字长文解读 lycium_plusplus:OpenHarmony C_C++ 三方库编译利器
导读:你是否为 OpenHarmony 平台编译 C/C++ 三方库而头疼?面对复杂的交叉编译工具链、依赖管理、多架构适配感到无从下手?本文将带你从零开始,深入浅出地解析 lycium_plusplus 框架的设计理念与使用技巧,让你轻松掌握 OpenHarmony 生态下的三方库编译之道!
欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
一、什么是 lycium_plusplus?
1.1 一句话定义
lycium_plusplus 是一个专为 OpenHarmony 系统设计的 C/C++** 三方库交叉编译自动化框架**,它能让你通过简单的配置,一键编译出能在 OpenHarmony 设备上运行的三方库。
1.2 项目背景
在 OpenHarmony 生态开发中,我们经常需要用到各种 C/C++ 三方库(如 curl、openssl、json 等)。但这些库原本是为 Linux/Windows 等成熟平台设计的,要移植到 OpenHarmony 面临以下挑战:
- 工具链复杂:需要使用特定的交叉编译器(clang/clang++ for OHOS)
- 依赖关系混乱:库与库之间存在复杂的依赖关系
- 多架构适配:需要支持 armeabi-v7a、arm64-v8a 等多种架构
- 构建系统多样:有的用 cmake,有的用 configure,有的用 make
lycium_plusplus 就是为了解决这些问题而生的!
1.3 核心能力
- 一键构建:自动解析依赖关系树,按正确顺序编译
- 多版本管理:支持同一库的不同版本共存
- HNP产物生成:直接打包成 HarmonyOS 可用的 hnp 格式
- 本机构建:支持在华为鸿蒙电脑上直接编译
- 274+ 已适配库:涵盖主流 C/C++ 三方库
二、为什么需要这个框架?
2.1 传统编译方式 vs lycium_plusplus
让我们通过对比来理解这个框架的价值:
传统方式编译curl库
# 1. 手动下载源码
wget https://curl.se/download/curl-8.0.1.tar.gz
tar -zxvf curl-8.0.1.tar.gz
# 2. 设置交叉编译环境变量
export CC=/path/to/ohos-sdk/llvm/bin/aarch64-linux-ohos-clang
export CXX=/path/to/ohos-sdk/llvm/bin/aarch64-linux-ohos-clang++
export CFLAGS="-DOHOS_NDK -fPIC -D__MUSL__=1"
# 3. 手动处理依赖(假设依赖 openssl、zstd)
cd ../openssl && make && make install
cd ../zstd && cmake && make && make install
# 4. 配置编译
cd curl-8.0.1
./configure --host=aarch64-linux-ohos \
--with-ssl=/path/to/openssl \
--with-zstd=/path/to/zstd
# 5. 编译安装
make -j8
make install
问题:
- 环境变量容易设置错误
- 依赖库需要手动先编译
- 多架构要重复编译多次
- 参数传递容易遗漏
使用 lycium_plusplus 编译 curl
# 1. 进入框架目录
cd lycium_plusplus/lycium
# 2. 一键编译(自动处理依赖)
./build.sh curl
优势:
- 零配置,开箱即用
- 自动解析并编译依赖(openssl、zstd、nghttp2)
- 自动处理多架构编译
- 产物自动安装到标准路径
2.2 适用场景
- OpenHarmony 应用开发:需要 C/C++ 三方库的北向应用
- 系统开发:为 OpenHarmony 设备提供底层库支持
- 库移植:将 Linux 库快速移植到 OpenHarmony 平台
- 学习研究:理解交叉编译原理和 OpenHarmony 构建体系
三、框架整体架构
3.1 目录结构
lycium_plusplus/
├── community/ # 社区库(隐式依赖,不直接编译)
│ ├── CUnit/
│ ├── Catch2/
│ ├── json-c/
│ └── ... (100+ 社区库)
│
├── thirdparty/ # 核心三方库(主要工作区)
│ ├── curl/
│ │ └── HPKBUILD # 每个库的构建配置
│ ├── json/
│ ├── openssl/
│ └── ... (274+ 已适配库)
│
├── external_deps/ # 外部适配仓配置
│ └── module.json # 外部仓下载清单
│
└── lycium/ # 核心编译引擎
├── build.sh # 交叉编译入口
├── build_local.sh # 本机构建入口
├── test.sh # 测试入口
├── script/ # 核心脚本
│ ├── build_hpk.sh # 单库构建流程
│ ├── envset.sh # 环境配置
│ └── load_outer_parts.py # 外部仓加载
└── template/ # 模板文件
└── HPKBUILD # HPKBUILD 模板
3.2 三大核心目录
| 目录 | 定位 | 特点 |
|---|---|---|
| thirdparty/ | 主战场 | 274+ 已适配库,可直接编译 |
| community/ | 后勤仓库 | 社区贡献库,作为依赖被引用 |
| external_deps/ | 扩展接口 | 外部适配仓,支持动态下载 |
3.3 编译流程架构图

四、核心概念解读
4.1 HPKBUILD:库的身份证
每个三方库都有一个 HPKBUILD 文件,它包含了库的所有编译信息。可以理解为一个“配方”,告诉框架如何编译这个库。
核心字段速查表:
| 字段 | 含义 |
|---|---|
| pkgname | 库名 |
| pkgver | 版本号 |
| pkgrel | 发布号 |
| pkgdesc | 库描述 |
| url | 官网 |
| archs | 支持的架构 |
| license | 许可证 |
| depends | 运行时依赖 |
| makedepends | 构建工具依赖 |
| source | 源码下载地址 |
4.2 构建生命周期
每个库的编译都经历以下阶段(类似工厂生产线):

各阶段职责:
- prepare():准备阶段
- 下载源码包(如果 downloadpackage=true)
- 解压源码(如果 autounpack=true)
- 应用 patch 修复兼容性问题
- 创建构建目录
- build():编译阶段
- 执行 cmake/configure 配置
- 执行 make 编译
- 生成目标文件
- package():安装阶段
- 执行 make install
- 将产物安装到 L Y C I U M R O O T / u s r LYCIUM_ROOT/usr LYCIUMROOT/usrpkgname/$ARCH/
- archive():打包阶段(可选)
- 生成 tar.gz 归档
- 使用 hnpcli 打包成 HNP 格式
- check():测试阶段
- 在 OpenHarmony 设备上运行测试用例
- 验证库功能正常
4.3 依赖管理机制
退出码协议(框架的核心通信机制):
| 退出码 | 含义 | 框架行为 |
|---|---|---|
| 0 | 编译成功 | 标记为已完成,继续下一个 |
| 101 | 依赖未就绪 | 添加到下一轮编译队列 |
| 其他 | 编译失败 | 记录错误,跳过该库 |
依赖解析示例:
假设我们要编译 curl,它的依赖关系是:
curl
└── openssl
└── zlib
编译流程:
第一轮:
- 编译 curl → 返回 101(依赖 openssl 未编译)
- 记录依赖:openssl
第二轮:
- 编译 openssl → 返回 101(依赖 zlib 未编译)
- 记录依赖:zlib
第三轮:
- 编译 zlib → 成功(无依赖)
第四轮:
- 编译 openssl → 成功(依赖 zlib 已就绪)
第五轮:
- 编译 curl → 成功(依赖 openssl 已就绪)
编译完成!
4.4 多架构编译
框架会自动遍历 archs 数组,为每个架构执行一次完整的构建流程:
archs=("armeabi-v7a" "arm64-v8a")
# 伪代码
for arch in ${archs[@]}; do
设置架构环境变量 # CC/CXX/CFLAGS 等
prepare
build
package
done
环境变量示例(arm64-v8a):
export CC=aarch64-linux-ohos-clang
export CXX=aarch64-linux-ohos-clang++
export CFLAGS="-DOHOS_NDK -fPIC -D__MUSL__=1 -D__OHOS__"
export LDFLAGS="--sysroot=${SYSROOT}"
五、HPKBUILD:框架的灵魂
5.1 标准模板解析
让我们逐行拆解一个标准的 HPKBUILD 文件:
# ==================== 元数据区 ====================
pkgname=curl # 库名(必须与目录名一致)
pkgver=curl-8_0_1 # 版本号
pkgrel=0 # 发布号(用于同版本多次发布)
pkgdesc="A command line tool..." # 描述
url="https://curl.se/" # 官网
archs=("armeabi-v7a" "arm64-v8a") # 支持的架构
license=("curl") # 许可证类型
# ==================== 依赖区 ====================
depends=("openssl" "zstd_1_5_6" "nghttp2") # 运行时依赖
makedepends=("cmake" "pkg-config") # 构建工具依赖
# ==================== 源码区 ====================
source="https://gitee.com/mirrors/curl/repository/archive/curl-8_0_1.zip"
downloadpackage=true # 是否自动下载(默认true)
autounpack=true # 是否自动解压(默认true)
# ==================== 路径区 ====================
builddir=curl-curl-8_0_1 # 解压后的目录名
packagename=$builddir.zip # 源码包名
# ==================== 构建函数区 ====================
1. **准备阶段**
prepare() {
cd $builddir
# 打 patch(如果需要)
patch -p1 < ../curl_oh_pkg.patch
# 创建构建目录
mkdir -p $ARCH-build
cd $OLDPWD
}
# 编译阶段
build() {
cd $builddir
# 配置("$@" 包含依赖路径和工具链参数)
cmake "$@" -DCURL_CA_BUNDLE="/etc/ssl/certs/cacert.pem" \
-DCURL_ZSTD=ON \
-B$ARCH-build -S./
# 编译
$MAKE -C $ARCH-build
ret=$?
cd $OLDPWD
return $ret # 必须返回退出码
}
# 安装阶段
package() {
cd $builddir
make -C $ARCH-build install # 安装到 $LYCIUM_ROOT/usr/curl/$ARCH/
cd $OLDPWD
}
# 测试阶段
check() {
echo "The test must be on an OpenHarmony device!"
# 实际测试命令(需在 OHOS 设备上运行)
}
# 清理阶段
cleanbuild() {
rm -rf ${PWD}/$builddir
}
5.2 关键变量说明
| 变量 | 作用域 | 说明 |
|---|---|---|
| $ARCH | 全局 | 当前编译架构(如 arm64-v8a) |
| $LYCIUM_ROOT | 全局 | 框架根目录 |
| $OHOS_SDK | 全局 | OpenHarmony SDK 路径 |
| $MAKE | 全局 | make 命令(已设置 -j8 并行) |
| “$@” | build() | cmake 参数(依赖路径、工具链等) |
| $buildlog | build() | 编译日志文件路径 |
5.3 构建工具类型
根据库的构建系统,buildtools 字段可设置为:
| 值 | 适用场景 | 配置方式 |
|---|---|---|
| cmake | CMakeLists.txt 项目 | 默认值,无需额外配置 |
| configure | autotools 项目 | 自动设置 --prefix 等参数 |
| make | 纯 Makefile 项目 | 直接执行 make |
| 空 | 其他 | 需要在 build() 中自定义 |
六、实战演练:从入门到精通
提示:本章提供三个循序渐进的实战案例,帮助读者快速掌握 HPKBUILD 编写与三方库适配技巧。读者可参考下面鸿蒙 PC 三方库适配相关文章深入学习:
| 序号 | 文章标题 | 核心内容 | 适合阶段 | 阅读链接 |
|---|---|---|---|---|
| 1 | 从零开始写 HPKBUILD:以 MediaInfo 为例的三方库 OpenHarmony 适配实战 | HPKBUILD 编写全流程、字段详解、实战演练 | 入门 | CSDN链接 |
| 2 | [鸿蒙三方库适配实战] 多媒体信息工具 MediaInfo CLI 的 OpenHarmony 平台迁移实践 | 复杂依赖处理、Patch 应用、编译问题排查 | 进阶 | CSDN链接 |
| 3 | Windows 鸿蒙 PC 应用开发:DevEco Studio 集成与调用三方 Native 库实战指南 | 产物使用、DevEco Studio 集成、北向应用调用 | 实战 | CSDN链接 |
学习路径建议
第一步:阅读文章1 → 理解 HPKBUILD 基本结构与编写方法
↓
第二步:阅读文章2 → 掌握复杂库适配技巧与问题排查
↓
第三步:阅读文章3 → 学习如何在应用中使用编译好的三方库
↓
第四步:回到本文 → 系统理解框架整体架构与设计思想
三篇文章核心知识点
文章1 - 从零开始写 HPKBUILD:
- HPKBUILD 文件完整结构解析
- 元数据字段、依赖声明、源码配置
- prepare/build/package/check 函数编写
- MediaInfo 适配完整案例演示
- 常见错误与解决方案
文章2 - MediaInfo CLI 迁移实践:
- 复杂依赖链处理(libzen + libcurl + zlib)
- Patch 文件编写与应用技巧
- configure/cmake 混合项目适配
- musl libc 兼容性问题处理
- 编译日志分析与调试方法
文章3 - DevEco Studio 集成调用:
- 编译产物在 DevEco Studio 中的配置
- CMakeLists.txt 中引入三方库
- 北向应用调用 Native 库的完整流程
- 权限配置与打包发布
- 真机调试与性能优化
七、进阶特性:外部适配仓
7.1 什么是外部适配仓?
外部适配仓是 lycium_plusplus 的创新设计,允许将适配代码独立于主仓库管理。
优势:
- 解耦发布:适配仓可独立更新,无需修改主仓
- 多版本管理:同一库的不同版本可有不同的适配
- 社区协作:不同开发者可维护不同库的适配
7.2 配置方法
步骤1:编辑 module.json
cd ../external_deps
cat module.json
{
"module": [
{
"name": "tree",
"branch": "ohos_2.2.1",
"version": "2.2.1",
"type": "git",
"url": "https://gitcode.com/OpenHarmonyPCDeveloper/ohos_tree.git"
}
]
}
步骤2:外部仓结构
ohos_tree/
├── HPKBUILD # 适配后的构建配置
├── 0001-ports-for-ohos.patch # 兼容性补丁
└── hnp.json # HNP 打包配置
步骤3:编译
cd ../lycium
./build.sh tree # 自动从外部仓下载并编译
7.3 HNP 打包配置
如果需要生成 HNP 产物,在 HPKBUILD 中添加 archive() 函数:
archive() {
mkdir -p ${LYCIUM_ROOT}/output/$ARCH
pushd $LYCIUM_ROOT/usr/$pkgname/$ARCH
tar -zvcf ${LYCIUM_ROOT}/output/$ARCH/${pkgname}_${pkgver}.tar.gz *
popd
cp hnp.json $LYCIUM_ROOT/usr/$pkgname/$ARCH
${HNP_TOOL} pack -i ${LYCIUM_ROOT}/usr/$pkgname/$ARCH \
-o ${LYCIUM_ROOT}/output/$ARCH/
}
hnp.json 示例:
{
"type": "hnp-config",
"name": "tree",
"version": "2.2.1",
"install": {}
}
八、常见问题与调试技巧
8.1 编译失败排查
问题1:依赖未找到
ERROR: openssl not found
解决方法:
# 检查依赖是否已编译
ls ../lycium/usr/ | grep openssl
# 手动编译依赖
./build.sh openssl
# 检查 HPKBUILD 中 depends 字段
cat ../thirdparty/curl/HPKBUILD | grep depends
问题2:工具链缺失
aarch64-linux-ohos-clang: command not found
解决方法:
# 检查 OHOS_SDK 环境变量
echo $OHOS_SDK
# 检查工具链是否存在
ls $OHOS_SDK/native/llvm/bin/ | grep clang
# 如果不存在,框架会自动从 Buildtools 解压
ls ../lycium/Buildtools/toolchain.tar.gz
问题3:架构不支持
configure: error: cannot guess build type
解决方法:
某些库的 configure 脚本不认识 OpenHarmony 架构,需要传递 --host 参数:
# 在 build() 中添加
./configure --host=aarch64-linux-ohos \
--build=x86_64-linux-gnu
8.2 日志查看
编译日志位置:
# 单库编译日志
ls ../thirdparty/curl/
├── curl-curl-8_0_1-arm64-v8a-lycium_build.log
└── curl-public-lycium_build.log
# 框架总日志
cat ../lycium/lycium_build_intl.log
实时查看日志:
# 另开一个终端
tail -f ../thirdparty/curl/*-lycium_build.log
8.3 调试技巧
技巧1:跳过下载
如果源码已下载,可以跳过下载阶段:
# 在 HPKBUILD 中设置
downloadpackage=false
技巧2:保留构建目录
调试时可以保留构建目录:
# 注释掉 cleanbuild 中的删除命令
cleanbuild() {
# rm -rf ${PWD}/$builddir # 临时注释
}
技巧3:手动执行编译
进入构建目录手动调试:
cd ../thirdparty/curl/curl-curl-8_0_1/arm64-v8a-build
cat CMakeCache.txt # 查看 cmake 配置
make VERBOSE=1 # 显示详细编译命令
8.4 经验之谈:musl libc 兼容性
OpenHarmony 使用 musl libc,与常见的 glibc 有部分差异:
问题1:缺少 strverscmp 函数
undefined reference to `strverscmp'
解决:链接 muslc_gext 库
# 在 HPKBUILD 的 build() 中添加
export LDFLAGS="$LDFLAGS -lmuslc_gext -L$LYCIUM_ROOT/usr/muslc_gext/$ARCH/lib"
问题2:getwd 函数已废弃
warning: the `getwd' function is dangerous
解决:替换为 getcwd
// 错误
char *dir = getwd(buf);
// 正确
char *dir = getcwd(buf, sizeof(buf));
九、框架设计思想总结
1. 约定优于配置(Convention over Configuration)
- 标准化 HPKBUILD 接口
- 固定的目录结构
- 统一的产物输出路径
2. 声明式构建(Declarative Build)
# 你只需要声明"是什么"
pkgname=curl
depends=("openssl")
# 框架负责处理"怎么做"
自动下载 → 自动编译依赖 → 自动传递路径
3. 依赖驱动(Dependency-Driven)
通过退出码协议实现依赖自动解析,无需手动指定编译顺序。
4. 环境隔离(Environment Isolation)
每个架构独立的构建目录,避免交叉污染:
builddir/
├── armeabi-v7a-build/
└── arm64-v8a-build/
更多推荐

所有评论(0)