Ubuntu 22.04 LTS 🐧
Ubuntu是最热门的Linux发行版之一,是一款开放源代码的免费软件,其易用性和稳定性均非常出色,并且拥有非常强大成熟的社区资源。可以选择云主机、虚拟机等多种方式。
📋 C/C++三方库鸿蒙化共建流程

🔧lycium交叉编译框架
lycium是一款协助开发者通过shell语言实现C/C++三方库快速交叉编译,并在OpenHarmony系统上快速验证的编译框架工具。开发者只需要设置对应C/C++三方库的编译方式以及编译参数,通过lycium就能快速的构建出能在OpenHarmony系统运行的二进制文件。
打开终端,执行以下命令克隆lycium工程。
⚠️ 注意:此处lycium存储路径(即交叉编译路径)建议与后续测试路径保持一致。
📍 也就是,如果交叉编译路径为home/openharmony/tpc_c_cplusplus/thirdparty/xxx,使用hdc向ohos设备推送交叉编译产物压缩包时应该也是home/openharmony/tpc_c_cplusplus/thirdparty。
mkdir openharmony
cd openharmony
git clone https://atomgit.com/openharmony-sig/tpc_c_cplusplus.git

📁lycium目录结构

编译环境配置 ⚙️
检查编译环境 🔍
打开终端执行git clone https://atomgit.com/oh-tpc/oh-scripts.git克隆交叉编译环境配置脚本工程[1],在oh-scripts/linux目录下执行python3 check_env.py检查编译环境是否包含以下几个基本编译命令: gcc、cmake、make、pkg-config、autoconf、autoreconf、 automake。
# 克隆交叉编译环境配置脚本工程
git clone https://atomgit.com/oh-tpc/oh-scripts.git
💡 若提示git command not fount,则执行sudo apt-get install git git-lfs安装后再执行克隆命令。

# 克隆完成后,在oh-scripts/linux目录下执行命令检查编译环境是否包含基本编译命令
cd oh-scripts/linux
python3 check_env.py


💡 若提示存在未安装的基本编译命令工具链,则需要执行python3 check_env.py -i或者python3 check_env.py --install完成缺失命令安装后,会再次执行检查。





✅ 至此,表示OpenHarmony SDK交叉编译需要的基本编译命令全部安装完成。
📥下载OpenHarmony SDK
📌 可以从OpenHarmony SDK 官方发布渠道[2]文档中下载,也可以从每日构建[3]中下载,二者区别在于后者可以下载FULL版本SDK(比PUBLIC版本在ets层提供了更多的API),前者只能下载PUBLIC版本的SDK。当然这两个版本的SDK中关于c/c++编译的部分是相同的,因此选择其中的一个下载方式即可。
SDK链接获取方式 🔗
方式一:OpenHarmony SDK官方发布渠道获取链接地址
📌 打开OpenHarmony SDK 官方发布渠道[4]选择最新版本,点击进入版本说明文档中。

📌 在右侧【目录】中点击"从镜像站点获取",鼠标右击"标准系统Public SDK包(WIndows/Linux)"行后站点,选择复制链接地址。

方式二:从每日构建中获取链接地址
📌 打开每日构建[5]网页,在项目栏选择"openharmony",在分支栏选择当前最新版本"OpenHarmony-6.0.0-Release",选择日期或者时间节点按钮,切换每日构建或者滚动构建,找到ohos-sdk-full或者ohos-sdk-pub lic行,点击行后“下载链接”,右键选择“下载链接”选择复制链接地址。

🚀 执行下载脚本
📥 我们为开发者提供了一键下载和自动解压OpenHarmony SDK文件,脚本默认提供第一种方式的SDK链接地址,开发者也可以在执行命令后,根据提示输入获取的SDK链接地址。在oh-scripts/linux目录下执行python3 download_ohsdk.py命令下载OpenHarmony SDK。
# 进入oh-scripts/linux目录
cd ~/oh-scripts/linux
python3 download_ohsdk.py



📌 因为我们后续使用lycium工具进行三方库适配工作,而lycium支持的是C/C++三方库的交叉编译,SDK工具链只涉及到native目录下的工具,因此需要将OHOS_SDK的路径需配置成native工具的父目录。在使用下载脚本会自动将export OHOS_SDK="/home/ubuntu/openharmony/ohos-sdk/linux"写入环境变量中,执行cat ~/.bashrc查看是否已写入。
cat ~/.bashrc

⚠️ 若自动写入失败,则需要执行vim ~/.bashrc手动配置环境变量。
✅ 完成后,还需要执行source ~/.bashrc使配置的环境变量生效。
📂 native目录介绍
执行cd ~/openharmony/ohos-sdk/linux/native进入到native目录,执行tree -L 2查看各级文件是否完整。

