鉴于有些初学的小伙伴,对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 由三部分组成:

  1. 元信息变量区 — 库名、版本、架构、依赖等声明
  2. 控制变量区 — 下载、解压、编译方式等开关
  3. 函数区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") 声明后,框架会自动:

  1. 检查依赖是否已编译完成
  2. 设置 $pkgconfigpath 指向依赖库的 pkgconfig 目录
  3. 在 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() 中调用 setarmXXENVcheck()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
其他 留空或自定义 框架仅处理 cmakeconfigure 的逻辑

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

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