OpenHarmony 通用C/C++三方库 标准化鸿蒙化适配

✨ 核心结论:任何一款C/C++三方库,仅需6个文件即可完成完整的鸿蒙化适配,无多余文件,标准化程度拉满
✨ 适配核心:鸿蒙官方提供了 标准化的C/C++库适配模板+编译规范,统一采用「交叉编译」+「GN编译」的方式完成移植,所有开源C/C++库均遵循此标准,适配成本极低
✨ 参考规范:https://atomgit.com/openharmony-tpc/tpc_resource#cc%E8%AF%AD%E8%A8%80

这是本次指南的核心内容,鸿蒙的底层能力、三方库生态均依赖C/C++库的支撑,官方对C/C++库的鸿蒙化适配做了极致标准化的定义,所有适配工作均围绕「固定6个文件」展开,无任何额外开发工作,所有C/C++库的适配流程、文件结构完全一致。

1 适配核心:仅需6个文件,完成全量鸿蒙化

所有C/C++三方库的鸿蒙化适配,最终产出物固定为6个文件,缺一不可,文件清单及作用如下,所有文件均有官方标准模板,直接复用修改即可:

├── HPKBUILD          # 核心文件:编译构建脚本(configure/cmake/make编译逻辑、交叉编译配置、打包安装)
├── HPKCHECK          # 测试校验脚本:定义鸿蒙设备端的测试逻辑、日志输出、用例执行
├── README.OpenSource # 开源声明文件:必填,标注库的开源协议、版权信息、源码来源
├── README_zh.md      # 中文说明文档:适配说明、编译步骤、使用方式、注意事项
├── SHA512SUM         # 可选:源码包哈希校验文件,校验下载的源码完整性,无需校验可忽略
├── xxx_oh_pkg.patch   # 补丁文件:源码兼容补丁,解决鸿蒙系统的编译报错、路径兼容、接口兼容等问题,按需添加

2 官方标准模板地址(直接复用)

所有文件的标准模板均由鸿蒙官方维护,直接fork修改即可,无需从零编写:

模板仓库:https://gitcode.com/openharmony-sig/tpc_c_cplusplus/tree/master/lycium/template

3 核心文件详解 & 实战案例(重点)

3.1 HPKBUILD | 鸿蒙化适配的核心核心文件

HPKBUILDShell编写的标准化编译构建脚本,也是C/C++库鸿蒙化的核心,该文件定义了:库的基础元信息、源码下载地址、交叉编译环境配置、编译构建逻辑、打包安装路径、测试准备、环境清理等所有核心流程。
鸿蒙官方提供了标准模板,同时业界已有大量实战案例(如fftw3、tassl),所有适配均基于此模板修改,模板通用,案例可复用

✅ 【官方标准HPKBUILD模板】
# This is an example HPKBUILD file. Use this as a start to creating your own,
# and remove these comments.
# NOTE: Please fill out the license field for your package! If it is unknown,
# then please put 'unknown'.

# Contributor: Your Name <youremail@domain.com>
# Maintainer: Your Name <youremail@domain.com>

pkgname=NAME # 库名,必填
pkgver=VERSION # 库版本,必填
pkgrel=0 # 发布号,固定为0即可
pkgdesc="" # 库功能描述,必填
url="" # 库官网地址,必填
archs=("armeabi-v7a" "arm64-v8a") # 鸿蒙主流CPU架构,固定这两个即可
license=() # 开源协议,必填
depends=() # 运行依赖库,无则留空,依赖库需适配同架构
makedepends=() # 编译依赖工具,无则留空
source="https://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz" # 源码下载链接

downloadpackage=true # 是否自动下载源码包,默认true
autounpack=true # 是否自动解压源码包,默认true
buildtools= # 编译方式,支持cmake/configure/make,必填

builddir= # 源码解压后的目录名
packagename=$builddir.tar.gz # 源码包文件名

