欢迎加入 开源鸿蒙跨平台社区,与开发者一起共建鸿蒙三方库的开源生态。
一、背景与目标
cppDES 是 GitHub 上的 C++ 实现 Data Encryption Standard(DES/3DES) 开源库,支持 ECB、CBC 模式,采用 CMake 构建,并自带 Google Test 测试。本文记录在 OpenHarmony 三方库共建仓库(tpc_c_cplusplus) 中,使用 lycium 交叉编译框架 将 cppDES 接入、编译、打包并在设备上运行测试的完整过程,以及遇到的问题与解决方案。
目标:
- 在 Mac/Linux 宿主机上交叉编译出适用于 OpenHarmony(armeabi-v7a / arm64-v8a)的静态库与测试可执行文件;
- 产物可被其他 Native/应用工程链接使用;
- 测试可在开发板上通过
test.sh或直接运行cppDESTest执行。

二、环境与框架简介
环境搭建 更详细的步骤(SDK 下载、环境变量、依赖工具安装等)可参考:OpenHarmony 交叉编译环境配置。下文仅列出与本文直接相关的要点。
2.1 编译环境搭建
- 宿主机:建议使用 Mac(Darwin)或 Linux。lycium 在 Windows(如 CYGWIN)上部分检查会关闭,推荐在 Linux 或 Mac 上完成编译与测试。
- 基本工具 :需提前安装以下命令,供下载、配置与构建使用:
- 必选:
gcc、g++、cmake、make、pkg-config、wget(或curl) - 若库使用 autotools:
autoconf、autoreconf、automake - 其他:
patch、unzip、tar、git、ninja等(按需) - 示例(Ubuntu):
sudo apt install cmake make gcc g++ pkg-config wget
- 必选:
- OHOS SDK :
-
从 OpenHarmony 官网或 DevEco Studio 配套渠道下载 Native 相关 SDK (需包含
native/llvm、native/build-tools/cmake、native/build/cmake/ohos.toolchain.cmake等)。 -
环境变量需指向 native 的父目录 (即 SDK 根目录),而非
native本身,例如:bashexport OHOS_SDK=/path/to/OpenHarmony/Sdk/20 -
编译前在终端执行
echo $OHOS_SDK确认已配置;未配置时build.sh会提示并退出。
-
- lycium 工具链 :首次执行
build.sh时,若检测到 SDK 中缺少*-linux-ohos-clang等交叉编译器,会从lycium/Buildtools/toolchain.tar.gz解压并拷贝到$OHOS_SDK/native/llvm/bin,无需单独安装。 - lycium 目录角色 :
build.sh负责按依赖顺序调度各三方库的编译;每个库的"下载 → 解压 → 配置 → 编译 → 安装"由该库目录下的 HPKBUILD 定义,产物统一落在lycium/usr/<pkgname>/<ARCH>/。
【此处可配图:终端中执行 echo $OHOS_SDK 与 ls $OHOS_SDK/native/llvm/bin 的截图,体现 SDK 路径与工具链存在。】
2.2 cppDES 上游特点
- 源码 :GitHub 无 release tag,使用分支归档地址
https://github.com/fffaraz/cppDES/archive/refs/heads/master.tar.gz,解压后目录名为cppDES-master。 - 构建 :CMake,包含:
- 静态库目标
libcppdes; - 命令行工具
cppDES; - 测试可执行文件
cppDESTest(依赖 FetchContent 拉取 googletest)。
- 静态库目标
- 安装 :上游 CMakeLists.txt 未提供 install() ,需在 lycium 的
package()中手动拷贝库与头文件。
【此处可配图:lycium 目录结构(build.sh、script/、template/、thirdparty/ 等)或 tpc_c_cplusplus 仓库结构概览。】
2.3 HPKBUILD、HPKCHECK 与 patch 简介
lycium 通过若干约定文件驱动"下载 → 解压 → 配置 → 编译 → 安装 → 设备测试",下面用通用结构说明三个部分,具体到 cppDES 的配置与完整代码在第三节「接入步骤」中展开。
HPKBUILD(构建描述)
- 是什么 :每个三方库目录下的 HPKBUILD 是一个可被
source的 shell 脚本,定义包元信息与若干函数 (prepare、build、package、cleanbuild 等)。build.sh 会先source HPKBUILD再按流程调用这些函数。 - 重点字段:pkgname / pkgver、source、builddir / packagename、archs、buildtools、depends(依赖的其他库 pkgname)。
- 重点函数:prepare()(打补丁/改构建脚本)、build()(cmake + make)、package()(拷贝到 usr)、cleanbuild()(清理)。
通用结构示例(以 cmake 为例):
bash
pkgname=NAME
pkgver=VERSION
source="https://example.com/xxx.tar.gz"
builddir=xxx-${pkgver}
packagename=$builddir.tar.gz
archs=("armeabi-v7a" "arm64-v8a")
buildtools="cmake"
depends=()
prepare() {
cd $builddir
# 可选:patch -p0 < ../xxx.patch 或 sed/awk 修改构建脚本
mkdir -p $ARCH-build
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 # 上游有 install 时;无则需手动 cp 到 $LYCIUM_ROOT/usr/$pkgname/$ARCH/
cd $OLDPWD
}
cleanbuild() {
rm -rf ${PWD}/$builddir
}
HPKCHECK(设备侧测试)
- 是什么 :同一三方库目录下的 HPKCHECK 也是可被
source的 shell 脚本,供设备上的 test.sh 调用,用于定义"如何在开发板上跑该库的测试"。 - 重点 :openharmonycheck() 内进入构建目录、执行测试二进制并以退出码返回;logfile 用于保存测试日志;设备上建议直接运行可执行文件,不依赖 ctest(避免宿主机路径写死)。
通用结构示例:
bash
source HPKBUILD > /dev/null 2>&1
logfile=${LYCIUM_THIRDPARTY_ROOT}/${pkgname}/${pkgname}_${ARCH}_${OHOS_SDK_VER}_test.log
checkprepare() { return 0; }
openharmonycheck() {
res=0
cd ${builddir}/${ARCH}-build
[ -f ./测试可执行文件 ] && ./测试可执行文件 >> ${logfile} 2>&1 && res=$? || res=1
cd $OLDPWD
return $res
}
patch(补丁)
- 是什么 :对上游源码或构建脚本的差分修改 ,以"补丁文件"形式保存,在 prepare() 中通过
patch -p0 < ../xxx.patch应用。 - 重点 :移植原则为不直接改 C/C++ 源码;若必须改构建脚本,用 patch 或 sed/awk 在 prepare 中施加。格式多为 unified diff,
-p0/-p1表示路径剥离级数。
unified diff 格式示例:
diff
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -32,5 +32,8 @@
include(GoogleTest)
-gtest_discover_tests(cppDESTest)
+if(NOT CMAKE_CROSSCOMPILING)
+ gtest_discover_tests(cppDESTest)
+endif()
三、接入步骤
3.1 创建三方库目录与模板文件
在 Workspace/tpc_c_cplusplus/thirdparty/ 下新建目录 cppDES ,并从 lycium 的 template 拷贝并改写以下文件:
| 文件 | 作用 |
|---|---|
| HPKBUILD | 定义包名、版本、源码地址、构建方式(cmake)、prepare/build/package/cleanbuild 等 |
| HPKCHECK | 定义在设备上如何执行测试(如运行 ./cppDESTest) |
| README.OpenSource | 开源协议、版权、源码来源(必填) |
| README_zh.md | 中文说明:适配说明、编译步骤、使用方式、注意事项 |
【此处可配图:thirdparty/cppDES 目录下的文件列表(HPKBUILD、HPKCHECK、README.OpenSource、README_zh.md、patch 等)。】
3.2 cppDES 的 HPKBUILD / HPKCHECK 配置要点
在 2.3 的通用结构基础上,cppDES 的取值与差异如下。
| 项 | cppDES 取值 / 说明 |
|---|---|
| pkgname | cppDES |
| pkgver | master(上游无 tag,用分支) |
| source | https://github.com/fffaraz/cppDES/archive/refs/heads/master.tar.gz |
| builddir | cppDES-master |
| buildtools | cmake |
| archs | armeabi-v7a、arm64-v8a |
| depends | 无 |
- prepare() :除
mkdir -p $ARCH-build外,需修改上游 CMakeLists.txt ,在交叉编译时跳过gtest_discover_tests(原因见下文「问题二」)。当前用 awk 做一次性替换,等价 patch 见0001-skip-gtest-discover-when-cross-compiling.patch。 - build() :全量
make -C $ARCH-build(不单编 libcppdes),以生成测试可执行文件 cppDESTest,供设备侧使用。 - package() :上游无 install,需手动 拷贝
liblibcppdes.a与include/cppdes/到$LYCIUM_ROOT/usr/cppDES/$ARCH/。
prepare() 中修改 CMakeLists 的写法(awk 实现):
bash
awk '/^gtest_discover_tests\(cppDESTest\)$/{print "if(NOT CMAKE_CROSSCOMPILING)"; print " gtest_discover_tests(cppDESTest)"; print "endif()"; next}1' CMakeLists.txt > CMakeLists.txt.tmp && mv CMakeLists.txt.tmp CMakeLists.txt
package() 中手动安装库与头文件的写法:
bash
mkdir -p $LYCIUM_ROOT/usr/$pkgname/$ARCH/lib $LYCIUM_ROOT/usr/$pkgname/$ARCH/include
[ -f $ARCH-build/liblibcppdes.a ] && cp -f $ARCH-build/liblibcppdes.a $LYCIUM_ROOT/usr/$pkgname/$ARCH/lib/
cp -r include/cppdes $LYCIUM_ROOT/usr/$pkgname/$ARCH/include/
HPKCHECK :设备上进入 cppDES-master/$ARCH-build 后执行 ./cppDESTest,退出码作为测试结果;完整脚本见仓库 thirdparty/cppDES/HPKBUILD 与 HPKCHECK。
3.3 交叉编译时跳过 gtest_discover_tests(prepare 中的修改)
上游 CMake 中有:
cmake
include(GoogleTest)
gtest_discover_tests(cppDESTest)
gtest_discover_tests 会在构建阶段 在宿主机 上执行刚编好的 cppDESTest 以发现测试用例。而 cppDESTest 是为 arm-linux-ohos 编译的,在 Mac/Linux 上无法运行,会报 "cannot execute binary file" 并导致构建失败。因此必须在 prepare() 里对 CMakeLists.txt 做最小修改,在交叉编译时跳过该步骤(见下文"问题二")。当前实现使用 awk 将上述一行替换为:
cmake
if(NOT CMAKE_CROSSCOMPILING)
gtest_discover_tests(cppDESTest)
endif()
这样在 OHOS toolchain 设置 CMAKE_CROSSCOMPILING=ON 时不会执行测试发现,但 cppDESTest 仍会正常编出,供设备端使用。
3.4 HPKCHECK 设备侧测试
- test.sh 会
cd到thirdparty/cppDES,再 source HPKCHECK,因此 openharmonycheck() 中进入${builddir}/${ARCH}-build(即cppDES-master/armeabi-v7a-build或arm64-v8a-build),若存在./cppDESTest则直接执行并以其退出码作为测试结果,不再使用 ctest(避免设备上与宿主机路径不一致导致的 CTest 配置问题)。
四、编译流程与命令
-
进入 lycium 目录:
bashcd /path/to/tpc_c_cplusplus/lycium -
执行编译(仅编译 cppDES):
bash./build.sh cppDES -
脚本将依次:检查 OHOS_SDK、解压/使用已有 cppDES-master.tar.gz、对每个 ARCH 执行 prepare → cmake 配置 → make → package,并写入
lycium/usr/hpk_build.csv。 -
产物位置:
- 静态库与头文件:
lycium/usr/cppDES/armeabi-v7a/、lycium/usr/cppDES/arm64-v8a/(lib、include)。 - 测试可执行文件:保留在
thirdparty/cppDES/cppDES-master/armeabi-v7a-build/cppDESTest与arm64-v8a-build/cppDESTest,需随测试资源一起拷贝到设备。
- 静态库与头文件:
【此处可配图:终端中执行 ./build.sh cppDES 后"Compileing OpenHarmony armeabi-v7a/arm64-v8a ...""Build cppDES master end!""ALL JOBS DONE!!!" 的完整输出截图。】
【此处可配图:lycium/usr/cppDES/ 下 armeabi-v7a、arm64-v8a 的 lib 与 include 目录结构(含 liblibcppdes.a、cppdes/*.h)。】
五、遇到的问题与解决方案
问题一:HPKBUILD 在 source 时报错 "command not found" / "syntax error"
现象 :执行 ./build.sh cppDES 时出现多行 "line N: : command not found" 以及 "syntax error near unexpected token {"(如 prepare() 附近),导致 cleanbuild 等未定义。
原因 :HPKBUILD 文件使用了 Windows 换行符(CRLF,\r\n) 。在 bash 中,行尾的 \r 会导致该行被错误解析(例如注释行被当成续行或命令),从而触发上述报错。
解决 :将 HPKBUILD(以及 HPKCHECK、README 等)统一为 Unix 换行(LF)。例如在 Mac 上:
bash
tr -d '\r' < thirdparty/cppDES/HPKBUILD > thirdparty/cppDES/HPKBUILD.tmp && mv thirdparty/cppDES/HPKBUILD.tmp thirdparty/cppDES/HPKBUILD
问题二:make 阶段报错 "cannot execute binary file" / GoogleTestAddTests.cmake Error
现象:cmake 配置成功,libcppdes、googletest、cppDESTest 的编译与链接也成功,但在生成 cppDESTest 之后出现类似:
text
/Users/.../cppDES-master/armeabi-v7a-build/cppDESTest: cannot execute binary file
CMake Error at .../GoogleTestAddTests.cmake:112 (message):
Error running test executable. Path: '.../cppDESTest' Result: 126
随后 make 报错并删除已生成的 cppDESTest。
原因 :gtest_discover_tests(cppDESTest) 会在构建时 在宿主机 上运行 cppDESTest 以发现测试。而该可执行文件是为 arm-linux-ohos 编译的,在 x86 Mac/Linux 上无法运行,因此系统返回 "cannot execute binary file"(退出码 126)。
解决 :在 prepare() 中修改上游 CMakeLists.txt,将:
cmake
gtest_discover_tests(cppDESTest)
改为:
cmake
if(NOT CMAKE_CROSSCOMPILING)
gtest_discover_tests(cppDESTest)
endif()
实现方式采用 awk 在解压后的 cppDES-master/CMakeLists.txt 上做一次性替换(见 HPKBUILD 中 prepare 段),无需改 C/C++ 源码,符合"构建脚本最小改动"的移植原则。修改后交叉编译时不再执行测试发现,但 cppDESTest 仍会正常生成,供设备端运行。
问题三:设备上 ctest 报 "No test configuration file found!"
现象 :将 thirdparty/cppDES 拷贝到设备后,进入 cppDES-master 目录执行 ctest,提示 "No test configuration file found!"。
原因 :CTest 的配置文件(如 CTestTestfile.cmake)是 CMake 在构建目录 中生成的,位于 cppDES-master/armeabi-v7a-build 或 arm64-v8a-build,而不是源码根目录 cppDES-master。在源码根目录执行 ctest 时找不到这些文件。
解决 :在设备上先进入对应架构的构建目录再执行 ctest,例如:
bash
cd cppDES-master/armeabi-v7a-build
ctest --output-on-failure
或直接运行测试可执行文件(推荐):
bash
cd cppDES-master/armeabi-v7a-build
./cppDESTest
HPKCHECK 已采用"直接运行 ./cppDESTest"的方式,避免依赖 ctest 与 CTest 配置文件。
【此处可配图:在错误目录执行 ctest 报 "No test configuration file found!" 的终端截图。】
问题四:设备上 ctest 报 "include could not find requested file" 或路径为本机路径
现象 :在设备上进入 armeabi-v7a-build 后执行 ctest,报错类似:
text
CMake Error at CTestTestfile.cmake:7 (include):
include could not find requested file:
/Users/lijiajun/.../thirdparty/cppDES/cppDES-master/armeabi-v7a-build/cppDESTest[1]_include.cmake
原因 :CTest 的测试列表是在宿主机 上生成的,其中的路径是宿主机绝对路径 。把构建目录拷贝到设备后,设备上并不存在该路径,因此 include 失败。这不是"缺动态库",而是路径不一致问题。
解决 :不在设备上依赖 ctest 的"发现 + include"机制,改为在 HPKCHECK 中直接执行 ./cppDESTest,用其退出码作为测试结果。这样既不依赖 CTest 配置文件中的宿主机路径,也无需在设备上做路径替换。

问题五:设备上 ctest 显示 "cppDESTest_NOT_BUILT" / "Could not find executable"
现象:设备上能进入构建目录并执行 ctest,但测试项显示为 "cppDESTest_NOT_BUILT",或 "Could not find executable cppDESTest_NOT_BUILT"。
原因 :若在 HPKBUILD 的 build() 中只编了 libcppdes (例如 make -C $ARCH-build libcppdes),则 cppDESTest 可执行文件根本没有被编译。CMake 仍会为该目标注册一条 CTest 测试,但可执行文件不存在,故标记为 NOT_BUILT。
解决 :在 build() 中做全量 make (不限定目标),即 make -C $ARCH-build,这样会同时编出 libcppdes 与 cppDESTest(并拉取、编译 googletest)。再结合"问题二"的 gtest_discover_tests 跳过逻辑,即可在宿主机上完整构建,并在设备上得到可用的 cppDESTest。

六、设备侧测试简要步骤
-
将 thirdparty(或至少 thirdparty/cppDES,含 cppDES-master 及两个架构的 *-build 目录)按 lycium 文档打包为测试资源,部署到开发板,并保证设备上的目录层级与编译机一致。
-
在设备上进入 lycium 根目录后执行:
bash./test.sh cppDES脚本会根据 CPU 架构进入对应
cppDES-master/<ARCH>-build并执行./cppDESTest,结果写入日志并汇总到 check_result。 -
或手动进入对应构建目录执行:
bashcd /path/to/thirdparty/cppDES/cppDES-master/arm64-v8a-build # 按实际架构选择 ./cppDESTest


七、总结
- cppDES 在 OpenHarmony 上的交叉编译依赖 lycium 的 HPKBUILD/HPKCHECK 机制,通过指定源码地址、builddir、buildtools=cmake,并在 prepare 中对 CMakeLists 做最小修改(跳过交叉编译时的 gtest_discover_tests),即可在宿主机完成全量构建并得到静态库与测试可执行文件。
- 典型问题:HPKBUILD 的 CRLF 导致脚本解析错误;gtest_discover_tests 在宿主机运行目标机二进制导致 "cannot execute binary file";设备上 CTest 路径与"无 cppDESTest 可执行文件"导致的测试失败,均可通过换行符统一、CMake 条件编译和"直接运行 cppDESTest"的方式规避。
- 最终产物:lycium/usr/cppDES/
<ARCH>/ 下的静态库与头文件可供应用集成;cppDES-master/<ARCH>-build/cppDESTest 用于设备端功能验证。
若你在使用 lycium 接入其他 C/C++ 三方库时也遇到类似"测试发现"或"路径不一致"问题,可参考本文的排查思路与修改方式。更多 OpenHarmony 跨平台与三方库共建内容,欢迎在 开源鸿蒙跨平台社区 交流。
参考与相关链接
- cppDES 上游:https://github.com/fffaraz/cppDES
- tpc_c_cplusplus / lycium:OpenHarmony 三方库 C/C++ 共建仓库及交叉编译框架
- 环境搭建 : OpenHarmony 交叉编译环境配置
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net/