- • 📁
build:构建时cmake依赖的配置文件 - • 🔧
build-tools:构建工具包含cmake和ninja - • 📂
sysroot:编译器的sysroot目录,SDK内部已经包含的库和对应的文件 - • 📋
oh-uni-package.json:SDK信息描述,如版本 - • 📌
NOTICE.txt:为注意事项,内容多为SDK的详细描述 - • 🔑
ndk_system_capability.json:记录SDK提供的能力 - • 🔗
nativeapi_syscap_config.json:记录SDK提供的能力对应的头文件
🔄 C/C++三方库鸿蒙化快速交叉编译流程

📝 修改三方库的编译方式以及编译参数
📄 编译配置模板文件HPKBUILD
lycium框架为开发者提供了对C/C++目标三方库的编译配置模板文件HPKBUILD[6],工程编译脚本模板如下:
# 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 # 发布号
pkgdesc="" # 库描述
url="" # 官网链接
archs=("armeabi-v7a" "arm64-v8a") # cpu 架构
license=()
depends=() # 依赖库的目录名 必须保证被依赖的库的archs是当前库的archs的超集
makedepends=() # 构建库时的依赖工具->需要用户安装的工具
source="https://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz" # 库源码下载链接
downloadpackage=true # 是否自动下载压缩包,如若不写默认 true. (应对一些特殊情况,代码只能 git clone (项目中依赖 submoudle ))
autounpack=true # 是否自动解压,如若不写默认 true, 如果为 false 则需要用户在 prepare 函数中自行解压
buildtools= # 编译方法, 暂时支持cmake, configure, make等, 是什么就填写什么. 如若不写默认为cmake.
builddir= # 源码压缩包解压后目录名 编译目录名
packagename=$builddir.tar.gz # 压缩包名
# 为编译设置环境,如设置环境变量,创建编译目录等
prepare() {
cd $builddir
cd ${OLDPWD}
}
# ${OHOS_SDK} oh sdk安装路径
# $ARCH 编译的架构是 archs 的遍历
# $LYCIUM_ROOT/usr/$pkgname/$ARCH 安装到顶层目录的usr/$pkgname/$ARCH
# 执行编译构建的命令
build() {
# 如果是cmake构建 "$@"=-DCMAKE_FIND_ROOT_PATH="..." -DCMAKE_TOOLCHAIN_FILE="..." -DCMAKE_INSTALL_PREFIX="..." 依赖库的搜索路径,toolchain file 路径,安装路径
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 #${PWD}/$packagename
}
📌 每个C/C++目标三方库都需要提供该交叉编译配置文件,都需要按照规则填写必要的变量值(目标库信息)以及编译构建生命周期函数。

- • 🔧 **
prepare函数:**编译前准备工作,主要包含: - • 创建编译目录(推荐根据不同架构创建不同编译目录,即使用模板默认方式即可)
- • 设置环境变量(根据不同的编译构建方式进行设置)
- • 下载源码(downloadpackage=false,推荐使用框架下载)
- • 解压源码包(下载的是源码包且autounpack=false,推荐使用框架解压)
- • 对于编译时需要做特殊修改(如编译时需要对编译脚本进行打patch操作等)
- • 🔨 **
build函数:**三方库的编译构建函数,makefile生成以及执行make指令。该函数需要根据原生库的构建方式进行配置,不同编译构建基本模板如下:build() {
cd $builddir ## 进入到编译目录
${OHOS_SDK}/native/build-tools/cmake/bin/cmake $* -DOHOS_ARCH=$ARCH -B$ARCH-build -S./ -L ## 执行cmake,配置相应的变量并生成Makefile文件
make -j4 -C $ARCH-build ## 执行make指令,生成对应的库文件以及可执行用例
ret=$? ## 记录make执行的返回值
cd $OLDPWD ## 返回进入编译目录前的路径
return $ret ## 返回make的返回值
}
变量说明:
build() {
cd $builddir/$ARCH-build
../configure $*>> `pwd`/build.log 2>&1 ## 执行configure,配置相应的变量并生成Makefile文件
make -j4 >> `pwd`/build.log 2>&1
ret=$?
cd $OLDPWD
return $ret
}
变量说明:
make CC=${cc} AR=${ar} RANLIB=${ranlib} -j4 >> `pwd`/build.log 2>&1
变量说明:
- 1. 其中
CC,AR,RANLIB等变量根据原生库Makefile文件中变量来设定,其值可在prepare函数中设定。
- 2. 其他特殊设置需要根据库自身情况在
configure后面进行添加
- 1. 其中
OHOS_SDK是ohos sdk的安装路径,在下载OpenHarmony SDK小结通过我们提供的脚本文件完成SDK下载及环境变量配置[7],需要在执行编译前完成设置。 - 2.
$*代表的参数:-DCMAKE_FIND_ROOT_PATH="..." -DCMAKE_TOOLCHAIN_FILE="..." -DCMAKE_INSTALL_PREFIX="..." 依赖库的搜索路径,toolchain file 路径,安装路径 - 6. 其他特殊设置需要根据自身情况在
cmake后面进行添加
- • 📦 **
package函数:**三方库打包函数,该函数只需要在编译目录直接执行make install即可。对于不支持make install的三方库,需要在该函数中手动安装三方库文件以及头文件等(将对应文件通过cp命令拷贝到对应的安装路径下面)。 - • ✔️ **
check函数:**该函数实现了测试准备以及测试说明。对于在目标机器上测试需要生成的测试用例或对于测试需要做修改的,可以在该接口中实现,并需要在该函数中说明在目标机器上运行测试的方法 。真正的测试需要在目标机器上进行。 - • 🧹 **
cleanbuild函数:**该函数主要清理当前库的编译环境。
📚 三种编译方式
以cJSON为例掌握cmake方式编译配置文件HPKBUILD
📌 为了便于理解,我将~/openharmony/tpc_c_cplusplus/thirdparty目录下的cJSON删除。重新在~/openharmony/tpc_c_cplusplus/thirdparty目录下新建目标三方库cJSON目录。
cd ~/openharmony/tpc_c_cplusplus/thirdparty
rm -rf cJSON
mkdir cJSON

