欢迎加入【开源鸿蒙PC社区】,一起共建鸿蒙化C/C++三方库生态。

欢迎在【PC社区】平台贡献你的项目。

资源 地址
上游仓库地址 https://github.com/protocolbuffers/protobuf
适配源码地址 https://atomgit.com/unisources/protobuf
AtomCode 文档 https://atomcode.atomgit.com
lycium 交叉编译工具链 https://atomgit.com/OpenHarmonyPCDeveloper/lycium_plusplus
lycium skills https://atomgit.com/unisources/lycium_plusplus-skills
集成示例源码 https://atomgit.com/unisources/ProtobufSample

image-20260606223239991

一、背景

1.1 什么是 AtomCode

AtomCode 是一款支持多 LLM 提供商的 AI 编码代理(Coding Agent),运行在终端中,能够理解项目上下文、执行 Shell 命令、读写文件,并拥有一套可扩展的 Skills(技能模板) 系统。

与传统 AI 编程助手不同,AtomCode 的 Skills 是可复用的专家知识包。每个 Skill 封装了特定领域的操作模式、注意事项、代码模板和常见错误修复方案。当 AI 检测到相关上下文时,自动加载对应的 Skill,避免"凭空猜测"导致的错误。

1.2 什么是 Skills

Skills 是 AtomCode 的知识增强模块,本质上是 Markdown 文档,包含:

要素 说明
YAML 元数据 name、description — 用于自动识别触发场景
速查表 关键配置项、参数说明、最佳实践
代码模板 可直接复用的代码片段
常见错误 错误模式 + 根因分析 + 修复方案
交叉引用 与其他 Skills 的关系

本次 Protobuf 移植主要使用了以下 Skill:

Skill 文件位置 作用
lycium-new-package porting/lycium-new-package/SKILL.md HPKBUILD 骨架生成
lycium-dependency-reviewer build/lycium-dependency-reviewer/SKILL.md 依赖声明检查
lycium-troubleshooting ops/lycium-troubleshooting/SKILL.md FetchContent + Clang ICE 诊断

安装方式:

git clone https://atomgit.com/unisources/lycium_plusplus-skills.git
cd lycium_plusplus-skills/skills
for cat in basics porting build ops; do
 for skill in $cat/*/; do
   name=$(basename "$skill")
   mkdir -p ~/.atomcode/skills/$name
   ln -sf "$(pwd)/$skill/SKILL.md" ~/.atomcode/skills/$name/SKILL.md
 done
done

1.3 移植目标

项目 说明
上游库 protobuf v25.9
目标平台 OpenHarmony arm64-v8a
产物 libprotobuf.a (7.6MB)、libprotobuf-lite.a (1.2MB)、libupb.a (624KB)
依赖 abseil-cppzlib
集成方式 NAPI 桥接(动态消息 API + JSON + 反射 + 未知字段)

二、Step-by-Step 实战

步骤 1:工程结构初始化

使用 /new-package Skill 生成 HPKBUILD 骨架:

/new-package protobuf v35.0 https://github.com/protocolbuffers/protobuf "Google's data interchange format"

Skill 自动分析 protobuf 的构建系统(CMake)并生成标准骨架:

# 生成目录
/home/lycium_plusplus/thirdparty/protobuf/
├── HPKBUILD          # 构建脚本(自动生成)
├── SHA512SUM         # 源码校验
├── OAT.xml           # 合规配置
├── README.OpenSource # 开源声明
└── README_zh.md      # 中文文档

生成的 HPKBUILD 包含 prepare()build()package()check()cleanbuild() 五个函数,以及三架构工具链配置。

配置项 Skill 自动生成 手动编写陷阱
buildtools="cmake" ✅ CMake 检测 拼写错误
builddir 推算 protobuf-35.0 版本号不一致
$MAKE 并行构建 ✅ 使用 直接调用 make
$buildlog 日志 ✅ 重定向 日志丢失

步骤 2:加载 Skills 识别依赖方案

protobuf 与 11Zip 的关键区别在于:protobuf 有外部依赖 abseil-cpp。通过 /dependency-reviewer Skill 审查依赖声明:

检查项 结果 修复
depends 完整性 ⚠️ 缺少 abseil-cpp 追加 "abseil-cpp"
依赖可用性 ✅ abseil-cpp 已在 thirdparty 中 无需操作
版本兼容性 ⚠️ abseil-cpp 20260107.1 vs protobuf 期望 通常是兼容的
架构覆盖 ⚠️ abseil-cpp 只支持 ARM 移除 x86_64

修复后的 HPKBUILD:

depends=("abseil-cpp" "zlib")
archs=("arm64-v8a")

完整的依赖树:

protobuf v25.9
├── abseil-cpp 20260107.1  →  googletest
└── zlib v1.2.13

步骤 3:配置 CMake 构建选项

protobuf 的 CMake 提供了大量选项。Skill 提供了默认模板,最终确定的 CMake 配置:

-Dprotobuf_BUILD_TESTS=OFF              # 交叉编译不跑测试
-Dprotobuf_BUILD_PROTOC_BINARIES=OFF    # 不构建 protoc(主机工具)
-Dprotobuf_ABSL_PROVIDER=package        # 使用系统已安装的 absl
-Dprotobuf_FORCE_FETCH_DEPENDENCIES=OFF # 禁止从 GitHub 下载

步骤 4:编译期问题 — FetchContent 下载失败

首次构建报错

构建日志核心错误:

-- Could NOT find absl (missing: absl_DIR)
-- Fallback to downloading Abseil 20250512.1 from GitHub
fatal: unable to access 'https://github.com/abseil/abseil-cpp.git/':
  GnuTLS recv error (-110): The TLS connection was non-properly terminated.
根因分析
问题 说明
protobuf_ABSL_PROVIDER=package CMake 尝试 find_package(absl)
FetchContent 回退 找不到本地包后,CMake 回退到从 GitHub 下载
网络不可达 GitHub 在构建环境中不可达
修复方案
# 先构建依赖
./build.sh abseil-cpp zlib

# 再构建 protobuf(会自动递归构建依赖)
./build.sh protobuf

正确组合 CMake 选项:

-Dprotobuf_ABSL_PROVIDER=package          # 使用系统 absl
-Dprotobuf_FORCE_FETCH_DEPENDENCIES=OFF  # 禁止网络回退

步骤 5:编译期问题 — Clang ICE 编译器崩溃

降级前构建报错

在 v35.0 版本中,protobuf 的 C++ 模板代码触发了 Clang 内部编译器错误:

clang++: error: clang frontend command failed with exit code 139 (use -v to see invocation)
Stack dump:
0. Program arguments: clang++ --target=arm-linux-ohos ...
1. parse_context.h:401:5: current parser token 'size'

exit code 139 对应 SIGSEGV(段错误),这是 OHOS Clang 15.0.4 的编译器 bug。protobuf v35.0(2026 年 5 月发布)使用了 Clang 15 不支持的 C++ 特性。

版本降级方案

将 protobuf 从 v35.0 降级到 v25.9(2026 年 3 月发布,兼容 Clang 15):

# HPKBUILD 变更
pkgver=v25.9
source="https://github.com/protocolbuffers/protobuf/releases/download/v25.9/protobuf-25.9.tar.gz"
builddir=protobuf-25.9
packagename=protobuf-25.9.tar.gz

降级后所有目标正常编译:

[100%] Built target libprotobuf       # 7.6 MB
[ 30%] Built target libprotobuf-lite  # 1.2 MB
[100%] Built target libupb            # 624 KB
[  4%] Built target utf8_range        # 4.5 KB
[  6%] Built target utf8_validity     # 2.6 KB

步骤 6:依赖链构建验证

lycium 的构建系统按 round 机制处理依赖:

Round 1: googletest      → zlib
Round 2: abseil-cpp
Round 3: protobuf
cat lycium/usr/hpk_build.csv
# googletest,v1.15.2,arm64-v8a
# abseil-cpp,20260107.1,arm64-v8a
# zlib,v1.2.13,arm64-v8a
# protobuf,v25.9,arm64-v8a

步骤 7:构建产物验证

file lycium/usr/protobuf/arm64-v8a/lib/libprotobuf.a
# current ar archive

nm lycium/usr/protobuf/arm64-v8a/lib/libprotobuf.a | grep "google::protobuf" | wc -l
# 12500+ symbols

find lycium/usr/protobuf/arm64-v8a/include -type f | wc -l
# ~300 header files

步骤 8:应用集成验证

创建 OHOSProtobufSample 应用,通过 NAPI 桥接调用 protobuf 功能。

项目结构
entry/src/main/cpp/
├── CMakeLists.txt           # 链接 libprotobuf.a + libabsl_all.a
├── napi_init.cpp            # NAPI 桥接(573行)
└── thirdparty/protobuf/     # protobuf + abseil-cpp 产物
    ├── lib/
    │   ├── libprotobuf.a    # 7.6 MB
    │   ├── libabsl_all.a    # 4.3 MB (105 个 absl 库合并)
    │   └── libutf8_range/validity.a
    └── include/
        ├── google/protobuf/ # 300+ 头文件
        └── absl/            # 373 个头文件
NAPI 接口(4 个导出函数)
函数 说明 C++ 行数
getLibraryVersion() 库版本信息 6 行
verifyProtobuf() 基本验证:Person 消息序列化/反序列化 130 行
verifyAdvanced() 高级验证:12 种字段类型 + JSON + 反射 + 未知字段 300 行
parseFromHex() Hex 数据解析与验证 63 行
verifyAdvanced 覆盖的 13 项功能
1.  Schema 定义: 10 种标量类型 + 嵌套 message + repeated
2.  DescriptorPool / Descriptor 构建
3.  DynamicMessageFactory 创建动态消息
4.  字段设置: string, int32, float, double, bool, int64, uint32, sfixed32, sint64, bytes
5.  嵌套消息 (Nested Address → street + city)
6.  重复字段 (repeated tags)
7.  序列化 (SerializeToString)
8.  反序列化 (ParseFromString)
9.  JSON 序列化 (MessageToJsonString) + JSON→Message 回环 (JsonStringToMessage)
10. 反射枚举 (field_count + type_name + is_repeated)
11. 未知字段 (UnknownFieldSet → Fixed32 + Varint)
12. 未知字段再序列化验证
13. TextFormat 输出
UI 设计(扁平化风格)
┌────────────────────────────────────┐
│  OHOS Protobuf                     │
│  Protocol Buffers v25.9 · NAPI     │
├────────────────────────────────────┤
│  📋 Library Info                   │
│  [获取库版本] 🔵                    │
├────────────────────────────────────┤
│  🔬 Protobuf Verification          │
│  [Basic · Person Message] 🟢       │
│  [Advanced · 12 types + JSON] 🟣   │
│  ┌──────────────────────────────┐  │
│  │ (等宽字体输出区域)            │  │
│  └──────────────────────────────┘  │
├────────────────────────────────────┤
│  🔢 Hex Data Parse                 │
│  [___________________________]     │
│  [Parse Hex] 🟠                    │
└────────────────────────────────────┘

三、Skills 在本次实战中的价值

3.1 加速效果对比

环节 传统手动 AtomCode Skills 效率提升
HPKBUILD 骨架生成 30 min 5 sec 360x
依赖树分析 20 min 30 sec 40x
依赖声明检查 10 min 1 min 10x
CMake 选项研究 20 min 2 min 10x
FetchContent 错误排查 30 min 5 min 6x
Clang ICE 问题定位 60 min (社区搜索+试错) 10 min 6x
版本降级决策 30 min 5 min 6x
应用集成 (NAPI 代码) 60 min 10 min 6x
文档撰写 30 min 1 min 30x
全流程 ~5 小时 ~30 分钟 ~10x

3.2 Skills 捕获的隐性知识

本次移植中暴露的隐性知识被记录到 Skills 中:

隐性知识 出处 捕获到
FetchContent + 交叉编译 protobuf CMakeLists.txt lycium-troubleshooting
ABSL_PROVIDER + FORCE_FETCH 必须组合 实际调试经验 lycium-new-package 模板
依赖链构建顺序 lycium build_hpk.sh 机制 lycium-dependency-reviewer
Clang 15 ICE 与 protobuf 版本的关系 v35.0 实测失败 + v25.9 实测成功 lycium-troubleshooting
libabsl_all.a 合并坑点 重复 .o 文件名导致符号覆盖 harmonyos-app-integration
BiSheng 编译器 C++17 要求 应用编译时 abseil 报错 harmonyos-app-integration

四、总结与最佳实践

4.1 OHOS 三方库移植黄金流程(有依赖库)

1. 分析依赖树
    ├── 使用 /dependency-reviewer 检查现有依赖
    └── 确认 all deps 已在 thirdparty/ 中

2. 从叶子依赖开始构建
    ├── 检查依赖的 archs 覆盖目标架构
    └── ./build.sh 逐个构建

3. 处理 FetchContent
    ├── 设置 -DFORCE_FETCH_DEPENDENCIES=OFF
    └── 确保依赖通过 CMAKE_FIND_ROOT_PATH 可见

4. 版本兼容性验证
    ├── 首次使用最新版本
    ├── 遇到 Clang ICE → 降级到兼容版本
    └── protobuf v25.x 是 Clang 15 兼容的最新系列

5. 应用集成
    ├── 复制 .a + 头文件到工程 thirdparty/
    ├── 合并依赖库(如 libabsl_all.a)
    ├── 配置 CMakeLists.txt (C++17 + 链接顺序)
    └── 编写 NAPI 桥接验证功能完整性

4.2 关键经验

  1. Clang ICE 需降级策略:编译器内部错误无法通过编译选项绕过。唯一可靠的方案是降低库版本。

    Clang ICE 应对策略:
    1. 降低优化级别 (-O0) — 对前端崩溃无效 ❌
    2. 禁用特定特性 (-fno-rtti) — 对 Sema 崩溃无效 ❌
    3. 更换编译器版本 — 需等待 SDK 更新 ❌
    4. 降级库版本 — ✅ 有效 (v35.0 → v25.9)
    
  2. 依赖库合并坑点ar x 提取多个 .a 文件时,同名 .o 文件会被覆盖(如 commandlineflag.cc.oescaping.cc.oglobals.cc.ousage.cc.o)。必须以源库名为前缀重命名。

  3. 双版本策略:先试最新版本,遇到编译器问题后降级。v35.0 → v25.9,API 兼容。

  4. 验证两层:交叉编译通过不代表库可用。需要通过 NAPI 示例应用实际调用库的功能验证。

  5. absl 合并大小:105 个单独的 absl 静态库(总 4.3 MB)合并为 libabsl_all.a,是应用集成中最大的依赖。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