# 编译前环境准备:创建目录、设置环境变量、源码预处理
prepare() {
    cd $builddir
    cd ${OLDPWD}
}

# 核心编译逻辑:交叉编译核心步骤,架构判断、编译命令执行
build() {
    cd $builddir
    ${OHOS_SDK}/native/build-tools/cmake/bin/cmake "$@" -DOHOS_ARCH=$ARCH -B$ARCH-build -S./ -L
    make -j4 -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
}
✅ 【实战案例1】fftw3 的HPKBUILD(无依赖纯算法库,configure编译)
# Contributor: 小肉头君 <chenbaodi@huawei.com>
# Maintainer: 小肉头君 <chenbaodi@huawei.com>

pkgname=fftw3
pkgver=3.3.10
pkgrel=0
pkgdesc="FFTW is a C subroutine library for computing the discrete Fourier transform (DFT) in one or more dimensions, of arbitrary input size, and of both real and complex data."
url="http://fftw.org/"
archs=("armeabi-v7a" "arm64-v8a")
license=("GPL-2.0-or-later")
depends=()
makedepends=()
source="http://fftw.org/fftw-${pkgver}.tar.gz"

autounpack=true
downloadpackage=true
buildtools="configure"

builddir=fftw-$pkgver
packagename=$builddir.tar.gz

source envset.sh
host=
optargs=
prepare() {
    mkdir -p $builddir/$ARCH-build
    if [ $ARCH == "armeabi-v7a" ]
    then
        setarm32ENV
        host=arm-linux
    fi
    if [ $ARCH == "arm64-v8a" ]
    then
        setarm64ENV
        host=aarch64-linux
    fi
    optargs="--enable-single --with-slow-timer"
}

build() {
    cd $builddir/$ARCH-build
    PKG_CONFIG_LIBDIR="${pkgconfigpath}" ../configure "$@" $optargs \
        --enable-threads --enable-shared --host=$host > $buildlog 2>&1
    $MAKE VERBOSE=1 >> $buildlog 2>&1
    ret=$?
    cd $OLDPWD
    return $ret
}

package() {
    cd $builddir/$ARCH-build
    $MAKE VERBOSE=1 install >> $buildlog 2>&1
    cd $OLDPWD
    if [ $ARCH == "armeabi-v7a" ];then unsetarm32ENV;fi
    if [ $ARCH == "arm64-v8a" ];then unsetarm64ENV;fi
    unset host optargs
}

check() {
    cd $builddir/$ARCH-build
    sed -i '/.*check-local: bench$(EXEEXT)/c\check-local: #bench$(EXEEXT)' tests/Makefile
    sed -i "s#/usr/bin/sed#sed#g" tests/bench
    sed -i "s#/bin/bash#/data/CIusr/bin/bash#g" tests/Makefile tests/bench
    cd $OLDPWD
    echo "The test must be on an OpenHarmony device!"
}

cleanbuild() {
    rm -rf ${PWD}/$builddir
}
✅ 【实战案例2】tassl 的HPKBUILD(带依赖加密库,configure编译+补丁适配)
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

# Contributor: Jeff Han <hanjinfei@foxmail.com>  ,Tao Han <hantao_ya@163.com> 
# Maintainer: Jeff Han <hanjinfei@foxmail.com>

pkgname=tassl
pkgver=1.1.1
pkgrel=0
pkgdesc="TASSL is an SSL/TLS protocol implementation that supports national secret algorithms"
url="https://github.com/jntass/TASSL-1.1.1"
archs=("armeabi-v7a" "arm64-v8a")
license=("OpenSSL")
depends=(openssl_1_1_1w zlib_1_3_1)
makedepends=()

commitId="a30d107669fdf7d6909b10f1e179de4aaff38ff5"
source="https://github.com/jntass/$pkgname-$pkgver/archive/$commitId.zip"

autounpack=true
downloadpackage=true
buildtools="configure"

builddir=TASSL-${pkgver}-$commitId
packagename=$builddir.zip

