欢迎加入 开源鸿蒙跨平台社区,与开发者一起共建鸿蒙三方库的开源生态。
一、背景与目标
DDlog (davidditao/DDlog)是基于 C++ 的高性能异步日志库,支持多级别日志(TRACE/DEBUG/INFO/WARN/ERROR/FATAL)、双缓冲异步写盘、按大小/时间滚动日志文件,提供流式 API(LOG_INFO << "msg";),无第三方依赖,仅需 C++11 与 POSIX,适合作为 OpenHarmony 应用与 Native 的日志基础设施。本文记录在 OpenHarmony 三方库共建仓库(tpc_c_cplusplus) 中,使用 lycium 交叉编译框架 将 DDlog 接入、编译静态库与多档测试可执行文件,以及在 64 位 CPU + 32 位用户态 开发板上进行分步测试、定位 SIGILL 的完整过程;当前 32 位用户态下写日志路径存在已知限制,后续待 64 位用户态环境就绪后再进行完整功能测试。
目标:
- 在 Mac/Linux 宿主机上交叉编译出适用于 OpenHarmony(armeabi-v7a / arm64-v8a)的 libddlog.a 与头文件;
- 编出多档测试可执行文件(ddlog_minimal、ddlog_setlevel、ddlog_log_int 等),便于在设备上分步定位问题;
- 产物可被其他 Native/应用工程链接使用;HPKCHECK 做产物存在性检查,设备上可手动跑分步测试或待 64 位用户态下跑完整 demo。
二、环境与框架简介
环境搭建 更详细的步骤可参考:OpenHarmony 交叉编译环境配置。下文仅列出与本文直接相关的要点。
2.1 编译环境搭建
-
宿主机 :建议 Mac(Darwin)或 Linux;需安装
cmake、make、patch、wget等。 -
OHOS SDK :需包含
native/llvm、native/build-tools/cmake、native/build/cmake/ohos.toolchain.cmake等;环境变量指向 SDK 根目录,例如:bashexport OHOS_SDK=/path/to/OpenHarmony/Sdk/20 -
lycium :每个三方库由目录下的 HPKBUILD 定义"下载 → 解压 → prepare → 编译 → 安装";产物落在
lycium/usr/<pkgname>/<ARCH>/;设备侧测试由 HPKCHECK 中的 openharmonycheck() 定义。
2.2 DDlog 上游特点
- 源码 :GitHub 无 CMake,使用分支归档
https://github.com/davidditao/DDlog/archive/refs/heads/master.tar.gz,解压后目录名为 DDlog-master。 - 构建 :上游无构建系统,本仓提供 CMakeLists.txt ,包含:
- 静态库目标 ddlog(产物 libddlog.a);
- 可选测试可执行文件(BUILD_DEMO=ON 时):ddlog_demo、ddlog_minimal、ddlog_setlevel、ddlog_log_int、ddlog_log_cstr、ddlog_log_multi。
- 依赖:无第三方库,仅 C++11 与 POSIX。
- 适配内容 :logfile 中
readlink("/proc/self/exe")在 OpenHarmony 上可能失败,补丁在失败时使用默认进程名"app";上游若干 typo(logstream.h、asynclogging.cc、logger.h 中 LOG_WARN/ERROR/FATAL 的 logger→Logger)通过补丁与 sed 修复。
2.3 HPKBUILD / HPKCHECK 在本库中的角色
- HPKBUILD :定义 pkgname=ddlog、pkgver=master、source、builddir=DDlog-master、buildtools=cmake;prepare() 中拷贝本仓 CMakeLists.txt 与各 demo_*.cc,并依次应用 0001~0004 补丁及 logger.h 的 sed 修复;build() 中 cmake 打开 BUILD_DEMO=ON 并全量 make;package() 中拷贝 libddlog.a、头文件及各测试可执行文件到 usr/ddlog/$ARCH/。
- HPKCHECK :不运行 demo(因 32 位用户态下写日志会 SIGILL),仅校验 libddlog.a 是否存在于构建目录或 usr 安装目录,通过即视为检查通过。
三、接入步骤
3.1 创建三方库目录与文件
在 Workspace/tpc_c_cplusplus/thirdparty/ 下新建目录 ddlog,并准备:
| 文件 | 作用 |
|---|---|
| HPKBUILD | 包名、版本、源码、prepare(补丁+sed)/build/package/cleanbuild |
| HPKCHECK | 设备上仅检查 libddlog.a 是否存在,不执行可执行文件 |
| CMakeLists.txt | 本仓提供,上游无;静态库 + BUILD_DEMO 时多档测试可执行文件 |
| demo_main.cc / demo_minimal.cc / demo_setlevel.cc 等 | 测试用例源码 |
| 0001~0004 补丁 | OpenHarmony 兼容与上游 typo 修复 |
| README.OpenSource | 开源协议、上游地址 |
| README_zh.md | 中文说明:编译、测试、已知限制、应用侧使用 |
3.2 DDlog 的 HPKBUILD 配置要点
| 项 | ddlog 取值 / 说明 |
|---|---|
| pkgname | ddlog |
| pkgver | master |
| source | https://github.com/davidditao/DDlog/archive/refs/heads/master.tar.gz |
| builddir | DDlog-master |
| buildtools | cmake |
| archs | armeabi-v7a、arm64-v8a |
| depends | 无 |
- prepare() :拷贝 CMakeLists.txt 与各 demo_*.cc;对解压后的源码依次应用 0001(logfile readlink fallback)、0002(logstream typo)、0003(asynclogging bind)、0004(logstream bzero,-l -N)、并对 src/logger.h 用 sed 将
#define LOG_WARN logger(等改为Logger(;最后mkdir -p $ARCH-build。 - build() :cmake 传入
-DBUILD_DEMO=ON,全量 make,生成 libddlog.a 与各测试可执行文件。 - package() :拷贝 libddlog.a 与 src/*.h 到 usr/ddlog/ A R C H / l i b 与 i n c l u d e / d d l o g / ;拷贝 d d l o g d e m o 、 d d l o g m i n i m a l 、 d d l o g s e t l e v e l 等(若存在)到 u s r / d d l o g / ARCH/lib 与 include/ddlog/;拷贝 ddlog_demo、ddlog_minimal、ddlog_setlevel 等(若存在)到 usr/ddlog/ ARCH/lib与include/ddlog/;拷贝ddlogdemo、ddlogminimal、ddlogsetlevel等(若存在)到usr/ddlog/ARCH/bin/。
3.3 armeabi-v7a 的编译选项(32 位用户态兼容)
在 CMakeLists.txt 中对 OHOS_ARCH=armeabi-v7a 增加:
-mfpu=vfpv3-d16 -mfloat-abi=softfp -marm
以与常见 32 位用户态 ABI 一致,减少因 NEON/硬浮点导致的非法指令。若仅需验证"进程启动 + setLogLevel",当前选项下 ddlog_minimal、ddlog_setlevel 在实测板子上可正常退出 0。
3.4 HPKCHECK 仅做产物检查
因 32 位用户态下执行 LOG_INFO << ... 会触发 Signal 4(见第五节),HPKCHECK 中 不运行 任何可执行文件,仅检查:
- 优先:
${builddir}/${ARCH}-build/libddlog.a存在; - 否则:
${LYCIUM_ROOT}/usr/${pkgname}/${ARCH}/lib/libddlog.a存在。
满足其一即 return 0,否则 return 1。测试日志写入 ${logfile} 便于排查。
四、编译流程与命令
-
进入 lycium 目录:
bashcd /path/to/tpc_c_cplusplus/lycium -
执行编译(仅编译 ddlog,建议先 cleanbuild 再编):
bash./build.sh ddlog cleanbuild ./build.sh ddlog -
脚本将依次:检查 OHOS_SDK、下载/解压 DDlog-master、对每个 ARCH 执行 prepare → cmake → make → package。
-

-
产物位置:
- 静态库与头文件:
lycium/usr/ddlog/armeabi-v7a/、lycium/usr/ddlog/arm64-v8a/(lib/libddlog.a、include/ddlog/*.h)。 - 测试可执行文件:
thirdparty/ddlog/DDlog-master/<ARCH>-build/下 ddlog_demo、ddlog_minimal、ddlog_setlevel、ddlog_log_int、ddlog_log_cstr、ddlog_log_multi;或安装后位于lycium/usr/ddlog/<ARCH>/bin/。
- 静态库与头文件:
五、设备侧分步测试与已知限制
5.1 分步测试可执行文件说明
编好后在板子上可按顺序运行下列可执行文件,每次 echo $? 查看退出码,用于定位哪一步开始出现 Signal 4:
| 可执行文件 | 做的事 | 通过则说明 |
|---|---|---|
| ddlog_minimal | 只链接库,不调任何接口 | 进程启动/加载正常 |
| ddlog_setlevel | 只调 Logger::setLogLevel(Logger::INFO) |
设置级别无 SIGILL |
| ddlog_log_int | setLevel +LOG_INFO << 42 |
整数写入流无 SIGILL |
| ddlog_log_cstr | setLevel +LOG_INFO << "hello" |
字符串写入流无 SIGILL |
| ddlog_log_multi | 多条 LOG_INFO/LOG_WARN + 字符串和整数 | 完整日志路径可用 |
| ddlog_demo | 与日常用法一致的多条日志 | 全功能可用 |
5.2 32 位用户态板测结论(已知限制)
在 64 位 CPU + 32 位用户态 (getconf LONG_BIT=32)的开发板上实测:

- ddlog_minimal 、ddlog_setlevel :退出码 0,正常。说明进程加载、
Logger::setLogLevel在该环境下无问题。 - 从 ddlog_log_int (即首次执行
LOG_INFO << 42)起出现 Signal 4 (SIGILL),后续 ddlog_log_cstr、ddlog_log_multi、ddlog_demo 同理。
结论 :问题出在「写日志流」路径(Logger 构造/析构、operator<<、或所用 libc++/工具链在该 32 位环境下生成的指令不被支持),与 setLogLevel 无关。当前 32 位用户态下 standalone 可执行文件无法完整跑通写日志;可在应用内集成后实测,或待 64 位用户态环境就绪后用 arm64-v8a 构建再测。
5.3 后续完整测试计划
- 在 64 位用户态 环境下,使用 arm64-v8a 构建的 ddlog_demo 进行完整功能与日志输出验证。
- 或在已能在板子上稳定运行的应用中集成 libddlog.a,通过
LOG_INFO << "test"等验证实际写日志是否正常。
六、遇到的问题与解决方案
问题一:HPKBUILD / 补丁 CRLF 导致 "command not found" 或 patch 失败
现象:执行 build.sh 时出现 "line N: : command not found"、语法错误,或 patch 报 "unexpected end of file"。
原因 :HPKBUILD 或部分补丁文件使用了 Windows 换行符(CRLF)。bash 解析时行尾 \r 会导致异常;patch 对行尾敏感,CRLF 会导致 hunk 不匹配。
解决 :将 HPKBUILD、HPKCHECK、补丁等统一为 Unix 换行(LF) ;在 apply 前对补丁做 sed 's/\r$//' 再 pipe 给 patch。
问题二:0005-logger-fix-LOG-WARN-macro.patch 的 1 hunk failed
现象:prepare 阶段应用 0005 时提示 "1 out of 1 hunks failed",logger.h.rej 生成。
原因:上游 logger.h 与补丁中的上下文(空行/行号)不一致,patch 无法匹配。
解决 :不再使用 0005 补丁,在 prepare() 中用 sed 直接修改 src/logger.h:
sed -i.bak 's/^#define LOG_\(WARN\|ERROR\|FATAL\) logger(/#define LOG_\1 Logger(/' src/logger.h,避免依赖行号与空行。
问题三:设备上运行 ddlog_demo 报 Signal 4(SIGILL)
现象 :在 32 位用户态开发板上执行 ./ddlog_demo 或 ./ddlog_log_int 等会触发 Signal 4,退出码 132。
原因 :首次执行「写日志流」(如 LOG_INFO << 42)时,Logger/LogStream 或 libc++ 在该 32 位环境下生成的指令不被 CPU/内核支持,导致非法指令。setLogLevel 与进程启动路径正常。
解决:通过分步测试可执行文件(ddlog_minimal → ddlog_setlevel → ddlog_log_int → ...)精确定位到「写流」路径;当前在 README 与本文中记录为已知限制,建议在应用内集成验证或待 64 位用户态下再完整测试。
问题四:test.sh 报 "bad interpreter: /usr/bin/bash"
现象 :在 Mac 上执行 ./test.sh ddlog 提示 "bad interpreter: /usr/bin/bash: no such file or directory"。
原因 :test.sh 首行为 #!/usr/bin/bash,而 macOS 上 bash 通常位于 /bin/bash。
解决 :将 test.sh 的 shebang 改为 #!/bin/bash。
七、总结
- DDlog 在 OpenHarmony 上的交叉编译依赖 lycium 的 HPKBUILD/HPKCHECK 机制;因上游无 CMake,本仓提供 CMakeLists.txt 与多档测试可执行文件,通过补丁与 sed 完成 OpenHarmony 兼容与上游 typo 修复,即可在宿主机完成构建,得到 libddlog.a、头文件与 ddlog_demo、ddlog_minimal、ddlog_setlevel 等。
- 设备侧 :HPKCHECK 仅做 libddlog.a 存在性检查 ,不运行 demo;在 32 位用户态板子上通过分步测试可定位到「写日志流」路径触发 SIGILL,结论已记录于 README,后续待 64 位用户态环境就绪再进行完整功能测试。
- 最终产物:lycium/usr/ddlog/
<ARCH>/ 下的静态库与头文件可供应用集成;各测试可执行文件用于设备端分步验证或 64 位用户态下的完整验证。
若你在使用 lycium 接入无 CMake 或需强兼容 32 位用户态的 C++ 库时也遇到类似问题,可参考本文的补丁/sed 处理与分步测试思路。更多 OpenHarmony 跨平台与三方库共建内容,欢迎在 开源鸿蒙跨平台社区 交流。
参考与相关链接
- DDlog 上游:https://github.com/davidditao/DDlog
- tpc_c_cplusplus / lycium:OpenHarmony 三方库 C/C++ 共建仓库及交叉编译框架
- 环境搭建 :OpenHarmony 交叉编译环境配置
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net/