[!NOTE]

加入开源鸿蒙跨平台社区

・共享三方库移植方案、跨平台应用开发

・互助解决编译 / 运行问题

・第一时间获取鸿蒙三方库适配模板

一个人走得快,一群人走得远!

1. 概述

Abseil C++ 是 Google 开源的 C++ 基础库,与标准库互补,广泛用于 gRPC、Protobuf 等。本章节将介绍如何在鸿蒙应用集成abseil-cpp鸿蒙化三方库的完整示例。

说明
适配版本 20260107.1(Abseil LTS)
源库地址 abseil/abseil-cpp
协议 Apache-2.0
适配地址 oh-tpc/abseil-cpp
目标架构 armeabi-v7aarm64-v8a
适配作者 allincoding
示例源代码 AbseilCPPSample

image-20260401145634764

已完成适配abseil-cpp模块

方向 代表模块(路径/命名空间) 提供的能力(你会用它做什么) HarmonyOS NDK 示例默认推荐
字符串 absl/strings/* string_view、拼接/分割/格式化、数字解析、匹配与裁剪、Cord 推荐
状态返回 absl/status/* Status/StatusOr<T>,统一错误码与消息的传递方式 强烈推荐
时间 absl/time/* Time/Duration/TimeZoneNow()FormatTime/ParseTime,Civil time 推荐
容器 absl/container/* flat_hash_map/setnode_hash_*btree_*InlinedVector 推荐(按场景选型)
哈希 absl/hash/* absl::Hash、组合哈希、与容器配套的哈希策略 推荐(配合容器/自定义 key)
随机数 absl/random/* BitGenUniform、各种分布 推荐(替代 rand()
数值/位运算 absl/numeric/* int128/uint128bits(popcount/rotl/rotr 等) 推荐(需要时)
算法封装 absl/algorithm/* 面向容器的算法(如 c_sort 等) 可选
作用域清理 absl/cleanup/* 作用域退出执行清理(defer/RAII 风格) 推荐(写 C++ glue 很好用)
CRC absl/crc/* CRC32C 等检错校验、增量计算 可选(数据链路/存储格式需要时)
functional absl/functional/* FunctionRef/bind_front/Overload/AnyInvocable 等(随版本) 可选(回调体系复杂时很值)
memory absl/memory/* 内存/对齐/兼容性工具集合(随版本不同) 可选(更偏底层工程)
同步并发 absl/synchronization/* 线程同步原语、通知/屏障等 可选(Native 层多线程时)
日志 absl/log/* 日志框架、sink、与 flags 配合 谨慎(移动端通常已有日志体系)
Flags absl/flags/* 命令行 flags 定义/解析/usage 不推荐(移动端通常不用 CLI)
调试/栈 absl/debugging/* 栈追踪、符号化、故障处理等 可选(调试/崩溃排障)
profiling absl/profiling/* 采样/剖析相关挂钩与组件 谨慎(体积/开销/产物控制)
基础与平台 absl/base/* 配置/宏/端序/NoDestructor 等基石能力 隐式依赖(经常被上层带入)

2. 创建NDK工程

NDK(Native Development Kit)是HarmonyOS SDK提供的Native API、相应编译脚本和编译工具链的集合,方便开发者使用C或C++语言实现应用的关键功能。NDK只覆盖了HarmonyOS一些基础的底层能力,如C运行时基础库libc、图形库、窗口系统、多媒体、压缩库、面向ArkTS/JS与C跨语言的Node-API等,没有提供ArkTS/JS API的完整能力。

——引自HarmonyOS官方文档-NDK开发

  • 通过如下两种方式,打开工程创建向导界面。
    • 如果当前未打开任何工程,可以在DevEco Studio的欢迎页,选择**Create Project**开始创建一个新NDK工程。
    • 如果已经打开了工程,可以在菜单栏选择**File > New > Create Project**来创建一个新NDK工程。
  • 根据工程创建向导,选择Native C++工程模板,然后单击**Next**。

image-20260331140834644

  • 在工程配置页面,根据向导配置工程的基本信息后,单击Finish,工具会自动生成示例代码和相关资源,等待工程创建完成。

image-20260331141236322

  • 在工程entry/src/main目录下会包含cpp目录。

image-20260331141350783

entry/src/main # 应用模块,编译构建生成一个HAP
├── cpp
│   ├── CMakeLists.txt # CMake配置文件,提供CMake构建脚本
│   ├── napi_init.cpp # 定义C++ API接口的文件
│   └── types # 用于存放C++的API接口描述文件
│       └── libentry
│           ├── Index.d.ts # 描述C++ API接口行为,如接口名、入参、返回参数等
│           └── oh-package.json5 # 配置.so三方包声明文件的入口及包名
├── ets # 用于存放ArkTS源码
├── module.json5 # 配置文件,包含HAP的配置信息、应用在具体设备上的配置信息以及应用的全局配置信息
└── resources # 用于存放应用所用到的资源文件,如图形、多媒体、字符串、布局文件等。

具体请参考工程目录结构

项目结构

AbseilCPPSample/
├── AppScope/                              # 应用级配置(包名、bundle 等)
│   └── app.json5
├── hvigor/                                # hvigor 工程级配置
│   └── hvigor-config.json5
├── hvigorfile.ts                          # hvigor 构建入口脚本
├── build-profile.json5                    # 工程构建 profile(产品/签名等)
├── oh-package.json5                       # 工程级 ohpm 依赖声明
├── code-linter.json5                      # 代码检查规则
├── entry/                                 # 主模块(Ability + UI + NDK)
│   ├── build-profile.json5                # 模块级构建配置
│   ├── oh-package.json5
│   └── src/main/
│       ├── module.json5                   # 模块能力、请求权限等
│       ├── cpp/                           # Native C++(生成 libentry.so)
│       │   ├── CMakeLists.txt             # CMake:链接 Abseil、编译 napi_init.cpp
│       │   ├── napi_init.cpp              # N-API 注册与各能力导出(体量较大)
│       │   ├── thirdparty/
│       │   │   └── abseil-cpp/            # 预编译 Abseil(按架构)
│       │   │       ├── arm64-v8a/
│       │   │       │   ├── include/absl/  # 头文件
│       │   │       │   └── lib/           # 静态库、cmake/pkgconfig
│       │   └── types/libentry/            # `libentry.so` 的 ArkTS 类型侧
│       │       ├── Index.d.ts             # 导出函数/类型声明(与 napi 对齐)
│       │       └── oh-package.json5
│       ├── ets/
│       │   ├── entryability/
│       │   │   └── EntryAbility.ets       # UI Ability 入口
│       │   ├── entrybackupability/
│       │   │   └── EntryBackupAbility.ets # 备份扩展(模板自带)
│       │   ├── model/
│       │   │   ├── AbseilModuleMeta.ets   # 模块列表、摘要、是否含 NAPI 演示等元数据
│       │   │   └── ModuleNapiExports.ets  # 各模块导出的 NAPI 符号表(与 Index.d.ts 对齐,供说明页等使用)
│       │   ├── common/                    # 路由、主题、示例壳与 Markdown
│       │   │   ├── AbseilNavigation.ets   # NavPathStack、专页名表、push/pop 实现(ModuleRouteHelper 由此 re-export)
│       │   │   ├── ModuleRouteHelper.ets  # 打开「说明 / 示例 / 专页」的对外 API
│       │   │   ├── NeoDreamTheme.ets      # 全局深色底、液晶面板/顶栏/卡片等配色(NeoModuleRoot)
│       │   │   ├── FormFactor.ets         # 手机/平板断点:栅格列数、间距、字号等(@StorageLink)
│       │   │   ├── ExamplePageTheme.ets   # 示例与说明液晶区内:章节字色、正文色、输入框描边(与 ModuleExamples 共用)
│       │   │   ├── DedicatedExamplePageShell.ets  # 各 *Module 专页统一布局:顶栏 + 液晶 + 标准引导 + 业务 Column
│       │   │   ├── NapiDemoSupport.ets    # runSafelyNapi、常见返回形状等
│       │   │   ├── AbseilDemoCard.ets     # 演示卡片:intro / detail / arktsExample / 运行 / 结果
│       │   │   ├── MarkdownModel.ets      # 概述页 Markdown AST 类型
│       │   │   ├── MarkdownParse.ets      # Markdown → AST(README 常用子集)
│       │   │   └── MarkdownBody.ets       # AST → ArkUI 排版
│       │   ├── home/                      # 首页 Tab 与子界面
│       │   │   ├── IndexOverviewTab.ets   # 总览 Tab(加载 rawfile/README.md)
│       │   │   ├── IndexIntroTab.ets      # 模块入口(查看说明)
│       │   │   ├── IndexExamplesTab.ets   # 交互示例 Tab(打开示例)
│       │   │   └── ModuleDocBody.ets      # 仅说明正文(摘要/能力/详细说明)
│       │   └── pages/
│       │       ├── Index.ets              # 主页面(多 Tab 容器)
│       │       ├── ModuleDoc.ets          # 模块说明页(无 libentry 依赖)
│       │       ├── ModuleExamples.ets     # 模块通用示例页(napi_base/strings/status 等内嵌卡片;无专页时占位提示)
│       │       ├── TimeModule.ets         # ┐
│       │       ├── ContainerModule.ets    # │
│       │       ├── HashModule.ets         # │
│       │       ├── RandomModule.ets       # ├─ 各 Abseil 方向的独立演示专页
│       │       ├── NumericModule.ets      # │  (与 AbseilNavigation.DEDICATED_NAV_NAMES 一致)
│       │       ├── AlgorithmModule.ets    # │
│       │       ├── CleanupModule.ets      # │
│       │       ├── CrcModule.ets          # │
│       │       ├── FunctionalModule.ets   # │
│       │       ├── MemoryModule.ets       # │
│       │       ├── SynchronizationModule.ets
│       │       ├── LogModule.ets          # │
│       │       ├── FlagsModule.ets        # │
│       │       ├── DebuggingModule.ets    # │
│       │       ├── ProfilingModule.ets    # │
│       │       └── BaseModule.ets         # ┘
│       └── resources/
│           ├── rawfile/
│           │   └── README.md              # 概述 Tab 全文(与仓库根 README.md 保持一致并随包发布)
│           └── base/
│               ├── profile/
│               │   └── main_pages.json    # 页面路由注册(上述 pages 须在此列出)
│               ├── element/               # 颜色、字号等主题资源
│               └── media/                 # 媒体与图层资源
└── ...                                    # 构建产物见 entry/build/、.cxx/(通常不入库)
ArkTS 分层说明
目录/文件 作用
ets/model/AbseilModuleMeta.ets 单一数据源:模块 id、标题、摘要、hasNativeDemo、说明段落等,驱动首页卡片与 ModuleDoc 内容。
ets/model/ModuleNapiExports.ets 按模块 id 列出本工程在 libentry.so 中导出的符号说明(与 types/libentry/Index.d.ts 一致);更新 NAPI 时需同步。
ets/common/AbseilNavigation.ets NavPathStack 路由:DEDICATED_NAV_NAMESIndex.etsnavDestination 一一对应;新增专页时两处都要登记。
ets/common/ModuleRouteHelper.ets 对外的 openModuleDocumentation / openModuleInteractiveDemo(由 AbseilNavigation re-export)。
ets/common/NeoDreamTheme.ets NeoModuleRootNeoPalette:应用级渐变底与「液晶」卡片视觉。
ets/common/FormFactor.ets 窄屏/宽屏布局参数(如 demoGridColumns、水平边距);专页与 ModuleExamples 共用。
ets/common/ExamplePageTheme.ets 示例/说明液晶区内的字色与输入框描边常量;ModuleExamples 与各专页共用,避免魔法色散落的。
ets/common/DedicatedExamplePageShell.ets 专页壳组件:与 ModuleExamples 同风格的顶栏 + 外留白 + 液晶面板 +「Native 交互示例」引导语 + moduleLeadExtra + 子内容插槽。
ets/common/AbseilDemoCard.ets 单条 NAPI 演示:介绍、示例详情、ArkTS 调用示例代码块、运行按钮、结果区(兼容旧版仅 desc)。
ets/common/NapiDemoSupport.ets runSafelyNapi 及常见结构化返回类型的 ArkTS 形状,供各页统一 try/展示错误。
ets/common/Markdown*.ets 概述 Tab 用:模型、解析、渲染(子集 Markdown)。
ets/home/* 首页三个 Tab;IndexOverviewTab 读取 resources/rawfile/README.md,经 MarkdownParse / MarkdownBody 排版。
resources/rawfile/README.md 仓库根目录 README.md 内容同步;更新后执行 cp README.md entry/src/main/resources/rawfile/README.md 再编译。
ets/pages/ModuleDoc.ets 当前模块的功能说明(液晶面板 + ModuleDocBody)。
ets/pages/ModuleExamples.ets 未拆专页的模块在此内嵌演示(如 napi_basestringsstatus 等);布局与专页一致(同色常量、输入区、栅格间距)。
ets/pages/*Module.ets 交互项多的模块独立成页(timecontainerhash…);内部使用 DedicatedExamplePageShell,卡片字段与 ModuleExamples 对齐。
ets/pages/Index.ets 主页面:Tab 容器 + Navigation/NavPathStack 与上述 pagesnavDestination 注册。
Native 侧要点
路径 说明
cpp/napi_init.cpp 所有导出到 ArkTS 的 N-API 实现;与 types/libentry/Index.d.ts 保持同名、同签名。
cpp/thirdparty/abseil-cpp/<arch>/ 与当前 OHOS_ARCH 一致的预编译产物;勿混用架构目录。

3. 应用中集成abseil-cpp三方库

  • abseil-cpp三方库生成的二进制文件oh-tpc/abseil-cpp/output目录下的文件拷贝到应用工程目录。

注:为了更好的管理应用集成的三方库,在应用工程的cpp目录新建一个thirdparty目录,将生成的二进制文件以及头文件拷贝到该目录下(根据实际的架构选择)。

image-20260331143046850

  • 打开cpp/CMakeLists.txt文件配置静态链接和头文件。

在调用 CMake 时会注入 OHOS_ARCH。本仓库采用 absl_DIR + find_package(... CONFIG) 加载官方风格的 Abseil CMake 包,并对 entry 目标单独增加 target_include_directories(PRIVATE ${ABSL_ROOT}/include),避免仅依赖全局 include_directories 时遗漏 Abseil 头路径。

完整列表以 entry/src/main/cpp/CMakeLists.txt 为准

cmake_minimum_required(VERSION 3.5.0)
project(AbseilCPPSample)

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

if(DEFINED PACKAGE_FIND_FILE)
    include(${PACKAGE_FIND_FILE})
endif()

include_directories(${NATIVERENDER_ROOT_PATH}
                    ${NATIVERENDER_ROOT_PATH}/include)

# ---------- abseil-cpp:按架构选包 ----------
if(${OHOS_ARCH} STREQUAL "armeabi-v7a")
    set(ABSL_ROOT ${NATIVERENDER_ROOT_PATH}/thirdparty/abseil-cpp/armeabi-v7a)
elseif(${OHOS_ARCH} STREQUAL "arm64-v8a")
    set(ABSL_ROOT ${NATIVERENDER_ROOT_PATH}/thirdparty/abseil-cpp/arm64-v8a)
else()
    message(FATAL_ERROR "Unknown OHOS_ARCH=${OHOS_ARCH}, expected armeabi-v7a or arm64-v8a")
endif()

# 指向 abslConfig.cmake 所在目录(注意是 lib/cmake/absl,不是 lib/cmake 根目录)
set(absl_DIR ${ABSL_ROOT}/lib/cmake/absl)
find_package(absl REQUIRED CONFIG)

add_library(entry SHARED napi_init.cpp)
target_include_directories(entry PRIVATE ${ABSL_ROOT}/include)

target_link_libraries(entry PRIVATE
    libace_napi.z.so
    absl::strings
    absl::string_view
    absl::status
    absl::statusor
    absl::time
    absl::time_zone
    absl::civil_time
    absl::cord
    absl::cord_internal
    absl::synchronization
    absl::spinlock_wait
    absl::hash
    absl::city
    absl::raw_hash_set
    absl::random_random
    absl::random_distributions
    absl::random_seed_sequences
    absl::int128
    absl::base
    absl::throw_delegate
    absl::raw_logging_internal
    absl::log_internal_check_op
    absl::log_internal_message
    absl::log_entry
    absl::log_sink
    absl::log_severity
    absl::log_flags
    absl::log_globals
    absl::log_initialize
    absl::log
    absl::check
    absl::log_sink_registry
    absl::exponential_biased
    absl::periodic_sampler
    absl::sample_recorder
    absl::str_format
    absl::str_format_internal
    absl::strerror
    absl::flags
    absl::flags_parse
    absl::flags_usage
    absl::debugging
    absl::failure_signal_handler
    absl::hashtable_profiler
    absl::flat_hash_map
    absl::flat_hash_set
    absl::node_hash_map
    absl::node_hash_set
    absl::btree
    absl::optional
    absl::variant
    absl::any
    absl::span
    absl::memory
    absl::type_traits
    absl::utility
    absl::algorithm
    absl::cleanup
    absl::crc32c
    absl::any_invocable
    absl::bind_front
    absl::function_ref
    absl::overload
    absl::numeric
    absl::compare
    absl::endian
    absl::bits
)

说明:

  • find_package(absl REQUIRED CONFIG) 依赖 absl_DIR 指向 lib/cmake/absl;不要使用已过时的仅 list(APPEND CMAKE_MODULE_PATH ${ABSL_ROOT}/lib/cmake)find_package(absl) 的写法,除非你能确认所用 Abseil 包布局仍支持。
  • target_link_libraries(... PRIVATE ...):Native 动态库一般只需把 Abseil 静态进自己 .so,用 PRIVATE 即可,避免向依赖方传递不必要的链接要求。
  • 链接列表较长是为了覆盖本示例 napi_init.cpp 中演示到的 strings / status / time / 容器 / 哈希 / 随机 / 数值 / cleanup / crc / functional / debugging / flags / log 等模块;静态链接时顺序由 CMake 目标依赖处理,但仍建议不要随意删减除非你明确只用到子集并验证无未定义符号。

4. Native 接口实现(napi_init.cpp)

Native 侧集中在 entry/src/main/cpp/napi_init.cpp:在 Init(napi_env, napi_value exports) 中通过 napi_define_properties 将大量属性挂到导出对象上(与 HarmonyOS N-API 常规写法一致)。源码文件体量较大,这是为了把多模块演示集中在 单个 libentry.so 内,便于 ArkTS 侧 import testNapi from 'libentry.so' 一次导入。

4.1 与 ArkTS 类型的对应关系

  • 唯一权威的类型列表entry/src/main/cpp/types/libentry/Index.d.ts。其中 export function / export const 与 C++ 里注册的 属性名字符串必须一致,参数与返回值形状也应保持同步,否则会出现编译通过但运行期找不到属性或类型不符的问题。
  • 当前该文件中约有 两百个 导出符号(含 add 与各类 *Result 接口形状),覆盖多类 Abseil 能力;不在 README 中逐条罗列,查阅时请直接在 IDE 中打开 Index.d.ts,或按下面「子系统」在文件中搜索前缀。

4.2 按 Abseil 子系统划分的导出一览

下表概括 命名前缀或区域Abseil 头文件层次 的对应关系;具体函数名、参数与注释以 Index.d.ts 为准。

子系统(ArkTS 命名特征) 主要涉及的 Abseil 区域 说明
add (无) 纯整数加法,用于验证 NAPI 链路。
strCatstartsWithstrSplit*strJoin*consume*substitute* absl/strings 拼接、匹配、裁剪、分割、替换、格式化、string_view 相关演示。
statusmakeStatusstatusOr*invalidArgumentError absl/statusabsl/statusor Status / StatusOr、错误工厂与解析示例。
nowformatUnixMillisparseRFC3339parseDurationformatDurationFromMillis absl/time 当前时间、格式化/解析、Duration 与毫秒运算。
stringView absl/string_view 长度与前缀探测等轻量示例。
container* absl/container flat_hash_map/setnode_hash_setbtree_* 与字符串分词组合演示。
hashHex*hashStringVsStringView absl/hash 哈希值以十六进制字符串等形式返回,便于 ArkTS 展示。
random* absl/random BitGen / InsecureBitGen、均匀与多种分布(非密码学随机)。
algorithm* absl/algorithm 与容器配合的查找、排序、累计等(输入多为逗号分隔整数 CSV)。
cleanup* absl/cleanup 作用域退出清理、Cancel / Invoke / 移动语义。
crc32c* absl/crc CRC32C 计算、扩展、拼接与 MemcpyCrc32c 等。
functional* absl/functional bind_frontFunctionRefAnyInvocableOverloadvisit 等。
memory* absl/memory 与智能指针、分配器特征相关的可运行小示例。
sync* absl/synchronization 互斥、读写锁、条件变量、NotificationBlockingCounterBarrier 等;实现中会在 Native 内创建短生命周期 std::thread,仅用于演示。
log* absl/log 通过 ToSinkOnly 等将日志正文捕获到返回值字符串;InitializeLog 在进程内通常仅首次有效。
flags* absl/flags 本 so 内注册的演示用 ABSL_FLAG(如 abseil_demo_int 等)的读写与解析示例。
debugging* absl/debugging 栈回溯摘要、符号化、LeakCheck 相关状态说明等(未在示例中安装进程级故障信号处理器,避免副作用)。
profiling* absl/profiling 哈希表剖析数据预览、Hashtablez 全局配置、ExponentialBiased 等。
base* absl/base bit_cast、字节序、call_once、周期时钟采样、ErrnoSaver 等与 base 相关的可运行 API。
popcount*rotlU32uint128*int128ToDecFromHalves absl/numericbitsint128 位运算与 128 位整数十进制字符串形式往返。

4.3 实现与维护注意点

建议
新增导出 napi_init.cppnapi_property_descriptor 表中增加一项,并在 Index.d.ts 中增加同名声明;复杂返回值优先用 普通对象 + 字段(与现有 *Result 一致),避免在 TS 侧难以表达的类型。
线程与全局状态 sync*logInitializeOnceflags*debuggingSymbolizerInitOnce 等会改变进程内全局或线程状态,演示页重复调用时行为可能与「首次调用」不同,属预期现象。
性能与体积 本文件为教学演示聚合了大量符号;若你仅需要 Abseil 的某一子集,可复制对应绑定函数并 裁剪 Init 中的描述符表与 CMakeLists.txt 中的 absl::* 链接项(见第 4.4 节)。

4.4 最小调用示例(ArkTS)

下列接口仍可作为「从 ArkTS 试通 Native」的最小用例;更多接口用法见各 pages/*Module.etsModuleExamples.ets

import testNapi from 'libentry.so';

const sum = testNapi.add(2, 3);
const cat = testNapi.strCat('Hello', 'Abseil');
const st = testNapi.status(0); // StatusResult:含 ok、code、codeName、message、statusString 等
const ms = testNapi.now();
const sv = testNapi.stringView('Hello HarmonyOS');

5. ArkTS 调用 Native 接口

ArkTS 通过 ohpm 本地依赖libentry.so 映射到带类型的包目录;业务页面再 import 该模块即可调用第 5 节注册的 NAPI。本仓库中 首页 Index.ets 不直接调用 testNapi,而是拆成 Tab 与子页;真正密集调用 Native 的是 ModuleExamples.ets、各 *Module.ets 专页等。

5.1 依赖声明与导入方式

模块级依赖entry/oh-package.json5)将 libentry.so 指向类型与包元数据所在目录:

{
  "dependencies": {
    "libentry.so": "file:./src/main/cpp/types/libentry"
  }
}

该目录下的 Index.d.ts 即为 TypeScript/ArkTS 侧类型来源;oh-package.json5types/libentry 内)需与 NAPI 注册保持一致(一般由模板与 napi_init.cpp 同步维护)。

在任意 .ets 页面或组件中导入:

import testNapi from 'libentry.so';

之后即可使用 testNapi.addtestNapi.strCat 等与 Index.d.tsexport 一致的成员。

5.2 主界面结构(pages/Index.ets

当前首页为 底部 Tabs,三个页签分别加载子组件(Index 内写 NAPI 调用):

Tab 组件 作用
概述 IndexOverviewTab 工程与适配信息总览。
介绍 IndexIntroTab 模块卡片网格;「查看说明」 跳转说明页。
示例 IndexExamplesTab 已标注 hasNativeDemo 的模块;「打开示例」 进入专页或通用示例页。

路由 API 在 common/ModuleRouteHelper.ets(实现见 AbseilNavigation.ets):openModuleDocumentation(moduleId)pages/ModuleDocopenModuleInteractiveDemo(moduleId) → 专页(由 DEDICATED_NAV_NAMES 映射到 NavPathStack 名)或 pages/ModuleExamples

5.3 哪些页面会用到 libentry.so

类型 代表路径 是否 import libentry.so
纯说明 pages/ModuleDoc.ets + home/ModuleDocBody.ets ,仅展示 AbseilModuleMeta 文案。
通用示例 pages/ModuleExamples.ets ,供 列入专页表的 moduleId(如 napi_basestringsstatus);time 等已走专页。
专页 pages/TimeModule.etsContainerModule.ets、… ,按主题拆分交互,避免单文件过大。
首页 Tab home/Index*.ets ,只负责导航与元数据展示。

新增专页时:在 resources/base/profile/main_pages.json 注册 pages/xxx,在 Index.etsnavDestination 增加对应 NavDestination,并在 AbseilNavigation.etsDEDICATED_NAV_NAMES 中增加 moduleId → 导航名(与 pushPathByName 一致)。

5.4 推荐调用习惯:安全封装与 UI 卡片

Native 侧若 napi_throw 或断言失败,ArkTS 可能收到异常。本仓库在 common/NapiDemoSupport.ets 中提供 runSafelyNapi(name, fn):在 try/catch 中执行 () => testNapi.xxx(...),返回 { ok, value?, error? },并把错误写入 hilog,便于在 UI 上展示「错误:…」而不打断页面。

演示 UI 使用 common/AbseilDemoCard.ets:推荐 intro / detail / arktsExample(介绍、示例详情、ArkTS 调用示例代码块),以及 title / result@Prop 绑定)onRun(内用 runSafelyNapi 写回 @State)。仍兼容仅填 desc 的旧用法。专页与 ModuleExamples 共用同一卡片组件。

5.5 代码片段:在组件中调用一项 NAPI

import testNapi from 'libentry.so';
import { runSafelyNapi } from '../common/NapiDemoSupport';

// 在 @Component 内:
@State addResult: string = '';

// 例如在 Button.onClick 或 AbseilDemoCard.onRun 中:
const r = runSafelyNapi('add', () => testNapi.add(2, 3) as Object);
this.addResult = r.ok ? `add(2,3) = ${r.value as number}` : `错误:${r.error}`;

直接调用(无 try/catch)在确定不会抛错的小脚本中也可行,与第 5.4 节最小示例一致:

import testNapi from 'libentry.so';
const n: number = testNapi.now();

6. 编译构建

6.1 推荐方式:DevEco Studio

  • 使用 DevEco Studio 打开工程根目录(含 build-profile.json5entry 模块)。
  • 菜单 Build > Build Hap(s)/APP(s)(或工具栏对应构建按钮)执行完整构建。
  • 修改了 CMakeLists.txtnapi_init.cppthirdparty/abseil-cpp 后,若 CMake 未自动重新配置,可执行 Build > Clean Project 后再 Rebuild,避免沿用旧的 .cxx 缓存。

构建过程中,NDK 会按当前产品配置分别 arm64-v8a 编译 Native 代码;Abseil 以静态库形式链入 libentry.so,再随 entry 模块打入 HAP

6.2 命令行构建(可选)

HarmonyOS 工程通常通过 hvigor 驱动构建。是否能在本机命令行直接执行,取决于是否已安装 ohpm/hvigor 并配置好环境变量;本仓库根目录未附带 hvigorw 包装脚本,若你本地没有统一 CLI,请以 IDE 构建为准。

在已配置命令行工具的环境下,常见做法是在工程根目录执行 hvigor 提供的 assemble 类任务(具体任务名以当前 SDK / 工程模板为准,可在 DevEco 的 Build Output 或官方文档中查阅)。构建失败时优先查看 Build 窗口中的 Native 编译日志(CMake、clang++ 链接行)。

6.3 构建产物与查找 libentry.so

HAP 包路径随 product / buildMode 略有不同,一般在 entry/build/ 下。libentry.so 的中间产物常出现在 entry/build/default/intermediates/ 下按 ABI 分子目录(例如带 arm64-v8aarmeabi-v7a 的路径);精确子路径会随 HarmonyOS SDK 版本变化。若在文档中写死深层路径容易过期,建议在 IDE 中 全局搜索文件名 libentry.so,或查看当次构建日志中的链接输出。

下表给出典型输出目录形态(default 为常见 product 名,请以本机为准):

ABI 常见查找线索
arm64-v8a entry/build/default/ 下搜索 arm64-v8alibentry.so

安装到真机/模拟器后,应用加载的仍是包内随 HAP 打包的 同一 libentry.so,无需手动拷贝到设备。

6.4 构建检查清单

说明
CMakeLists.txt 与第 4 节一致 absl_DIRfind_package(absl CONFIG)target_include_directories 缺一会出现头文件或链接错误。
ArkTS 编译通过 Index.d.tsnapi_init.cpp 不一致时,常见为类型检查报错或运行期缺属性。

7. 常见问题

Q1: 编译报错找不到 absl/... 头文件

  • 确认 thirdparty/abseil-cpp/<arch>/include/absl/ 存在,且 <arch> 与当前 OHOS_ARCH 一致。
  • 确认 target_include_directories(entry PRIVATE ${ABSL_ROOT}/include) 已配置(见第 4.2 节),不要只改全局 include_directories 却漏掉 ABSL_ROOT

Q2: 链接阶段 undefined reference 或大量缺符号

  • Abseil 以多个 absl::* CMake 目标组织静态库,目标之间存在传递依赖;不要随意删减 target_link_libraries 中的列表,除非你明确只保留子集并已验证链接(见第 4.4 节)。
  • 确认未混用 不同 LTS 版本错误 ABIlibabsl_*.a

Q3: find_package(absl) 失败 / Could not find absl

  • 使用 set(absl_DIR ${ABSL_ROOT}/lib/cmake/absl)find_package(absl REQUIRED CONFIG)absl_DIR 必须指向 abslConfig.cmake 所在目录lib/cmake/absl),而不是 lib/cmake 根目录。

Q4: 是否支持 x86_64 模拟器等其它架构?

当前预编译包与 CMake 分支仅处理 armeabi-v7aarm64-v8a。若需 x86_64 等,需在 oh-tpc/abseil-cpp 获取对应架构产物,并在 CMakeLists.txt 中扩展 OHOS_ARCH 分支。

Q5: ArkTS 报找不到 libentry.so 上的属性,或类型与运行不一致

  • 属性名须与 napi_init.cppnapi_define_properties 注册的字符串 完全一致(大小写敏感)。
  • entry/oh-package.json5 中依赖 "libentry.so": "file:./src/main/cpp/types/libentry" 须存在;子包内 oh-package.json5types 应指向 Index.d.ts
  • 修改 Index.d.ts 后若 IDE 仍报错,可 Invalidate Caches / 重新同步 或 Clean 后重编。

Q6: 点击「运行」后 UI 结果字符串不更新

本示例中 AbseilDemoCard 使用 @Prop 绑定 result。若把卡片放在 @Builder 里并传入字面量或未绑定的状态,可能出现 子组件不随 @State 刷新。请对照 AbseilDemoCard.ets 的用法,保持 result 与外层 @State 双向绑定(见第 6.4 节)。

Q7: 跳转到新页面提示路由失败或白屏

  • 新增 pages/XXX.ets 后必须在 entry/src/main/resources/base/profile/main_pages.jsonsrc 数组中注册。
  • 从首页进入专页时,还需在 AbseilNavigation.etsDEDICATED_NAV_NAMES 中配置 moduleId → 导航名,并与 Index.etsNavDestination.name 一致(见第 6.3 节)。

Q8: sync* 等演示卡顿、偶现失败

synchronization 相关 NAPI 会在 Native 内创建 短生命周期线程 做演示。在真机低电量、调试器附加或极端调度下,超时类演示可能比桌面更敏感;若仅偶发,可先 重试;若必现,请结合 hilog 与 Native 日志排查是否被系统限制多线程。

Q9: 日志里出现 NAPI 抛错 / runSafelyNapi 返回 ok: false

多为 参数非法Native 断言未先初始化(如部分 debugging* / log* 依赖首次 Init)。请先看 error 字符串hilog 中的 abseilDemo 标签;专页上尽量 按界面提示的顺序点击(例如先 InitializeSymbolize)。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