OpenHarmony PC 第三方 C/C++ 库适配完整指南
概述
Lycium 是一个用于将第三方 C/C++ 库适配到 OpenHarmony PC 平台的自动化构建系统。它提供了一套标准化的构建流程,让开发者能够快速、高效地将现有的开源库移植到鸿蒙生态系统中。
核心特性
- 🚀 自动化构建流程:从下载源码到编译安装全程自动化
- 📦 依赖管理:自动处理库之间的依赖关系
- 🔧 多架构支持:支持 armeabi-v7a、arm64-v8a 等多种 CPU 架构
- ✅ 完整性校验:使用 SHA512 校验确保源码完整性
- 🧪 测试框架:内置测试框架,支持在设备上验证移植效果
- 🔄 跨平台编译:支持在 Linux、macOS、 上进行交叉编译出产物
系统架构
目录结构
lycium_plusplus/
├── lycium/
│ ├── build.sh # 主构建脚本
│ ├── script/ # 构建辅助脚本
│ │ ├── build_hpk.sh # 单个库的构建脚本
│ │ └── envset.sh # 环境变量设置
│ ├── template/ # 适配模板文件
│ │ ├── HPKBUILD # 构建配置模板
│ │ ├── HPKCHECK # 测试脚本模板
│ │ ├── README.md # 使用说明
│ │ └── SHA512SUM # 校验和模板
│ └── usr/ # 编译产物安装目录
├── thirdparty/ # 第三方库适配目录
├── community/ # 社区贡献的库
└── outerrepo/ # 外部仓库配置
工作流程
HPKBUILD配置 下载源码 SHA512校验 解压源码 prepare准备 build编译 package打包 安装到usr目录 check测试可选
HPKBUILD 文件详解
HPKBUILD 是 Lycium 构建系统的核心配置文件,定义了如何构建和打包一个第三方库。
基本元数据
bash
# 贡献者和维护者信息
# Contributor: Your Name <youremail@domain.com>
# Maintainer: Your Name <youremail@domain.com>
pkgname=NAME # 库名,必须唯一
pkgver=VERSION # 库版本号(如 1.2.3)
pkgrel=0 # 发布号(适配版本号)
pkgdesc="" # 库的简短描述
url="" # 项目官方网站
archs=("armeabi-v7a" "arm64-v8a") # 支持的 CPU 架构
license=() # 开源许可证(如 MIT、GPL)
架构说明
| 架构名称 | 说明 | 应用场景 |
|---|---|---|
armeabi-v7a |
ARM 32位架构 | 老旧设备、低端设备 |
arm64-v8a |
ARM 64位架构 | 现代设备、主流架构 |
x86 |
Intel 32位 | 模拟器、PC |
x86_64 |
Intel 64位 | 模拟器、PC |
依赖管理
bash
# 运行时依赖:编译和运行都需要的库
depends=("zlib" "openssl")
# 构建依赖:仅编译时需要的工具
makedepends=("cmake" "pkg-config" "autoconf")
依赖规则:
- 被依赖库的
archs必须是当前库archs的超集 - 依赖会自动按顺序构建
- 循环依赖会导致构建失败
源码配置
bash
# 源码下载地址
source="https://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
# 控制选项
downloadpackage=true # 是否自动下载(默认 true)
autounpack=true # 是否自动解压(默认 true)
buildtools="cmake" # 构建工具:cmake/configure/make
# 目录配置
builddir="$pkgname-$pkgver" # 解压后的源码目录名
packagename="$builddir.tar.gz" # 压缩包文件名
核心函数
1. prepare() - 准备阶段
在编译前进行必要的准备工作。
bash
prepare() {
cd $builddir
# 应用补丁
patch -p1 < ../fix-compilation.patch
# 修改配置文件
sed -i 's/old_value/new_value/g' config.h
# 创建必要的目录
mkdir -p build
cd ${OLDPWD}
}
常见用途:
- ✅ 应用 patch 补丁文件
- ✅ 修改源码中的硬编码路径
- ✅ 生成配置文件
- ✅ 处理特殊的解压需求
2. build() - 编译阶段
执行实际的编译构建。
bash
build() {
cd $builddir
# CMake 构建示例
${OHOS_SDK}/native/build-tools/cmake/bin/cmake \
"$@" \ # 自动传入的参数
-DOHOS_ARCH=$ARCH \ # 当前编译架构
-DBUILD_SHARED_LIBS=ON \ # 自定义参数
-B$ARCH-build \ # 构建目录
-S./ \ # 源码目录
-L # 列出所有变量
# 执行编译
make -j8 -C $ARCH-build
# 检查编译结果
ret=$?
cd $OLDPWD
return $ret
}
自动传入的参数("$@"):
bash
-DCMAKE_FIND_ROOT_PATH="/path/to/deps" # 依赖库搜索路径
-DCMAKE_TOOLCHAIN_FILE="/path/to/ohos.toolchain.cmake" # 工具链文件
-DCMAKE_INSTALL_PREFIX="/install/path" # 安装路径
-DCMAKE_BUILD_TYPE=Release # 构建类型
3. package() - 打包安装
将编译产物安装到指定目录。
bash
package() {
cd $builddir
# 使用构建系统的安装命令
make -C $ARCH-build install
# 或手动安装
# install -Dm755 $ARCH-build/lib*.so "$INSTALL_DIR/lib/"
# install -Dm644 include/*.h "$INSTALL_DIR/include/"
cd $OLDPWD
}
安装路径自动设置为:
$LYCIUM_ROOT/usr/$pkgname/$ARCH/
4. check() - 测试验证(可选)
bash
check() {
echo "The test must be on an OpenHarmony device!"
# 这个函数主要用于提示
# 实际测试在 HPKCHECK 文件中定义
}
5. cleanbuild() - 清理环境
bash
cleanbuild() {
rm -rf ${PWD}/$builddir
# 可选:保留源码包以便重新构建
# rm -rf ${PWD}/$packagename
}
实战案例:适配 zlib 库
让我们通过一个完整的例子来演示如何适配 zlib 压缩库。
第 1 步:创建目录
bash
cd thirdparty
mkdir zlib
cd zlib
第 2 步:编写 HPKBUILD
创建 HPKBUILD 文件:
bash
# Contributor: OpenHarmony TPC Team <tpc@openharmony.io>
# Maintainer: OpenHarmony TPC Team <tpc@openharmony.io>
pkgname=zlib
pkgver=1.3.1
pkgrel=0
pkgdesc="A Massively Spiffy Yet Delicately Unobtrusive Compression Library"
url="https://www.zlib.net/"
archs=("armeabi-v7a" "arm64-v8a")
license=("Zlib")
depends=()
makedepends=("cmake")
source="https://github.com/madler/zlib/archive/refs/tags/v$pkgver.tar.gz"
downloadpackage=true
autounpack=true
buildtools="cmake"
builddir="zlib-$pkgver"
packagename="v$pkgver.tar.gz"
prepare() {
cd $builddir
# zlib 默认构建静态库,我们需要动态库
# 可以通过 CMake 参数控制,这里不需要额外操作
cd ${OLDPWD}
}
build() {
cd $builddir
# 使用 CMake 构建
${OHOS_SDK}/native/build-tools/cmake/bin/cmake \
"$@" \
-DOHOS_ARCH=$ARCH \
-DBUILD_SHARED_LIBS=ON \
-B$ARCH-build \
-S./ \
-L
# 编译
make -j8 -C $ARCH-build
ret=$?
cd $OLDPWD
return $ret
}
package() {
cd $builddir
make -C $ARCH-build install
cd $OLDPWD
}
check() {
echo "The test must be on an OpenHarmony device!"
}
cleanbuild() {
rm -rf ${PWD}/$builddir
}
第 3 步:生成 SHA512SUM(可选但推荐)
bash
# 下载源码包
wget https://github.com/madler/zlib/archive/refs/tags/v1.3.1.tar.gz
# 计算 SHA512
sha512sum v1.3.1.tar.gz > SHA512SUM
# SHA512SUM 文件内容示例:
# 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17... v1.3.1.tar.gz
第 4 步:编译
bash
cd ../../lycium
./build.sh zlib
第 5 步:验证产物
bash
ls -lh usr/zlib/arm64-v8a/
# 应该看到:
# include/ - 头文件
# lib/ - 库文件(libz.so)
# share/ - 文档等
不同构建系统的适配
CMake 项目
这是最常见也是最简单的情况。
bash
buildtools="cmake"
build() {
cd $builddir
${OHOS_SDK}/native/build-tools/cmake/bin/cmake \
"$@" \
-DOHOS_ARCH=$ARCH \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTING=OFF \
-B$ARCH-build \
-S./
make -j8 -C $ARCH-build
ret=$?
cd $OLDPWD
return $ret
}
Configure/Autotools 项目
bash
buildtools="configure"
build() {
cd $builddir
# 创建构建目录
mkdir -p $ARCH-build
cd $ARCH-build
# 配置
../configure \
--prefix=$LYCIUM_ROOT/usr/$pkgname/$ARCH \
--host=aarch64-linux-ohos \
--enable-shared \
--disable-static
# 编译
make -j8
ret=$?
cd $OLDPWD
return $ret
}
Makefile 项目
bash
buildtools="make"
build() {
cd $builddir
# 直接使用 Make
make -j8 \
CC=${OHOS_SDK}/native/llvm/bin/aarch64-linux-ohos-clang \
CXX=${OHOS_SDK}/native/llvm/bin/aarch64-linux-ohos-clang++ \
PREFIX=$LYCIUM_ROOT/usr/$pkgname/$ARCH
ret=$?
cd $OLDPWD
return $ret
}
package() {
cd $builddir
make install PREFIX=$LYCIUM_ROOT/usr/$pkgname/$ARCH
cd $OLDPWD
}
HPKCHECK 文件详解
HPKCHECK 文件用于在 OpenHarmony 设备上进行测试验证。
基本结构
bash
# Contributor: Your Name <youremail@domain.com>
# Maintainer: Your Name <youremail@domain.com>
source HPKBUILD > /dev/null 2>&1 # 导入 HPKBUILD 配置
# 日志文件路径
logfile=${LYCIUM_THIRDPARTY_ROOT}/${pkgname}/${pkgname}_${ARCH}_${OHOS_SDK_VER}_test.log
# 测试前的准备(可选)
checkprepare() {
# 编译测试程序
# 复制测试数据
return 0
}
# 在 OpenHarmony 环境执行测试
openharmonycheck() {
res=0
cd ${builddir}/${ARCH}-build
# 执行测试命令
ctest > ${logfile} 2>&1
res=$?
cd $OLDPWD
return $res
}
完整的测试示例
bash
source HPKBUILD > /dev/null 2>&1
logfile=${LYCIUM_THIRDPARTY_ROOT}/${pkgname}/${pkgname}_${ARCH}_${OHOS_SDK_VER}_test.log
checkprepare() {
echo "Preparing test environment..." | tee -a ${logfile}
# 确保测试目录存在
mkdir -p ${LYCIUM_THIRDPARTY_ROOT}/${pkgname}
return 0
}
openharmonycheck() {
res=0
echo "========================================" | tee -a ${logfile}
echo "Testing ${pkgname} ${pkgver}" | tee -a ${logfile}
echo "Architecture: ${ARCH}" | tee -a ${logfile}
echo "SDK Version: ${OHOS_SDK_VER}" | tee -a ${logfile}
echo "========================================" | tee -a ${logfile}
cd ${builddir}/${ARCH}-build
# 运行 CTest
if [ -f CTestTestfile.cmake ]; then
ctest --output-on-failure >> ${logfile} 2>&1
res=$?
else
# 手动运行测试程序
if [ -f ./test_program ]; then
./test_program >> ${logfile} 2>&1
res=$?
else
echo "No test program found" | tee -a ${logfile}
res=0 # 没有测试不算失败
fi
fi
cd $OLDPWD
if [ $res -eq 0 ]; then
echo "✅ All tests passed!" | tee -a ${logfile}
else
echo "❌ Some tests failed! Check ${logfile} for details" | tee -a ${logfile}
fi
return $res
}
SHA512SUM 文件
用于验证下载的源码包的完整性,防止文件损坏或被篡改。
格式
<sha512-hash> <filename>
示例
e29c45d60eacc25... zlib-1.3.1.tar.gz
f8b3d3e42a9d1c... fix-compilation.patch
生成方法
macOS
bash
# 安装 coreutils(如果没有 sha512sum)
brew install coreutils
# 生成校验和
sha512sum *.tar.gz *.patch > SHA512SUM
Linux
bash
sha512sum *.tar.gz *.patch > SHA512SUM
验证流程
构建系统会自动:
- 下载源码包
- 计算下载文件的 SHA512
- 与 SHA512SUM 中的值比对
- 如果不匹配,中止构建并报错
高级技巧
1. 应用补丁文件
bash
prepare() {
cd $builddir
# 应用单个补丁
patch -p1 < ../fix-build.patch
# 应用多个补丁
for patch_file in ../*.patch; do
echo "Applying $patch_file"
patch -p1 < "$patch_file"
done
cd ${OLDPWD}
}
补丁文件也需要在 SHA512SUM 中记录:
bash
sha512sum *.tar.gz *.patch > SHA512SUM
2. 跨架构依赖处理
bash
build() {
cd $builddir
# 设置依赖库路径
export PKG_CONFIG_PATH="$LYCIUM_ROOT/usr/zlib/$ARCH/lib/pkgconfig"
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$LYCIUM_ROOT/usr/openssl/$ARCH/lib/pkgconfig"
${OHOS_SDK}/native/build-tools/cmake/bin/cmake \
"$@" \
-DOHOS_ARCH=$ARCH \
-DZLIB_ROOT=$LYCIUM_ROOT/usr/zlib/$ARCH \
-B$ARCH-build \
-S./
make -j8 -C $ARCH-build
ret=$?
cd $OLDPWD
return $ret
}
3. 处理 Git 仓库源码
某些项目只能通过 git clone 获取(例如包含 submodule):
bash
downloadpackage=false # 不自动下载
autounpack=false # 不自动解压
prepare() {
# 手动克隆仓库
if [ ! -d $builddir ]; then
git clone --recursive https://github.com/user/project.git $builddir
cd $builddir
git checkout v$pkgver
cd ${OLDPWD}
fi
}
4. 多配置构建
bash
build() {
cd $builddir
# 根据架构调整编译选项
if [ "$ARCH" = "armeabi-v7a" ]; then
extra_flags="-DENABLE_NEON=OFF"
else
extra_flags="-DENABLE_NEON=ON"
fi
${OHOS_SDK}/native/build-tools/cmake/bin/cmake \
"$@" \
-DOHOS_ARCH=$ARCH \
$extra_flags \
-B$ARCH-build \
-S./
make -j8 -C $ARCH-build
ret=$?
cd $OLDPWD
return $ret
}
5. 自定义安装
有些项目的 make install 不符合要求,需要手动安装:
bash
package() {
cd $builddir
install_prefix="$LYCIUM_ROOT/usr/$pkgname/$ARCH"
# 安装库文件
install -Dm755 $ARCH-build/lib*.so.* "$install_prefix/lib/"
ln -sf lib*.so.* "$install_prefix/lib/lib*.so"
# 安装头文件
mkdir -p "$install_prefix/include"
cp -r include/* "$install_prefix/include/"
# 安装 pkg-config 文件
install -Dm644 $ARCH-build/*.pc "$install_prefix/lib/pkgconfig/"
cd $OLDPWD
}
使用构建系统
编译单个库
bash
cd lycium
./build.sh <library-name>
编译多个库
bash
./build.sh zlib openssl curl
编译所有库
bash
./build.sh
查看编译日志
bash
# 实时日志
tail -f lycium_build_intl.log
# 完整日志
cat lycium_build_intl.log
清理并重新编译
bash
# 清理特定库
cd thirdparty/zlib
rm -rf zlib-1.3.1
# 重新编译
cd ../../lycium
./build.sh zlib
常见问题排查
问题 1:找不到依赖库
错误信息:
CMake Error: Could not find package "ZLIB"
解决方案:
- 确保依赖库已经编译
- 检查
depends=()是否正确配置 - 在 build() 函数中添加搜索路径
bash
build() {
cd $builddir
${OHOS_SDK}/native/build-tools/cmake/bin/cmake \
"$@" \
-DOHOS_ARCH=$ARCH \
-DCMAKE_PREFIX_PATH="$LYCIUM_ROOT/usr/zlib/$ARCH" \
-B$ARCH-build \
-S./
make -j8 -C $ARCH-build
ret=$?
cd $OLDPWD
return $ret
}
问题 2:交叉编译失败
错误信息:
error: unsupported platform
解决方案:
- 确保使用正确的工具链文件
- 检查 CMake 配置是否正确识别目标平台
- 可能需要在 prepare() 中修改源码
bash
prepare() {
cd $builddir
# 修改配置以支持 OpenHarmony
sed -i 's/Linux/OpenHarmony/' CMakeLists.txt
cd ${OLDPWD}
}
问题 3:SHA512 校验失败
错误信息:
SHA512 checksum mismatch
解决方案:
- 重新下载源码包
- 重新生成 SHA512SUM 文件
- 或者临时删除 SHA512SUM 文件(不推荐)
bash
# 重新生成
rm SHA512SUM
wget <source-url>
sha512sum *.tar.gz > SHA512SUM
问题 4:编译产物缺少文件
现象 :
编译成功但安装目录缺少 .so 文件或头文件
解决方案:
- 检查 package() 函数是否正确执行
- 查看是否需要手动安装
- 检查构建选项(如 BUILD_SHARED_LIBS)
bash
package() {
cd $builddir
# 使用 VERBOSE 模式查看安装了什么
make -C $ARCH-build install VERBOSE=1
# 或检查构建目录内容
ls -lR $ARCH-build/
cd $OLDPWD
}
问题 5:多架构编译冲突
现象 :
arm64-v8a 编译时使用了 armeabi-v7a 的产物
解决方案 :
确保每个架构使用独立的构建目录:
bash
build() {
cd $builddir
# 使用 $ARCH-build 而不是固定的 build
${OHOS_SDK}/native/build-tools/cmake/bin/cmake \
"$@" \
-DOHOS_ARCH=$ARCH \
-B$ARCH-build \ # 关键:架构相关的构建目录
-S./
make -j8 -C $ARCH-build
ret=$?
cd $OLDPWD
return $ret
}
最佳实践
1. 版本管理
- ✅ 使用精确的版本号(1.2.3)
- ✅ 在
pkgrel中记录适配版本 - ✅ 提交时包含版本信息
2. 补丁管理
- ✅ 补丁文件命名要有意义:
fix-cross-compile.patch - ✅ 在补丁开头注释说明用途
- ✅ 尽量将补丁提交到上游项目
3. 测试验证
- ✅ 编写完整的 HPKCHECK
- ✅ 在真实设备上测试
- ✅ 记录测试日志
4. 文档编写
在库目录下创建 README.md:
markdown
# zlib for OpenHarmony
## 版本信息
- zlib version: 1.3.1
- Adaptation version: 0
- Supported architectures: armeabi-v7a, arm64-v8a
## 编译
\`\`\`bash
cd lycium
./build.sh zlib
\`\`\`
## 使用
\`\`\`cmake
find_package(ZLIB REQUIRED)
target_link_libraries(your_target ZLIB::ZLIB)
\`\`\`
## 已知问题
- 无
## 测试状态
- ✅ arm64-v8a: Passed
- ✅ armeabi-v7a: Passed
5. 代码审查清单
提交前检查:
-
pkgname唯一且与目录名一致 -
pkgver和pkgrel正确 -
depends列出所有依赖 -
archs根据实际测试结果填写 -
license字段已填写 - SHA512SUM 文件存在且正确
- 所有函数都有正确的返回值
- 补丁文件已添加注释
- 在目标架构上测试通过
环境变量参考
构建过程中可用的环境变量:
| 变量名 | 说明 | 示例值 |
|---|---|---|
OHOS_SDK |
OpenHarmony SDK 路径 | /Users/user/Library/OpenHarmony/Sdk/20 |
ARCH |
当前编译的架构 | arm64-v8a |
LYCIUM_ROOT |
Lycium 根目录 | /path/to/lycium |
CLANG_VERSION |
Clang 编译器版本 | 15.0.4 |
SYSROOT |
系统根目录 | $OHOS_SDK/native/sysroot |
pkgname |
当前库名 | zlib |
pkgver |
当前库版本 | 1.3.1 |
builddir |
源码目录 | zlib-1.3.1 |
工具链路径
| 工具 | 路径 |
|---|---|
| CMake | ${OHOS_SDK}/native/build-tools/cmake/bin/cmake |
| Clang (arm64) | ${OHOS_SDK}/native/llvm/bin/aarch64-linux-ohos-clang |
| Clang++ (arm64) | ${OHOS_SDK}/native/llvm/bin/aarch64-linux-ohos-clang++ |
| Clang (arm) | ${OHOS_SDK}/native/llvm/bin/arm-linux-ohos-clang |
| Clang++ (arm) | ${OHOS_SDK}/native/llvm/bin/arm-linux-ohos-clang++ |
示例库集合
简单库(无依赖)
- zlib:压缩库
- bzip2:压缩库
- json-c:JSON 解析库
中等复杂度(有依赖)
- libpng:依赖 zlib
- curl:依赖 openssl, zlib
- sqlite:数据库,无依赖但构建复杂
复杂库
- FFmpeg:依赖多个编解码库
- OpenCV:依赖众多图像处理库
- Qt:大型 GUI 框架
总结
Lycium 构建系统为 OpenHarmony PC 平台的第三方库适配提供了标准化、自动化的解决方案。通过正确编写 HPKBUILD 文件,开发者可以:
- ✅ 快速移植:标准化流程减少重复工作
- ✅ 依赖管理:自动处理库之间的依赖关系
- ✅ 质量保证:SHA512 校验和测试框架确保质量
- ✅ 社区协作:统一的格式便于代码审查和维护
关键要点
- 📝 HPKBUILD 是核心,定义了整个构建流程
- 🔍 依赖管理 是关键,确保 archs 的超集关系
- 🎯 架构支持 要根据实际测试结果填写
- ✅ 测试验证 在真实设备上进行
- 📚 文档完善 帮助其他开发者使用
下一步
- 从简单的库开始(如 zlib)
- 逐步尝试有依赖的库
- 贡献到社区仓库
- 参与代码审查