HarmonyOS鸿蒙三方库移植框架lycium中的HPKBUILD 与 HPKCHECK 使用指南
鉴于有些初学的小伙伴,对lycium编译框架和框架中HPKBUILD 与 HPKCHECK脚本的写法用法感到陌生,特写此文。一个面向 OpenHarmony 三方库交叉编译的构建脚本编写的简易教程 ,基于 lycium_plusplus 编译框架的。
更多交流学习,欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
猫哥的博客:https://blog.csdn.net/qq8864
Lycium编译框架地址:
tpc_c_cplusplus框架介绍地址:https://gitcode.com/openharmony-sig/tpc_c_cplusplus
lycium_plusplus框架地址:https://gitcode.com/OpenHarmonyPCDeveloper/lycium_plusplus
一、背景介绍
在 OpenHarmony 生态中,大量 C/C++ 三方库需要从 Linux 交叉编译到 OH 系统(arm64-v8a / armeabi-v7a / x86_64)。lycium_plusplus 提供了一个自动化编译框架,核心是两个配置文件:
| 文件 | 作用 |
|---|---|
| HPKBUILD | 描述库的元信息、源码获取方式、编译、打包、清理等所有构建步骤(类似 Arch Linux 的 PKGBUILD) |
| HPKCHECK | 描述在 OpenHarmony 真机/开发板上如何对该库进行测试验证 |
二、项目结构速览
lycium_plusplus/
├── lycium/ # 编译框架核心
│ ├── build.sh # 主构建入口(交叉编译)
│ ├── build_local.sh # 鸿蒙电脑本机构建入口
│ ├── script/
│ │ ├── build_hpk.sh # 每个库的构建驱动脚本(自动加载 HPKBUILD)
│ │ └── envset.sh # OHOS SDK 交叉编译环境变量设置
│ ├── template/ # HPKBUILD / HPKCHECK 模板
│ └── usr/ # 编译产物安装目录
├── community/ # 社区三方库(每个库一个文件夹)
│ ├── openssl_1_0_2u/
│ │ ├── HPKBUILD
│ ├── bzip2_1_0_8/
│ │ ├── HPKBUILD
│ │ └── HPKCHECK
│ └── ...(200+ 个库)
├── external_deps/ # 外部适配仓(独立维护的库)
│ ├── module.json # 外部库的 git 仓库配置
│ └── openssl/
│ ├── HPKBUILD
│ └── hnp.json
└── output/ # 打包产物输出目录
三、编译流程全景
用户执行: cd lycium && ./build.sh <库名>
build.sh(框架入口)
│
├── 检查环境(OHOS_SDK 等)
├── 在 community/ 或 external_deps/ 中查找 HPKBUILD
├── 在库目录下创建 build_hpk.sh / envset.sh 软链接
│
└── build_hpk.sh(自动加载 HPKBUILD)
│
├── downloadpackage? → 下载源码包
├── autounpack? → 解压源码
├── checksum? → SHA512SUM 校验
│
├── for each arch in archs[]:
│ ├── prepare() # 环境准备
│ ├── build() # 编译构建
│ ├── package() # 安装到 usr/ 目录
│ ├── archive()? # 打包 HNP 产物(可选)
│ └── check() # 编译检查
│
└── 记录构建结果到 hpk_build.csv
四、HPKBUILD 文件详解
4.1 文件结构总览
一个完整的 HPKBUILD 由三部分组成:
- 元信息变量区 — 库名、版本、架构、依赖等声明
- 控制变量区 — 下载、解压、编译方式等开关
- 函数区 —
prepare()/build()/package()/check()/cleanbuild()
4.2 元信息变量
| 变量 | 含义 | 是否必填 | 示例 |
|---|---|---|---|
pkgname |
库名称(唯一标识) | ✅ | pkgname=openssl_1_0_2u |
pkgver |
库版本 | ✅ | pkgver=1.0.8 |
pkgrel |
发布号(版本迭代用) | ✅ | pkgrel=0 |
pkgdesc |
库描述 | ✅ | pkgdesc="TLS/SSL and crypto library" |
url |
项目官网 | ✅ | url="https://www.openssl.org/" |
archs |
支持的目标 CPU 架构数组 | ✅ | archs=("armeabi-v7a" "arm64-v8a") |
license |
开源协议 | ✅ | license=("Apache License 2.0") |
depends |
运行时依赖的库名数组 | 可选 | depends=("openssl_1_1_1w" "zstd_1_5_6") |
makedepends |
构建时需要的主机工具 | 可选 | makedepends=("tclsh8.6") |
4.3 控制变量
| 变量 | 默认值 | 说明 |
|---|---|---|
source |
— | 源码下载 URL |
downloadpackage |
true |
是否自动下载压缩包。对于 git clone 场景设为 false |
autounpack |
true |
是否自动解压。特殊场景(如需要先 patch 再解压)设为 false |
buildtools |
cmake |
构建系统类型:cmake / configure / make |
builddir |
— | 源码解压后的目录名(编译目录) |
packagename |
— | 压缩包文件名 |
patchflag |
— | 自定义变量,用于控制只打一次 patch |
4.4 核心函数
4.4.1 prepare() — 编译准备
prepare() {
# 1. 设置交叉编译环境变量(引用 envset.sh 中的 setarm32ENV / setarm64ENV)
# 2. 创建架构专属的构建目录(避免多架构冲突)
# 3. 打 patch(仅打一次)
# 4. 拷贝源码到构建目录
}
关键原则:不同架构需要独立的构建目录,防止编译产物互相覆盖。
4.4.2 build() — 执行编译
build() {
# $@ 参数包含框架自动注入的依赖搜索路径和安装路径
# $ARCH 当前正在编译的架构
# $buildlog 日志文件路径
# $MAKE 定义在 build.sh 中,默认 make -j8
# ${OHOS_SDK}/native/build-tools/cmake/bin/cmake OH 提供的 cmake
}
三种主流构建方式对比:
| buildtools | 典型调用方式 |
|---|---|
cmake |
cmake "$@" -DOHOS_ARCH=$ARCH -B$ARCH-build -S./ |
configure |
./configure "$@" --host=$host --prefix=$LYCIUM_ROOT/usr/$pkgname/$ARCH |
make |
$MAKE CC=${cc} AR=${ar} ... |
4.4.3 package() — 安装打包
package() {
# 将编译产物安装到 $LYCIUM_ROOT/usr/$pkgname/$ARCH/
# cmake: make install
# configure: make install
# make: make install PREFIX=...
}
4.4.4 check() — 编译后检查
check() {
# 编译阶段(host 端)可执行的检查
# 对于需要在开发板上运行的测试,打印提示
echo "The test must be on an OpenHarmony device!"
}
4.4.5 cleanbuild() — 清理
cleanbuild() {
rm -rf ${PWD}/$builddir $builddir-*-build
}
4.5 系统内置可用变量
| 变量 | 来源 | 含义 |
|---|---|---|
$ARCH |
build_hpk.sh 循环赋值 |
当前架构,如 arm64-v8a |
$OHOS_SDK |
用户环境变量 | OHOS SDK 根目录 |
$SYSROOT |
build.sh 导出 |
系统 sysroot 路径 |
$LYCIUM_ROOT |
build.sh 导出 |
lycium 根目录 |
$MAKE |
build.sh 导出 |
make -j8 |
$buildlog |
build_hpk.sh 赋值 |
本次构建的日志文件路径 |
$pkgconfigpath |
build_hpk.sh 函数 configuredependpath() |
依赖库的 pkgconfig 路径 |
$OHOS_CMAKE_TOOLCHAIN_FILE |
build.sh 赋值 |
cmake 工具链文件路径 |
$publicbuildlog |
build_hpk.sh 赋值 |
公开日志路径 |
五、HPKBUILD 实战案例
案例 1:configure 方式 — OpenSSL 1.0.2u
文件位置: community/openssl_1_0_2u/HPKBUILD
pkgname=openssl_1_0_2u
pkgver=OpenSSL_1_0_2u
pkgrel=0
pkgdesc="TLS/SSL and crypto library"
url="https://www.openssl.org/"
archs=("armeabi-v7a" "arm64-v8a")
license=("Apache License 2.0")
depends=()
makedepends=()
source="https://github.com/openssl/${pkgname:0:7}/archive/refs/tags/$pkgver.tar.gz"
autounpack=true
downloadpackage=true
buildtools="configure"
builddir=${pkgname:0:7}-${pkgver}
packagename=$builddir.tar.gz
source envset.sh # 导入环境设置函数
host=
prepare() {
cp -rf $builddir $builddir-$ARCH-build # 每个架构独立拷贝一份
if [ $ARCH == "armeabi-v7a" ]; then
setarm32ENV # 设置 arm32 交叉编译环境
host=linux-generic32
elif [ $ARCH == "arm64-v8a" ]; then
setarm64ENV # 设置 arm64 交叉编译环境
host=linux-aarch64
fi
}
build() {
cd $builddir-$ARCH-build
# "$@" 包含了 --prefix 等路径参数
PKG_CONFIG_LIBDIR=$pkgconfigpath ./Configure enable-gost "$@" -fPIC $host > $buildlog 2>&1
$MAKE >> $buildlog 2>&1
ret=$?
cd $OLDPWD
return $ret
}
package() {
cd $builddir-$ARCH-build
$MAKE install >> $buildlog 2>&1
cd $OLDPWD
}
check() {
# 清理 prepare 中设置的环境
unset host
[ $ARCH == "armeabi-v7a" ] && unsetarm32ENV || unsetarm64ENV
echo "The test must be on an OpenHarmony device!"
}
cleanbuild() {
rm -rf ${PWD}/$builddir $builddir-*-build
}
要点解析:
- 使用
buildtools="configure"声明构建系统类型 - 通过
cp -rf $builddir $builddir-$ARCH-build创建独立目录,不同架构互不干扰 source envset.sh导入setarm32ENV/setarm64ENV函数prepare()中根据$ARCH分别设置编译器环境
案例 2:cmake 方式 — Catch2 测试框架
文件位置: community/Catch2/HPKBUILD
pkgname=Catch2
pkgver=v2.13.8
pkgrel=0
pkgdesc="Catch2 is mainly a unit testing framework for C++"
url="https://github.com/catchorg/Catch2"
archs=("armeabi-v7a" "arm64-v8a")
license=("BSL-1.0")
depends=()
makedepends=()
source="https://github.com/catchorg/$pkgname/archive/refs/tags/$pkgver.tar.gz"
downloadpackage=true
autounpack=true
buildtools="cmake"
builddir=${pkgname}-${pkgver:1}
packagename=$builddir.tar.gz
prepare() {
mkdir -p $builddir/$ARCH-build # cmake 方式:在 builddir 内建架构目录
}
build() {
cd $builddir
# "$@" 包含 -DCMAKE_FIND_ROOT_PATH=... -DCMAKE_TOOLCHAIN_FILE=... -DCMAKE_INSTALL_PREFIX=...
PKG_CONFIG_LIBDIR="${pkgconfigpath}" \
${OHOS_SDK}/native/build-tools/cmake/bin/cmake "$@" \
-DOHOS_ARCH=$ARCH \
-DCATCH_DEVELOPMENT_BUILD=ON \
-DCATCH_BUILD_TESTING=ON \
-B$ARCH-build -S./ -L > $buildlog 2>&1
$MAKE VERBOSE=1 -C $ARCH-build >> $buildlog 2>&1
ret=$?
cd $OLDPWD
return $ret
}
package() {
cd $builddir
$MAKE VERBOSE=1 -C $ARCH-build install >> $buildlog 2>&1
cd $OLDPWD
}
check() {
echo "The test must be on an OpenHarmony device!"
# 修改 CTestTestfile.cmake 中的 cmake 路径以适配 OHOS
cd $builddir/$ARCH-build
ohos_sdk_cmake_path=${OHOS_SDK//\//\\\/}"\/native\/build-tools\/cmake\/bin\/cmake"
sed -i 's/'$ohos_sdk_cmake_path'/cmake/' ./projects/CTestTestfile.cmake
cd $OLDPWD
}
cleanbuild() {
rm -rf ${PWD}/$builddir
}
要点解析:
- cmake 方式使用
buildtools="cmake"(默认值,可不写) - 构建目录约定:
$builddir/$ARCH-build - cmake 必须使用
${OHOS_SDK}/native/build-tools/cmake/bin/cmake "$@"携带了-DCMAKE_FIND_ROOT_PATH、-DCMAKE_TOOLCHAIN_FILE、-DCMAKE_INSTALL_PREFIX等关键参数
案例 3:make 方式 — bzip2
文件位置: community/bzip2_1_0_8/HPKBUILD
pkgname=bzip2_1_0_8
pkgver=1.0.8
pkgdesc="bzip2 is a freely available, high-quality data compressor."
url=https://sourceware.org/git/bzip2
archs=(armeabi-v7a arm64-v8a)
license=(bzip2-1.0.6)
depends=()
makedepends=()
source= # 无压缩包(git clone 获取)
autounpack=false
downloadpackage=false
buildtools=make # 声明 make 构建
clonesrcflag=true
commitid=6a8690fc8d26c815e798c588f796eabe9d684cf0
builddir=bzip2-${pkgver}
packagename=
cc=; ar=; ranlib=
prepare() {
if ${clonesrcflag}; then
git clone ${url}.git ${builddir} > ${publicbuildlog} 2>&1 || return -1
cd ${builddir}
git reset --hard ${commitid}
cd ${OLDPWD}
clonesrcflag=false
fi
cp -rf $builddir $builddir-$ARCH-build # 独立目录
cd $builddir-$ARCH-build
# 手动指定交叉编译器
[ $ARCH == "armeabi-v7a" ] && cc=${OHOS_SDK}/native/llvm/bin/arm-linux-ohos-clang
[ $ARCH == "arm64-v8a" ] && cc=${OHOS_SDK}/native/llvm/bin/aarch64-linux-ohos-clang
ar=${OHOS_SDK}/native/llvm/bin/llvm-ar
ranlib=${OHOS_SDK}/native/llvm/bin/llvm-ranlib
cd $OLDPWD
}
build() {
cd $builddir-$ARCH-build
# 直接调用 make,手动传入 CC/AR/RANLIB
$MAKE VERBOSE=1 CC=${cc} AR=${ar} RANLIB=${ranlib} libbz2.a bzip2 bzip2recover > $buildlog 2>&1
ret=$?
cd $OLDPWD
return $ret
}
package() {
cd $builddir-$ARCH-build
$MAKE VERBOSE=1 install PREFIX=$LYCIUM_ROOT/usr/$pkgname/$ARCH >> $buildlog 2>&1
cd $OLDPWD
}
check() {
echo "The test must be on an OpenHarmony device!"
}
cleanbuild() {
rm -rf ${PWD}/$builddir $builddir-*-build
}
要点解析:
buildtools=make— 直接使用 Makefile 编译- Git clone 方式获取源码:
downloadpackage=false,autounpack=false - 手动指定 CC/AR/RANLIB 等交叉编译工具路径
- 安装时手动指定
PREFIX
案例 4:有依赖关系的复杂库 — curl
文件位置: community/curl_8_9_1/HPKBUILD
pkgname=curl_8_9_1
pkgver=curl-8_9_1
archs=("armeabi-v7a" "arm64-v8a")
depends=("openssl_1_1_1w" "zstd_1_5_6" "nghttp2") # 依赖三个库
source="https://gitee.com/lycium_pkg_mirror/${pkgname:0:4}/repository/archive/$pkgver.zip"
builddir=${pkgname:0:4}-${pkgver}
buildtools=cmake
prepare() {
if $patchflag; then
cd $builddir
patch -p1 < `pwd`/../curl_oh_pkg.patch # 打 patch
patchflag=false
cd $OLDPWD
fi
mkdir -p $builddir/$ARCH-build
}
build() {
cd $builddir
# "$@" 自动注入了 -DCMAKE_FIND_ROOT_PATH 用于搜索依赖库
${OHOS_SDK}/native/build-tools/cmake/bin/cmake "$@" \
-DCURL_CA_BUNDLE="/etc/ssl/certs/cacert.pem" \
-DCURL_ZSTD=ON -DENABLE_WEBSOCKETS=ON \
-B$ARCH-build -S./ > $buildlog 2>&1
$MAKE -C $ARCH-build >> $buildlog 2>&1
ret=$?
cd $OLDPWD
return $ret
}
要点:depends=("lib1" "lib2") 声明后,框架会自动:
- 检查依赖是否已编译完成
- 设置
$pkgconfigpath指向依赖库的 pkgconfig 目录 - 在 cmake 的
$@中注入-DCMAKE_FIND_ROOT_PATH
案例 5:外部适配仓 + HNP 打包 — OpenSSL 3.6
文件位置: external_deps/openssl/HPKBUILD
pkgname=openssl
pkgver=3.6
fullpkgver=openssl-3.6
archs=("arm64-v8a")
depends=()
source="https://gitcode.com/GitHub_Trending/ope/openssl.git"
autounpack=false
downloadpackage=false # git clone 方式
source envset.sh
prepare() {
if [ ! -d $builddir ]; then
git clone -b $fullpkgver $source $builddir # clone 指定分支
fi
setarm64ENV # 只支持 arm64-v8a
}
build() {
pushd $builddir
./config no-asm shared linux-aarch64 no-tests \
--prefix="${LYCIUM_ROOT}/usr/$pkgname/$ARCH" \
-D__OHOS__
make -j8 >> $buildlog 2>&1
popd
}
package() {
pushd $builddir
make install_sw >> $buildlog 2>&1
popd
}
archive() { # ★ 额外阶段:HNP 打包
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/
}
cleanbuild() {
rm -rf $builddir-$ARCH-build
unsetarm64ENV
}
要点:
archive()函数是可选的额外阶段,build_hpk.sh会自动检测并执行${HNP_TOOL}来自envset.sh中的setarm64ENV设置hnp.json是 HNP 打包的配置文件
六、archive() 与 install_local() 扩展函数
除了 4 个核心函数,HPKBUILD 还可以定义:
# HNP 打包(外部适配仓使用)
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/
}
# 本地安装(鸿蒙本机构建使用)
install_local() {
cp -r $LYCIUM_ROOT/usr/$pkgname/$ARCH/* ${INSTALL_LOCAL_PERFIX}/
}
# 恢复构建环境(清理 prepare 中设置的环境变量)
recoverpkgbuildenv() {
[ $ARCH == "arm64-v8a" ] && unsetarm64ENV
[ $ARCH == "armeabi-v7a" ] && unsetarm32ENV
}
build_hpk.sh 会通过 declare -F archive &>/dev/null 检测这些函数是否存在,存在则自动调用。
七、HPKCHECK — 测试验证文件
7.1 文件结构
# 1. 导入 HPKBUILD(获取 pkgname、builddir 等变量)
source HPKBUILD > /dev/null 2>&1
# 2. 定义测试日志路径
logfile=${LYCIUM_THIRDPARTY_ROOT}/${pkgname}/${pkgname}_${ARCH}_${OHOS_SDK_VER}_test.log
# 3. (可选)测试前准备
checkprepare() {
return 0
}
# 4. 在 OpenHarmony 设备上执行测试的核心函数
openharmonycheck() {
res=0
cd ${builddir}/${ARCH}-build
# 执行测试命令(ctest / make check / 直接运行可执行文件...)
ctest > ${logfile} 2>&1
res=$?
cd $OLDPWD
return $res
}
7.2 多种测试模式示例
模式 1:ctest(cmake 项目的标准测试)
# Catch2/HPKCHECK
openharmonycheck() {
res=0
cd $builddir/$ARCH-build
ctest >> $logfile 2>&1
res=$?
if [ $res -ne 0 ]; then
mkdir ${LYCIUM_FAULT_PATH}/${pkgname}
cp Testing/Temporary/LastTest.log ${LYCIUM_FAULT_PATH}/${pkgname}/
fi
cd $OLDPWD
return $res
}
模式 2:make check(autotools / Makefile 项目)
# bzip2/HPKCHECK
openharmonycheck() {
cd $builddir-$ARCH-build
make check > ${logfile} 2>&1
res=$?
cd $OLDPWD
return $res
}
模式 3:直接运行可执行文件
# libwebsockets/HPKCHECK
openharmonycheck() {
res=0
cd ${builddir}/${ARCH}-build/bin
./libwebsockets-test-server > ${logfile} 2>&1
res=$?
cd $OLDPWD
return $res
}
模式 4:带网络检查的测试
# curl/HPKCHECK
openharmonycheck() {
res=0
# 先检查网络
ping www.baidu.com -c3 >> /dev/null
if [ $? -ne 0 ]; then
echo "network not ready!"
return 1
fi
cd ${builddir}/${ARCH}-build
cp ../../curl_test.sh ./
bash curl_test.sh > ${logfile} 2>&1
res=$?
cd $OLDPWD
return $res
}
模式 5:复杂测试用例(ImageMagick)
# ImageMagick/HPKCHECK
openharmonycheck() {
res=0
cd ${builddir}-${ARCH}-build
make check-TESTS > ${logfile} 2>&1
res=$?
if [ ${res} -ne 0 ]; then
# 修复路径问题后重试
find . -type f -exec sed -i.bak 's|/bin/bash|/data/CIusr/bin/bash|g' {} \;
make check-TESTS > ${logfile} 2>&1
res=$?
if [ ${res} -ne 0 ]; then
mkdir -p ${LYCIUM_FAULT_PATH}/${pkgname}
cp test-suite.log ${LYCIUM_FAULT_PATH}/${pkgname}/
fi
fi
cd ${OLDPWD}
return ${res}
}
八、envset.sh — 交叉编译环境变量
envset.sh 提供了不同架构的环境设置函数:
arm32 (armeabi-v7a)
setarm32ENV() {
export CC=${OHOS_SDK}/native/llvm/bin/arm-linux-ohos-clang
export CXX=${OHOS_SDK}/native/llvm/bin/arm-linux-ohos-clang++
export CFLAGS="-DOHOS_NDK -fPIC -march=armv7a -D__MUSL__=1"
export CXXFLAGS="-DOHOS_NDK -fPIC -march=armv7a -D__MUSL__=1"
export AR=${OHOS_SDK}/native/llvm/bin/llvm-ar
export AS=${OHOS_SDK}/native/llvm/bin/llvm-as
export LD=${OHOS_SDK}/native/llvm/bin/ld.lld
export STRIP=${OHOS_SDK}/native/llvm/bin/llvm-strip
export RANLIB=${OHOS_SDK}/native/llvm/bin/llvm-ranlib
export OBJDUMP=${OHOS_SDK}/native/llvm/bin/llvm-objdump
export OBJCOPY=${OHOS_SDK}/native/llvm/bin/llvm-objcopy
export NM=${OHOS_SDK}/native/llvm/bin/llvm-nm
}
arm64 (arm64-v8a)
setarm64ENV() {
export TARGET_PLATFORM=aarch64-linux-ohos
export CC=${OHOS_SDK}/native/llvm/bin/aarch64-linux-ohos-clang
export CXX=${OHOS_SDK}/native/llvm/bin/aarch64-linux-ohos-clang++
export CFLAGS="-DOHOS_NDK -fPIC -D__MUSL__=1 -D__OHOS__ --sysroot=${SYSROOT}"
export CXXFLAGS="${CFLAGS}"
export LDFLAGS="--target=${TARGET_PLATFORM} --sysroot=${SYSROOT}"
export HNP_TOOL=${OHOS_SDK}/toolchains/hnpcli # HNP 打包工具
}
关键提示
- 在 HPKBUILD 中通过
source envset.sh加载这些函数 prepare()中调用setarmXXENV,check()或package()中调用unsetarmXXENV清理- 也可以使用
recoverpkgbuildenv()函数统一管理环境清理
九、常见问题与最佳实践
9.1 架构独立目录
始终为不同架构创建独立的构建目录!
# 好:cmake 方式
mkdir -p $builddir/$ARCH-build
# 好:configure / make 方式
cp -rf $builddir $builddir-$ARCH-build
# 差:所有架构共用同一目录(编译产物会冲突)
9.2 patch 只打一次
patchflag=true
prepare() {
if $patchflag; then
cd $builddir
patch -p1 < `pwd`/../xxx.patch
patchflag=false # ★ 关键
cd $OLDPWD
fi
}
9.3 字符串截取技巧
HPKBUILD 中广泛使用 Shell 字符串操作来解析包名:
# 从 openssl_1_0_2u 中提取 openssl(取前 7 个字符)
${pkgname:0:7} → openssl
# 从 curl_8_9_1 中提取 curl(取前 4 个字符)
${pkgname:0:4} → curl
# 从 Catch2 v2.13.8 中去掉 v 前缀(从第 1 个字符开始)
${pkgver:1} → 2.13.8
9.4 buildtools 选择指南
| 项目构建方式 | buildtools 值 |
说明 |
|---|---|---|
| CMake | cmake(默认) |
推荐,支持最完善 |
| autoconf/configure | configure |
需设置 --host |
| 原生 Makefile | make |
手动传 CC/AR/RANLIB |
| 其他 | 留空或自定义 | 框架仅处理 cmake 和 configure 的逻辑 |
9.5 日志与调试
- 编译日志:
$buildlog— 每个架构各自的日志文件 - 公开日志:
$publicbuildlog— 跨架构共享的日志 - 查看日志:
cat <库目录>/*-lycium_build.log
9.6 外部依赖处理
对于 external_deps/ 中的库,通过 module.json 配置源码仓信息:
{
"module": [
{
"name": "openssl",
"branch": "ohos_3.6",
"version": "3.6",
"type": "git",
"url": "https://gitcode.com/OpenHarmonyPCDeveloper/ohos_openssl.git"
}
]
}
然后 ./build.sh openssl 即可自动 clone 并编译。
十、快速编写模板
当你需要为新的库编写 HPKBUILD 时,复制此模板并根据实际构建方式修改:
# Contributor: Your Name <youremail@domain.com>
# Maintainer: Your Name <youremail@domain.com>
pkgname=NAME # 库唯一名称
pkgver=VERSION # 版本号
pkgrel=0 # 发布号
pkgdesc="" # 描述
url="" # 官网
archs=("armeabi-v7a" "arm64-v8a")
license=() # 开源协议
depends=() # 依赖的库名列表
makedepends=() # 构建所需的主机工具
source="" # 源码下载 URL
downloadpackage=true
autounpack=true
# ★ 根据项目构建方式选择:cmake / configure / make
buildtools=cmake
builddir= # 解压后的目录
packagename=$builddir.tar.gz
prepare() {
mkdir -p $builddir/$ARCH-build
# ── 如果需要打 patch ──
# if $patchflag; then
# cd $builddir
# patch -p1 < `pwd`/../xxx.patch
# patchflag=false
# cd $OLDPWD
# fi
# ── 如果是 configure/make 方式 ──
# cp -rf $builddir $builddir-$ARCH-build
# source envset.sh
# [ $ARCH == "arm64-v8a" ] && setarm64ENV
}
build() {
cd $builddir
# ★ cmake 方式
${OHOS_SDK}/native/build-tools/cmake/bin/cmake "$@" \
-DOHOS_ARCH=$ARCH -B$ARCH-build -S./ > $buildlog 2>&1
$MAKE -C $ARCH-build >> $buildlog 2>&1
# ★ configure 方式(在 $builddir-$ARCH-build 内执行)
# ./configure "$@" --host=$host > $buildlog 2>&1
# $MAKE >> $buildlog 2>&1
# ★ make 方式(在 $builddir-$ARCH-build 内执行)
# $MAKE CC=${cc} AR=${ar} >> $buildlog 2>&1
ret=$?
cd $OLDPWD
return $ret
}
package() {
cd $builddir
$MAKE -C $ARCH-build install >> $buildlog 2>&1
cd $OLDPWD
}
# ★ 安装到本地(鸿蒙本机构建时需要)
# install_local() {
# cp -r $LYCIUM_ROOT/usr/$pkgname/$ARCH/* ${INSTALL_LOCAL_PERFIX}/
# }
# ★ HNP 打包(外部适配仓需要)
# archive() {
# mkdir -p ${LYCIUM_ROOT}/output/$ARCH
# pushd $LYCIUM_ROOT/usr/$pkgname/$ARCH
# tar -zvcf ${LYCIUM_ROOT}/output/$ARCH/${pkgname}_${pkgver}.tar.gz *
# popd
# }
check() {
echo "The test must be on an OpenHarmony device!"
}
cleanbuild() {
rm -rf ${PWD}/$builddir $builddir-*-build
}
配套 HPKCHECK 模板:
source HPKBUILD > /dev/null 2>&1
logfile=${LYCIUM_THIRDPARTY_ROOT}/${pkgname}/${pkgname}_${ARCH}_${OHOS_SDK_VER}_test.log
openharmonycheck() {
res=0
cd ${builddir}/${ARCH}-build
ctest > ${logfile} 2>&1
res=$?
if [ $res -ne 0 ]; then
mkdir -p ${LYCIUM_FAULT_PATH}/${pkgname}
cp Testing/Temporary/LastTest.log ${LYCIUM_FAULT_PATH}/${pkgname}/
fi
cd $OLDPWD
return $res
}
十一、总结
| 概念 | 一句话总结 |
|---|---|
| HPKBUILD | 描述库的完整构建过程:获取源码 → 准备环境 → 编译 → 安装 → 打包 |
| HPKCHECK | 描述在 OH 开发板上如何对库进行功能测试 |
| prepare() | 设置交叉编译环境、建目录、打 patch |
| build() | 根据 buildtools 类型执行编译命令 |
| package() | 将产物安装到 usr/$pkgname/$ARCH/ |
| archive() | 可选,用于 HNP 格式打包 |
| check() | 编译后检查,但真正的测试需在 OH 设备上运行 |
| envset.sh | 提供各架构的 CC/CXX/CFLAGS 等环境变量设置 |
| build.sh | 框架入口,自动处理依赖关系和多架构编译 |
掌握了 HPKBUILD 的写法,你就可以将任意 C/C++ 三方库适配到 OpenHarmony 系统,实现真正的跨平台编译构建。
参考链接
https://blog.csdn.net/qq8864/article/details/156576500
https://blog.csdn.net/qq8864/article/details/160327059
更多推荐



所有评论(0)