✏️ 使用VSCode打开tpc_c_cplusplus项目,在thirdparty/cJSON目录创建HPKBUILD文件,按照编译配置模板编写cJSON编译配置文件。
pkgname=cJSON # 三方库名称(必填)
pkgver=v1.7.19 # 三方库版本(必填)
pkgrel=0
pkgdesc=""
url="https://github.com/DaveGamble/cJSON" # 官方链接(可选)
archs=("armeabi-v7a" "arm64-v8a") # CPU架构,默认即可
license=("MIT")
depends=()
makedepends=()
source="https://github.com/DaveGamble/$pkgname/archive/refs/tags/$pkgver.tar.gz" # 库源码下载链接
autounpack=true # 是否自动下载压缩包,如若不写默认 true. (应对一些特殊情况,代码只能 git clone (项目中依赖 submoudle ))
downloadpackage=true # 是否自动解压,如若不写默认 true, 如果为 false 则需要用户在 prepare 函数中自行解压
buildtools="cmake" # 编译方法, 暂时支持cmake, configure, make等, 是什么就填写什么. 如若不写默认为cmake.
builddir=$pkgname-${pkgver:1} # 源码压缩包解压后目录名 编译目录名
packagename=$builddir.tar.gz # 压缩包名
# 为编译设置环境,如设置环境变量,创建编译目录等
prepare() {
mkdir -p $builddir/$ARCH-build
}
build() {
cd $builddir
${OHOS_SDK}/native/build-tools/cmake/bin/cmake "$@" \
-DOHOS_ARCH=$ARCH -B$ARCH-build -S./ -L > $buildlog 2>&1
make -j4 -C $ARCH-build >> `pwd`/$ARCH-build/build.log 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!"
}
# 清理环境
cleanbuild(){
rm -rf ${PWD}/$builddir #${PWD}/$packagename
}
以bzip2为例掌握make方式编译配置文件HPKBUILD
✏️ 使用VSCode打开tpc_c_cplusplus项目,在thirdparty/bzip2目录创建HPKBUILD文件,按照编译配置模板编写bzip2编译配置文件。
pkgname=bzip2
pkgver=1_0_6
pkgrel=0
pkgdesc=""
url=""
archs=("armeabi-v7a" "arm64-v8a" "x86_64")
license=("public domain" "LGPLv2.1" "GPLv2" "GPLv3")
depends=()
makedepends=()
# 官方下载地址https://sourceforge.net/projects/$pkgname/files/$pkgname-$pkgver.tar.gz受网络影响可能存在下载失败的情况,现使用gitee镜像可以与官方仓库保持同步
source="https://gitee.com/lycium_pkg_mirror/$pkgname/repository/archive/$pkgname-$pkgver.zip"
autounpack=true
downloadpackage=true
buildtools="make"
builddir=$pkgname-$pkgname-${pkgver}
packagename=$builddir.zip
cc=
ar=
ranlib=
# bzip2 采用makefile编译构建,为了保留构建环境(方便测试)。因此同一份源码在解压后分为两份,各自编译互不干扰
prepare() {
cp -rf $builddir $builddir-$ARCH-build
cd $builddir-$ARCH-build
if [ $ARCH == "armeabi-v7a" ]
then
cc=${OHOS_SDK}/native/llvm/bin/arm-linux-ohos-clang
ar=${OHOS_SDK}/native/llvm/bin/llvm-ar
ranlib=${OHOS_SDK}/native/llvm/bin/llvm-ranlib
fi
if [ $ARCH == "arm64-v8a" ]
then
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
fi
if [ $ARCH == "x86_64" ]
then
cc=${OHOS_SDK}/native/llvm/bin/x86_64-linux-ohos-clang
ar=${OHOS_SDK}/native/llvm/bin/llvm-ar
ranlib=${OHOS_SDK}/native/llvm/bin/llvm-ranlib
fi
cd $OLDPWD # 1> /dev/null
}
build() {
cd $builddir-$ARCH-build
$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
unset cc ar ranlib
}
check() {
echo "The test must be on an OpenHarmony device!"
# make check
}
# 清理环境
cleanbuild(){
rm -rf ${PWD}/$builddir $builddir-armeabi-v7a-build $builddir-arm64-v8a-build $builddir-x86_64-build #${PWD}/$packagename
}
以libuuid为例掌握configure方式编译配置文件HPKBUILD
✏️ 使用VSCode打开tpc_c_cplusplus项目,在thirdparty/libuuid目录创建HPKBUILD文件,按照编译配置模板编写libuuid编译配置文件。
pkgname=libuuid
pkgver=1.0.3
pkgrel=0
pkgdesc="The libuuid library is used to generate unique identifiers for objects that may be accessible beyond the local system. "
url="https://sourceforge.net/projects/libuuid/"
archs=("armeabi-v7a" "arm64-v8a")
license=("BSD")
depends=()
makedepends=()
source="https://sourceforge.net/projects/$pkgname/files/$pkgname-$pkgver.tar.gz"
autounpack=true
downloadpackage=true
buildtools="configure"
builddir=$pkgname-${pkgver}
packagename=$builddir.tar.gz
source envset.sh
host=
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
}
build() {
cd $builddir/$ARCH-build
PKG_CONFIG_LIBDIR="${pkgconfigpath}" \
../configure "$@" --host=$host > $buildlog 2>&1
$MAKE VERBOSE=1 >> $buildlog 2>&1
ret=$?
cd $OLDPWD
return $ret
}
package() {
cd $builddir/$ARCH-build
$MAKE install >> $buildlog 2>&1
cd $OLDPWD
unset host
}
check() {
cd $builddir/$ARCH-build
$MAKE check >> $buildlog 2>&1
cd $OLDPWD
if [ $ARCH == "armeabi-v7a" ]
then
unsetarm32ENV
fi
if [ $ARCH == "arm64-v8a" ]
then
unsetarm64ENV
fi
echo "The test must be on an OpenHarmony device!"
# real test CMD
# ./test_uuid
}
# 清理环境
cleanbuild(){
rm -rf ${PWD}/$builddir #${PWD}/$packagename
}
⚡ 快速编译三方库(以cJSON为例)
📌 配置完三方库的编译方式参数后,在~/openharmony/tpc_c_cplusplus/lycium目录执行./build.sh pkgname,进行自动编译三方库,并打包安装到当前目录的usr/$pkgname/$ARCH目录。

💡 pkgname为目标三方库名称,如cJSON,ARCH为当前系统架构名称。
cd ~/openharmony/tpc_c_cplusplus/lycium
./build.sh cJSON
⚠️ 注意:
./build.sh # 默认编译 thirdparty 目录下的多有库
./build.sh aaa bbb ccc ... # 编译 thirdparty 目录下指定的 aaa bbb ccc ...库 当 aaa 库存在依赖时,必须保证入参中包含依赖,否则 aaa 库不会编译

✅ 构建完成后,会在cJSON目录下生成交叉编译源码、压缩包以及构建日志。

📂 在lycium/usr目录生成cJSON编译构建产物。

🎉 至此,完成了从零到一的C/C++快速交叉编译构建工作。
引用链接
[1] 交叉编译环境配置脚本工程:https://atomgit.com/oh-tpc/oh-scripts
[2]OpenHarmony SDK 官方发布渠道:https://atomgit.com/openharmony/docs/blob/master/zh-cn/release-notes/Readme.md
[3]每日构建:https://ci.openharmony.cn/workbench/cicd/dailybuild/dailylist
[4]HPKBUILD:https://atomgit.com/openharmony-sig/tpc_c_cplusplus/blob/master/lycium/template/HPKBUILD