source envset.sh
patchflag=true
prepare() {
    if $patchflag
    then
        cd $builddir
        patch -p1 < `pwd`/../tassl_oh_pkg.patch >> $publicbuildlog 2>&1
        patchflag=false
        cd $OLDPWD
    fi
    cp $builddir ${builddir}-${ARCH}-build -rf
	if [ $ARCH == "armeabi-v7a" ];then setarm32ENV;
    elif [ $ARCH == "arm64-v8a" ];then setarm64ENV;
    else echo "${ARCH} not support";return -1;fi
}

build() {
    cd $builddir-$ARCH-build
    ./config "$@" no-asm  > $buildlog 2>&1
    $MAKE >> $buildlog 2>&1
    ret=$?
    cd $OLDPWD
    return $ret
}

package() {
    cd $builddir-$ARCH-build
	mkdir -p ${LYCIUM_ROOT}/usr/${pkgname}/${ARCH}/
    $MAKE install >> $buildlog 2>&1
    cd $OLDPWD
}

check() {
    if [ $ARCH == "armeabi-v7a" ];then unsetarm32ENV;
    elif [ $ARCH == "arm64-v8a" ];then
        cd $builddir-$ARCH-build
        sed -i.bak "s|PERL=/usr/bin/perl|PERL=/data/CIusr/bin/perl|g" ./Makefile
		make test >> $buildlog 2>&1
        cd $OLDPWD
        unsetarm64ENV
    else echo "${ARCH} not support";return -1;fi
    echo "The test must be on an OpenHarmony device!"
}

cleanbuild() {
    rm -rf  $builddir-$ARCH-build $packagename $builddir
}
3.2 HPKCHECK | 标准化测试校验脚本

该文件是鸿蒙化适配的测试标准文件,定义了C/C++库在鸿蒙设备端的测试逻辑,所有库的HPKCHECK结构一致,仅需修改测试命令即可,官方模板如下:

# This is an example HPKCHECK file. Use this as a start to creating your own,
# and remove these comments.

# 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
}

# 鸿蒙设备端核心测试接口,所有测试逻辑写在这里
openharmonycheck() {
    res=0                               
    cd ${builddir}/${ARCH}-build        
    ctest > ${logfile} 2>&1             # 测试命令,按需修改为make test/ctest等
    res=$?                              
    cd $OLDPWD                          

    return $res                         
}
3.3 其他4个文件 | 标准化无定制成本
  • README.OpenSource:固定格式,填写库名、版本、开源协议、源码地址即可;
  • README_zh.md:填写编译步骤、适配说明、使用方式,无固定格式;
  • SHA512SUM:可选,无需校验则不创建,需要则生成源码包的sha512哈希值即可;
  • xxx_oh_pkg.patch:按需创建,解决鸿蒙编译的兼容性问题,比如路径适配、接口兼容、编译报错等,补丁文件通过patch -p1命令在prepare阶段执行。

4 C/C++库鸿蒙化的核心编译逻辑

所有C/C++库的编译均基于 鸿蒙交叉编译环境,核心要点如下,也是HPKBUILD中最核心的逻辑:

  1. 架构支持:固定适配 armeabi-v7a(arm32)arm64-v8a(arm64) 两大主流架构;
  2. 环境配置:通过 source envset.sh 导入鸿蒙交叉编译环境变量,通过 setarm32ENV/setarm64ENV 设置对应架构的编译环境;
  3. 编译方式:支持 configure/make/cmake 三种主流C/C++编译方式,官方均做了兼容;
  4. 编译产物:最终编译产物会安装到 ${LYCIUM_ROOT}/usr/${pkgname}/${ARCH}/ 目录,鸿蒙系统可直接调用;
  5. 测试要求:所有C/C++库的测试均需在鸿蒙真机设备上执行,模拟器暂不支持完整测试。

结尾

生态共建,万物互联,鸿蒙可期。

Logo

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

更多推荐