rudp Reliable UDP 库在 OpenHarmony 的 lycium 适配与 CRC32 测试
本文介绍了将C语言实现的Reliable UDP库(rudp)接入OpenHarmony三方库生态的过程。通过lycium交叉编译框架,在Mac/Linux宿主机上完成对rudp库的OHOS适配,生成适用于不同架构的静态库librudp.a及相关头文件。为规避设备端网络问题,专门编写了不依赖socket的CRC32测试用例(rudp_test),验证库内纯函数功能。整个流程包括环境配置、源码编译、
欢迎加入 开源鸿蒙跨平台社区,与开发者一起共建鸿蒙三方库的开源生态。
一、背景与目标
rudp(evercomer/rudp)是 C 实现的 Reliable UDP 库,接口类似 POSIX socket(RUDPListen、RUDPAccept、RUDPSend、RUDPRecv 等),支持双逻辑通道、多线程安全,可在 Linux/Windows 上编译。上游仅提供 Makefile(无 CMake/autotools),无第三方依赖,仅需系统库 pthread、rt。本文记录在 OpenHarmony 三方库共建仓库(tpc_c_cplusplus) 中,使用 lycium 交叉编译框架 将 rudp 接入、通过 make 命令行传入 CC/AR 覆盖工具链完成 OHOS 交叉编译、在 prepare() 中生成 CRC32 测试用例(4 条,不依赖 socket),并在设备上通过 HPKCHECK 执行 ./rel/rudp_test 完成验证的完整过程。
目标:
- 在 Mac/Linux 宿主机上交叉编译出适用于 OpenHarmony(armeabi-v7a / arm64-v8a / x86_64)的 librudp.a 与头文件;
- 提供与上游 API 一致的 basetype.h、platform_adpt.h、rudp.h,供应用集成;
- 编写不依赖网络的 CRC32 测试(库内纯函数
calc_crc32),编出 rudp_test,避免设备上因 socket 导致的 Signal 11; - 设备上执行
./rel/rudp_test,输出 4 条 [PASS] 表示全部通过。
二、环境与框架简介
环境搭建更详细的步骤(SDK 下载、环境变量、依赖工具安装等)可参考:OpenHarmony 交叉编译环境配置。下文仅列出与本文直接相关的要点。
2.1 编译环境搭建
- 宿主机:建议 Mac(Darwin)或 Linux;需安装
make、wget(或 curl)等。 - OHOS SDK:需包含
native/llvm(提供*-linux-ohos-clang、llvm-ar);环境变量指向 SDK 根目录,例如:export OHOS_SDK=/path/to/OpenHarmony/Sdk/20 - lycium:每个三方库由目录下的 HPKBUILD 定义“下载 → 解压 → prepare → 编译 → 安装”;产物落在
lycium/usr/<pkgname>/<ARCH>/;设备侧测试由 HPKCHECK 中的 openharmonycheck() 定义。
2.2 rudp 上游特点
- 源码:使用 master 分支,通过
https://codeload.github.com/evercomer/rudp/zip/refs/heads/master下载,解压后目录名为 rudp-master;主要文件为 rudp.c、rudp.h、crc32.c、crc32.h、platform_adpt.c 等。 - 构建:上游仅提供 Makefile,使用
CC=$(CROSS)gcc、AR=$(CROSS)ar,无make install;本适配不引入 CMake,在 build() 中通过命令行传入CC、AR覆盖,使 OHOS 的*-linux-ohos-clang、llvm-ar生效,执行make rel=1 all生成 rel/librudp.a。 - API:RUDPListen、RUDPAccept、RUDPSend、RUDPRecv 等,需头文件 basetype.h、platform_adpt.h、rudp.h。
- 依赖:仅系统库 pthread、rt。
- 测试:上游有 socket 相关测试;本适配为避免设备上网络/socket 导致 Signal 11,在 prepare() 中通过 heredoc 生成 rudp_test.c,仅对库内纯函数 calc_crc32(crc32.h)做 4 条用例校验(空串、
"a"、"hello"、"123456789"),不调用 RUDPStart 或 socket。
2.3 HPKBUILD / HPKCHECK 在本库中的角色
- HPKBUILD:定义 pkgname=rudp、pkgver=1.0、source、builddir=rudp-master、buildtools=make;prepare() 中复制
$builddir为$builddir-$ARCH-build,按 ARCH 设置cc/ar(OHOS 的 clang、llvm-ar),并用 heredoc 生成 rudp_test.c(4 条 CRC32 用例);build() 中make CC="${cc}" AR="${ar}" rel=1 all编出 librudp.a,再编译 rudp_test.c 链接 librudp.a 得到 rel/rudp_test;package() 中拷贝头文件、librudp.a、rudp_test 到 usr/rudp/$ARCH/。 - HPKCHECK:设备上进入
${builddir}-${ARCH}-build,执行./rel/rudp_test,将输出写入 logfile,以退出码作为测试结果。
三、接入步骤
3.1 创建三方库目录与文件
在 Workspace/tpc_c_cplusplus/thirdparty/ 下新建目录 rudp,并准备:
| 文件 | 作用 |
|---|---|
| HPKBUILD | 包名、版本、源码、prepare(设 cc/ar、生成 rudp_test.c)/build/package |
| HPKCHECK | 设备上进入构建目录执行 ./rel/rudp_test,以退出码为结果 |
| README.OpenSource | 开源协议(Unlicense)、上游地址、版本(JSON 格式) |
| README_zh.md | 中文说明:简介、产物、编译、测试、API 用法等 |
| .gitignore | 忽略 rudp-master.zip、rudp-master/、rudp-master--build/、.log 等 |
3.2 rudp 的 HPKBUILD 配置要点
| 项 | rudp 取值 / 说明 |
|---|---|
| pkgname | rudp |
| pkgver | 1.0 |
| source | https://codeload.github.com/evercomer/rudp/zip/refs/heads/master |
| builddir | rudp-master |
| buildtools | make |
| archs | armeabi-v7a、arm64-v8a、x86_64 |
| depends | 无 |
- prepare():
cp -rf $builddir $builddir-$ARCH-build,进入构建目录后按 ARCH 设置cc、ar(如 arm64-v8a 为aarch64-linux-ohos-clang、llvm-ar);用 heredoc 生成 rudp_test.c,内含 4 条 CRC32 用例结构体与 main 循环,调用calc_crc32(init, data, len)与预期值比较,不涉及 socket。 - build():在
$builddir-$ARCH-build中执行$MAKE CC="${cc}" AR="${ar}" rel=1 all生成 rel/librudp.a;再执行"${cc}" -o rel/rudp_test rudp_test.c -D__LINUX__ -I. rel/librudp.a -lpthread -lrt编出测试程序。 - package():拷贝 basetype.h、platform_adpt.h、rudp.h 到
usr/rudp/$ARCH/include/,rel/librudp.a 到usr/rudp/$ARCH/lib/,rel/rudp_test 到usr/rudp/$ARCH/bin/。
prepare() 核心片段(按 ARCH 设置工具链并生成 rudp_test.c):
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
fi
if [ "$ARCH" = "arm64-v8a" ]; then
cc=${OHOS_SDK}/native/llvm/bin/aarch64-linux-ohos-clang
ar=${OHOS_SDK}/native/llvm/bin/llvm-ar
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
fi
# 用 heredoc 生成 rudp_test.c(4 条 CRC32 用例,略)
cat > rudp_test.c << 'ENDTEST'
#include "crc32.h"
#include <stdio.h>
#include <string.h>
/* ... test_case_t 与 cases[]、main 循环 ... */
ENDTEST
cd $OLDPWD
}
build() 核心片段:
build() {
cd $builddir-$ARCH-build
$MAKE CC="${cc}" AR="${ar}" rel=1 all >> "$buildlog" 2>&1
ret=$?
if [ $ret -ne 0 ]; then
cd $OLDPWD
return $ret
fi
"${cc}" -o rel/rudp_test rudp_test.c -D__LINUX__ -I. rel/librudp.a -lpthread -lrt >> "$buildlog" 2>&1
ret=$?
cd $OLDPWD
return $ret
}
package() 核心片段:
package() {
cd $builddir-$ARCH-build
_usr="$LYCIUM_ROOT/usr/$pkgname/$ARCH"
mkdir -p "$_usr/include" "$_usr/lib" "$_usr/bin"
cp -f basetype.h platform_adpt.h rudp.h "$_usr/include/"
cp -f rel/librudp.a "$_usr/lib/"
[ -f rel/rudp_test ] && cp -f rel/rudp_test "$_usr/bin/"
cd $OLDPWD
unset cc ar
}
3.3 为何采用 CRC32 测试而非完整 socket 测试
- 上游 rudp 的典型用法需 RUDPListen/RUDPAccept、RUDPSend/RUDPRecv,依赖网络与 socket。在部分 OpenHarmony 设备或环境下,直接跑完整服务端/客户端测试可能触发 Signal 11(SIGSEGV),不利于 CI 与自动化检查。
- 本适配仿 emoji_segmenter 思路:只测库内纯函数(不依赖 socket)。rudp 中的 calc_crc32(crc32.h)满足这一点,且与 RUDP 协议校验逻辑相关,具有代表性。4 条用例(空串、单字符、短串、数字串)即可验证 CRC32 实现正确性,设备上无需网络即可稳定通过。
3.4 HPKCHECK 设备侧测试逻辑
设备上进入 ${builddir}-${ARCH}-build(即 rudp-master/armeabi-v7a-build 等):
- 若存在 rel/rudp_test,则执行
./rel/rudp_test,标准输出与错误写入${logfile},以可执行文件退出码作为测试结果(0 为通过); - 若不存在可执行文件,则记录 “No rel/rudp_test executable, skip test”,返回 1。
四、编译流程与命令
-
进入 lycium 目录:
cd /path/to/tpc_c_cplusplus/lycium -
执行编译(仅编译 rudp):
./build.sh rudp -
脚本将依次:检查 OHOS_SDK、下载/解压 rudp-master、对每个 ARCH 执行 prepare → build → package,并写入
lycium/usr/hpk_build.csv。
-
产物位置:
- 静态库与头文件:
lycium/usr/rudp/armeabi-v7a/、lycium/usr/rudp/arm64-v8a/、lycium/usr/rudp/x86_64/(lib/librudp.a、include/basetype.h、platform_adpt.h、rudp.h)。 - 测试可执行文件:
lycium/usr/rudp/<ARCH>/bin/rudp_test,或构建目录内thirdparty/rudp/rudp-master/<ARCH>-build/rel/rudp_test。
- 静态库与头文件:
五、设备侧测试
将对应架构的构建目录(如 rudp-master/arm64-v8a-build)中的 rel/rudp_test 拷贝到设备,或直接使用安装后的 usr/rudp/<ARCH>/bin/rudp_test。在设备上进入包含 rel/rudp_test 的目录(若在构建目录内则为 rudp-master/<ARCH>-build)后执行:
./rel/rudp_test
通过时输出示例:
rudp tests (CRC32), 4 cases
[PASS] crc32 empty
[PASS] crc32 "a"
[PASS] crc32 "hello"
[PASS] crc32 "123456789"
All 4 tests passed.
退出码 0 表示全部通过。HPKCHECK 在设备上执行同一命令,结果写入 thirdparty/rudp/rudp_<ARCH>_<SDK_VER>_test.log,便于排查。

