DDlog 高性能异步日志库在 OpenHarmony 的 lycium 适配与分步测试

欢迎加入 开源鸿蒙跨平台社区,与开发者一起共建鸿蒙三方库的开源生态。


一、背景与目标

DDlogdavidditao/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;需安装 cmakemakepatchwget 等。

  • OHOS SDK :需包含 native/llvmnative/build-tools/cmakenative/build/cmake/ohos.toolchain.cmake 等;环境变量指向 SDK 根目录,例如:

    bash 复制代码
    export 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} 便于排查。


四、编译流程与命令

  1. 进入 lycium 目录

    bash 复制代码
    cd /path/to/tpc_c_cplusplus/lycium
  2. 执行编译(仅编译 ddlog,建议先 cleanbuild 再编):

    bash 复制代码
    ./build.sh ddlog cleanbuild
    ./build.sh ddlog
  3. 脚本将依次:检查 OHOS_SDK、下载/解压 DDlog-master、对每个 ARCH 执行 prepare → cmake → make → package。

  4. 产物位置

    • 静态库与头文件: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_minimalddlog_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 跨平台与三方库共建内容,欢迎在 开源鸿蒙跨平台社区 交流。


参考与相关链接

相关推荐
民国二十三画生2 小时前
C++(兼容 C 语言) 的标准输入语法,用来读取一行文本
c语言·开发语言·c++
柒儿吖2 小时前
基于 lycium 在 OpenHarmony 上交叉编译 utfcpp 完整实践
c++·c#·harmonyos
sTone873752 小时前
std::function/模板/裸函数指针选型指南
c++
无聊的小坏坏2 小时前
一文讲通:二分查找的边界处理
数据结构·c++·算法
云深处@2 小时前
【C++11】包装器,智能指针
开发语言·c++
十五年专注C++开发2 小时前
CMake进阶:SelectLibraryConfigurations模块
c++·cmake·自动化构建
量子炒饭大师2 小时前
【C++入门】Cyber深度漫游者的初始链路——【类与对象】初始化成员列表
开发语言·c++·dubbo·类与对象·初始化成员列表
mmz12072 小时前
逆序对问题(c++)
c++·算法
化学在逃硬闯CS2 小时前
Leetcode110.平衡二叉树
数据结构·c++·算法·leetcode