仓颉共建之旅
从零开始,把 Java 开源库
dd-plist完整移植为仓颉库plist4cj的全过程实录。本系列如实记录我参与 「仓颉三方库共建计划」 的完整历程——从读懂活动规则、搭建环境、逐模块翻译,到两轮 PR 审核整改、发布仓颉中心仓。既是过程记录,也是一份可复用的移植参考。
这个系列是关于什么的?
2026 年,我报名参加了华为仓颉(Cangjie)生态的 「仓颉三方库共建计划」,认领了 dd-plist——一个读写苹果 .plist 配置文件的 Java 开源库。
我从零开始学习仓颉语言,一边学一边做,把整个移植过程完整记录下来,整理成这个 31 篇的系列。每一篇都对应移植过程中的一个真实阶段:遇到的问题、分析的思路、最终的解法。
适合谁读
- 想参与「仓颉三方库共建计划」、但不了解完整流程的开发者
- 想了解如何把一个 Java 库系统性移植为仓颉库的开发者
- 对仓颉语言感兴趣、希望通过真实项目上手的读者
- 💻 环境说明:系列中的环境搭建与命令均基于 Windows
文章目录
第一部分:准备篇(第 1-5 篇)
| 篇章 | 标题 | 核心内容 |
|---|---|---|
| 第 1 篇 | 读懂「仓颉三方库共建计划」 | 这个活动到底在做什么、我要做什么、完整流程 |
| 第 2 篇 | 搭建仓颉开发环境 | 怎么在 Windows 上装好仓颉、怎么验证装成功了 |
| 第 3 篇 | 认识 dd-plist:它到底是个什么库 | plist 是什么、这个库解决什么问题 |
| 第 4 篇 | 通读源码,规划移植路线 | 怎么读懂一个陌生代码库、按什么顺序翻译 |
| 第 5 篇 | 搭建工程,翻出第一段能跑的代码 | 用 cjpm 搭工程、仓颉包与目录规则、翻译第一个模块并 build/test 跑通 |
第二部分:叶子类型篇(第 6-11 篇)
| 篇章 | 标题 | 核心内容 |
|---|---|---|
| 第 6 篇 | 推代码上远端,翻译 NSObject 与 NSString | 该推哪个分支、大类怎么拆着翻、翻译前先查 API、用方法替代反射 |
| 第 7 篇 | 翻译 NSNumber:被关键字、NaN、溢出教育的一课 | type 关键字冲突、match 常量坑、数值转换抛异常、std.convert 解析 |
| 第 8 篇 | 翻译 NSData:字节数组与 Base64 的双面人生 | 字节数组构造、Base64 编解码、文件读取、GnuStep 扩展 |
| 第 9 篇 | 翻译 NSDate:时间格式的大杂烩 | XML/GnuStep 双格式解析、DateTime 构造、跨格式兼容 |
| 第 10 篇 | 翻译 UID:小类也有大坑 | BigInteger 替代方案、字节填充、十六进制输出 |
| 第 11 篇 | 翻译 NSNull:最简单的类,最不简单的单例 | wrap/unwrap 模式、单例实现、序列化抛异常 |
第三部分:容器类型篇(第 12-14 篇)
| 篇章 | 标题 | 核心内容 |
|---|---|---|
| 第 12 篇 | 翻译 NSArray:ArrayList 的仓颉翻译 | 容器类型移植、NSObject 比较与克隆、仓颉 sort 用法 |
| 第 13 篇 | 翻译 NSDictionary:HashMap 在仓颉里怎么活 | HashMap 替代、containsValue 五种重载、CDATA 输出 |
| 第 14 篇 | 翻译 NSSet:没有 HashSet 的日子 | 手动去重、ArrayList+线性查找、序列化委托 NSArray |
第四部分:工具与写出器篇(第 15-23 篇)
| 篇章 | 标题 | 核心内容 |
|---|---|---|
| 第 15 篇 | 翻译 BinaryLocationInformation | 位置信息子类、offset/id 字段 |
| 第 16 篇 | 翻译 ASCIILocationInformation | line/column 追踪 |
| 第 17 篇 | 翻译 ParsedObjectStack:解析期的对象栈 | 栈结构、对象 ID 去重 |
| 第 18 篇 | 翻译 ByteOrderMarkReader:BOM 检测 | UTF-8/16/32 BOM 识别、多字节读取 |
| 第 19 篇 | 翻译 XMLPropertyListWriter | XML 输出、缩进控制、CDATA 处理 |
| 第 20 篇 | 翻译 ASCIIPropertyListWriter | ASCII 格式输出、GnuStep 扩展 |
| 第 21 篇 | 翻译 BinaryPropertyListWriter:最复杂的写出器 | 对象 ID 分配、交叉引用、偏移量表、trailer 写入 |
| 第 22 篇 | 翻译 XMLLocationInformation | XPath 位置追踪 |
| 第 23 篇 | 翻译 PropertyListParser:格式自动检测 | BOM 检测、magic bytes 分派、格式常量 |
第五部分:解析器篇(第 24-26 篇)
| 篇章 | 标题 | 核心内容 |
|---|---|---|
| 第 24 篇 | 翻译 BinaryPropertyListParser:二进制解析 | 二进制格式头解析、对象表遍历、偏移量计算 |
| 第 25 篇 | 翻译 XMLPropertyListParser:手写 XML 递归下降 | 仓颉无 XML DOM、手写逐字符解析器、标签状态机 |
| 第 26 篇 | 翻译 ASCIIPropertyListParser:手写 ASCII 递归下降 | 无引号值类型推断、转义序列状态机、GnuStep 扩展 |
第六部分:收尾篇(第 27-31 篇)
| 篇章 | 标题 | 核心内容 |
|---|---|---|
| 第 27 篇 | 收尾:双版本验证、文档补齐与 PR 提交 | SDK 共存解压、cjpm 缓存清理、bundle 打包、OpenSSL 兼容性、文档规范、PR 模板 |
| 第 28 篇 | PR 审核整改:把测试覆盖率从 64% 提到 81% | cjcov 工具链、@OverflowWrapping 溢出修复、双版本覆盖率报告、只统计生产源码 |
| 第 29 篇 | 数据类覆盖率攻坚:从 81% 冲到 97% | 精准补测方法、两个 UTF-8 BOM 截断 Bug、as 不是上转型、NSDate 喂 Inf/NaN 死循环 |
| 第 30 篇 | 第二轮审核整改:16 个问题点、2 个一票否决,到 PR 合并 | 文档即契约、统一入口补齐、上游回归测试揪出 3 个真 Bug、复审说明怎么写 |
| 第 31 篇 | 发布到仓颉中心仓:cjlint 的突袭与一个缺失的 DLL | cjpm bundle/publish 流程、cjlint MANDATORY 三类违规修法、OpenSSL 3 DLL 硬编码依赖、发布令牌安全 |
项目成果
经过 31 篇文章的完整记录,plist4cj 项目已全部完成:
| 指标 | 数据 |
|---|---|
| 移植模块 | 13 个类 + 3 个解析器 + 3 个写出器 |
| 单元测试 | 309/309 PASSED |
| 行覆盖率 | 97.26%(2875/2956,仅生产源码) |
| LTS 1.0.5 验证 | ✅ 309/309 |
| STS 1.1.3 验证 | ✅ 309/309 |
| PR 状态 | ✅ 两轮审核整改后已合并 |
| 中心仓发布 | ✅ plist4cj 1.0.1 已上架,plist4cj = "1.0.1" 即可引用 |
| 共建文章 | 31 篇 |
| 当前状态 | 🟢 项目主线完结 |
一句话总结
「三方库共建」= 把一个用其他语言写好的开源库,用仓颉语言重新实现一遍,丰富仓颉的生态。
我认领的
dd-plist是一个处理苹果.plist配置文件的 Java 库,我的任务就是把它变成仓颉版的plist4cj。
本系列主线已完结。如果对你有帮助,欢迎分享给想参与仓颉共建的朋友。