六、遇到的问题与解决方案
问题一:HPKBUILD 使用 CRLF 导致 source 报错或语法错误
现象:执行 ./build.sh rudp 时出现 syntax error near unexpected token 或 command not found(在 prepare/build 附近)。
原因:HPKBUILD 使用 Windows 换行符(CRLF),行尾 \r 导致 bash 解析异常。
解决:将 HPKBUILD、HPKCHECK 统一为 Unix 换行(LF),例如:
tr -d '\r' < HPKBUILD > HPKBUILD.tmp && mv HPKBUILD.tmp HPKBUILD
或在仓库内通过 .gitattributes 指定 HPKBUILD text eol=lf、HPKCHECK text eol=lf,避免再次引入 CRLF。
问题二:GitHub 源码下载失败(archive 链接超时或 404)
现象:使用 https://github.com/evercomer/rudp/archive/refs/heads/master.zip 等归档链接时下载失败。
原因:部分网络环境下 GitHub archive 不稳定或需代理。
解决:将 source 改为 codeload 形式:https://codeload.github.com/evercomer/rudp/zip/refs/heads/master,并设置 packagename=$builddir.zip(解压后目录仍为 rudp-master),提高下载成功率。若仍失败,可尝试镜像(如 mirror.ghproxy.com)或本地放置 zip 后关闭 downloadpackage。
问题三:设备上跑完整 socket 测试出现 Signal 11
现象:若在 rudp_test 中调用 RUDPListen、RUDPSend 等做完整收发测试,在部分设备上运行时报 Signal 11(SIGSEGV)。
原因:与设备侧网络栈、权限或运行时环境有关,非编译错误。
解决:本适配采用仅测 CRC32 的策略,不调用 RUDP 与 socket,仅验证库内 calc_crc32 的正确性,保证 HPKCHECK 与设备侧自动化测试稳定通过。完整 RUDP 功能可在应用集成后在实际网络环境中自行验证。
七、总结
- rudp 在 OpenHarmony 上的交叉编译依赖 lycium 的 HPKBUILD/HPKCHECK 机制。上游仅 Makefile、无 CMake,本适配通过 make 命令行传入 CC/AR 覆盖工具链(参考 make 交叉编译文档),在宿主机完成构建,得到 librudp.a、头文件与 rudp_test。
- 测试策略:为避免设备上 socket 导致的 Signal 11,在 prepare() 中生成 rudp_test.c,仅对 calc_crc32 做 4 条用例校验,无网络依赖,设备上执行
./rel/rudp_test即可稳定通过;HPKCHECK 以该可执行文件退出码作为结果。 - 典型问题:HPKBUILD 的 CRLF 需统一为 LF;源码下载可改用 codeload 或镜像;完整 socket 测试建议在应用集成后于实际环境中验证。
- 最终产物:lycium/usr/rudp/
<ARCH>/ 下的静态库与头文件可供应用集成(链接-lrudp -lpthread -lrt);rel/rudp_test 用于设备端 CRC32 功能验证。
若你在使用 lycium 接入仅提供 Makefile 的 C 库时,可参考本文的“CC/AR 覆盖 + prepare 内生成无 socket 测试”的方式。更多鸿蒙三方库共建内容,欢迎在 开源鸿蒙跨平台社区 交流。
参考与相关链接
- rudp 上游:https://github.com/evercomer/rudp
- make 交叉编译文档:tpc_c_cplusplus docs/make_portting.md
- tpc_c_cplusplus / lycium:OpenHarmony 三方库 C/C++ 共建仓库及交叉编译框架
- 环境搭建:OpenHarmony 交叉编译环境配置
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net/
- AtomGit 仓库地址:https://atomgit.com/oh-tpc/rudp
更多推荐
所有评论(0)