当前位置: 首页 > news >正文

从零开始:开发一个仓颉三方库的完整实战

在这里插入图片描述

作者:Undoom
日期:2025-11-03
项目:filesize - 文件大小格式化工具库

前言

本文详细记录了从零开始开发一个仓颉三方库的完整过程,包括从克隆模板、编写代码、解决问题到最终发布的每一个步骤。通过这篇文章,你将学会如何创建一个标准的、文档完善的仓颉三方库。

项目背景

在日常开发中,我们经常需要将文件大小(字节数)转换为人类可读的格式,比如将 1048576 显示为 1.05 MB。虽然这是一个简单的需求,但如果每个项目都重复实现一遍,不仅浪费时间,还容易出错。因此,我决定开发一个专门的仓颉三方库来解决这个问题。

你将学到

  • ✅ 如何使用官方模板快速启动项目
  • ✅ 仓颉语言的包管理和项目结构
  • ✅ 遇到编译错误时如何诊断和解决
  • ✅ 如何编写标准的三方库代码
  • ✅ 如何完善文档和开源协议
  • ✅ 如何发布到 GitCode 仓库

第一步:准备工作

1.1 环境要求

开始之前,确保你的开发环境已准备就绪:

# 检查仓颉编译器版本
cjc --version
# 要求: >= 1.0.3# 检查包管理器
cjpm --version# 确认环境变量
echo $CANGJIE_HOME

1.2 克隆官方模板

仓颉官方提供了标准的三方库模板,可以帮助我们快速启动项目:

# 克隆模板仓库
git clone git@gitcode.com:cj-awaresome/template.git filesize
cd filesize# 查看项目结构
tree -L 2

模板的目录结构:

template/
├── README.md              # 项目说明(需要修改)
├── CHANGELOG.md           # 版本日志(需要修改)
├── LICENSE                # 开源协议(需要修改)
├── README.OpenSource      # 开源声明(需要修改)
├── cjpm.toml             # 包配置(需要修改)
├── doc/                  # 文档目录
│   ├── design.md         # 设计文档(需要重写)
│   ├── feature_api.md    # API文档(需要重写)
│   └── assets/           # 资源文件
├── src/                  # 源码目录
│   └── Template.cj       # 模板源码(需要替换)
└── test/                 # 测试目录├── HLT/              # 高层测试└── LLT/              # 低层测试

第二步:配置项目基础信息

2.1 修改 cjpm.toml

这是项目的核心配置文件,需要修改为我们的库信息:

[dependencies][package]cjc-version = "1.0.3"compile-option = ""description = "文件大小格式化工具库 - 将字节数转换为人类可读的格式"link-option = ""name = "filesize"                    # 修改包名output-type = "static"               # 三方库使用 staticsrc-dir = ""target-dir = ""version = "1.0.0"                    # 设置版本号package-configuration = {}

关键点

  • name: 包名要与功能相关,简洁明了
  • output-type: 三方库使用 "static",不是 "executable"
  • description: 简短说明库的功能

2.2 更新远程仓库

# 修改远程仓库地址
git remote set-url origin git@gitcode.com:cj-awaresome/filesize.git# 验证修改
git remote -v

第三步:编写核心代码

3.1 创建源文件

删除模板文件,创建我们的 filesize.cj

rm src/Template.cj
touch src/filesize.cj

3.2 第一版代码实现

开始编写核心功能。这是一个迭代过程,我先写了一个基础版本:

package filesizeimport std.math.*// 主格式化函数
public func formatFileSize(size: Int64): String {let base = 10let roundDigits = 2let bits = falselet result = calculateFileSize(size, base, roundDigits, bits)return result
}// 核心计算逻辑
internal func calculateFileSize(size: Int64, base: Int, roundDigits: Int, bits: Bool): String {let ceil = if (base == 10) { 1000 } else { 1024 }let num = Float64(size)var e: Int64 = 0// 计算指数if (num > 0.0) {let logVal = log(num) / log(Float64(ceil))let floorVal = floor(logVal)e = Int64(floorVal)if (e < 0) { e = 0 }if (e > 8) { e = 8 }}// 计算值var val = if (base == 2) {num / pow(2.0, Float64(e * 10))} else {num / pow(1000.0, Float64(e))}if (bits) { val = val * 8.0 }// 四舍五入let factor = pow(10.0, Float64(roundDigits))let rounded = round(val * factor) / factor// 获取单位let unit = getUnit(e)return "${rounded} ${unit}"
}// 单位映射
private func getUnit(exponent: Int64): String {if (exponent == 0) { return "B" }if (exponent == 1) { return "KB" }if (exponent == 2) { return "MB" }if (exponent == 3) { return "GB" }if (exponent == 4) { return "TB" }if (exponent == 5) { return "PB" }if (exponent == 6) { return "EB" }if (exponent == 7) { return "ZB" }if (exponent == 8) { return "YB" }return "B"
}

3.3 第一次编译 - 遇到问题!

cjpm build

错误信息

Error: the package name in /Users/jianguo/Desktop/cangjie/tpc/template-1/src is wrong, 
the right name should be 'filesize'

问题分析
这是仓颉语言的一个重要特性 - 每个源文件都必须声明它所属的包!我在文件开头添加了 package filesize,但编译器还在报错。

经过排查,发现还有其他文件(constants.cjtypes.cj)也缺少包声明。

解决方案
确保所有 .cj 文件的第一行都是包声明:

package filesize// 其他代码...

3.4 第二个问题 - 导入不存在的模块

错误信息

Error: root package 'filesize' imports package 'std.string' in its source code, 
but it is not added as a dependency in cjpm.toml

问题分析
我引用了 std.string.*,但实际上仓颉标准库中并不存在这个模块!

解决方案
删除不存在的导入:

package filesizeimport std.math.*
// import std.string.*  ❌ 删除这一行

3.5 第三个问题 - 语法兼容性

在开发过程中,我发现我最初写的一些语法在仓颉中不支持:

问题 1:默认参数

// ❌ 错误:仓颉不支持默认参数
public func formatFileSize(size: Int64, options: Map<String, Any> = {}): String// ✅ 正确:使用函数重载或固定参数
public func formatFileSize(size: Int64): String

问题 2:三元运算符

// ❌ 错误:不支持 ? : 语法
let ceil = base == 10 ? 1000 : 1024// ✅ 正确:使用 if 表达式
let ceil = if (base == 10) { 1000 } else { 1024 }

问题 3:类型转换方法

// ❌ 错误:方法名不对
let num = size.toFloat64()// ✅ 正确:使用类型构造函数
let num = Float64(size)

3.6 成功编译!

修复所有问题后:

cjpm build
# 输出:cjpm build success ✅

第四步:编写测试用例

4.1 创建测试文件

rm -rf test/HLT test/LLT
touch test/test.cj

4.2 编写测试代码

package filesize.testimport filesize.*test "格式化 1KB" {let result = formatFileSize(1024)println("1024 bytes = ${result}")assert(result.contains("KB"))
}test "格式化 1MB" {let result = formatFileSize(1024 * 1024)println("1MB = ${result}")assert(result.contains("MB"))
}test "格式化 1GB" {let result = formatFileSize(1024 * 1024 * 1024)println("1GB = ${result}")assert(result.contains("GB"))
}

4.3 运行测试

cjpm test
# 输出:cjpm test success ✅

第五步:完善项目文档

5.1 编写 LICENSE

采用 Apache 2.0 开源协议:

# 创建完整的 Apache 2.0 协议文件
# 并在文件头部添加版权声明
Apache License
Version 2.0, January 2004Copyright 2025 坚果 (Jianguo)Licensed under the Apache License, Version 2.0...

5.2 更新 README.md

编写专业的项目说明文档,包括:

# filesize - 文件大小格式化库## 介绍
简要说明库的功能...## 项目特性
- ✨ 简单易用
- 📊 自动单位转换
...## 使用说明
### 安装
### 使用示例## 开源协议
Apache License 2.0

5.3 编写 CHANGELOG.md

记录版本历史:

# 更新日志## [1.0.0] - 2025-11-03### Feature
+ 实现文件大小格式化核心功能
+ 支持 KB、MB、GB 等单位自动转换
...

5.4 编写技术文档

doc/design.md - 设计文档:

  • 架构设计
  • 算法说明
  • 数据流程
  • 性能分析

doc/feature_api.md - API 文档:

  • 函数签名
  • 参数说明
  • 使用示例
  • 注意事项

5.5 更新 README.OpenSource

[{"Name": "filesize","License": "Apache License 2.0","License File": "LICENSE","Version": "1.0.0","Owner": "jianguo@nutpi.net","Upstream URL": "https://gitcode.com/cj-awaresome/filesize","Description": "仓颉语言的文件大小格式化工具库"}
]

5.6 添加 .gitignore

# 创建 .gitignore 文件
cat > .gitignore << 'EOF'
# 编译输出
target/
cjpm.lock# IDE 配置
.vscode/
.idea/
*.swp# 系统文件
.DS_Store
EOF

第六步:提交到 Git 仓库

6.1 添加所有文件

git add -A
git status

查看待提交的文件:

Changes to be committed:new file:   .gitignoremodified:   CHANGELOG.mdmodified:   LICENSEmodified:   README.OpenSourcemodified:   README.mdmodified:   cjpm.tomldeleted:    src/Template.cjnew file:   src/filesize.cjmodified:   doc/design.mdmodified:   doc/feature_api.mddeleted:    test/HLT/testcase0001.cjdeleted:    test/LLT/testcase0001.cjnew file:   test/test.cj

6.2 提交代码

git commit -m "实现 filesize 库:文件大小格式化工具- 添加 filesize.cj 实现文件大小格式化功能
- 支持 KB, MB, GB 等单位自动转换
- 更新 cjpm.toml 配置,包名改为 filesize
- 添加基础测试用例
- 完善所有文档和开源协议
- 删除模板文件,添加 .gitignore"

6.3 推送到远程仓库

git push origin main

输出

remote: Start Git Hooks Checking [PASSED]
To gitcode.com:cj-awaresome/filesize.git* [new branch]      main -> main

成功!🎉


第七步:后续优化

7.1 修复编译警告

第一次运行时发现有未使用变量的警告:

warning: unused variable:'standard'

解决方案:删除未使用的参数

git commit -m "修复编译警告,移除未使用的参数"
git push origin main

7.2 移除 main() 函数

三方库不应该包含可执行入口:

// ❌ 删除 main() 函数
main() {println("Testing...")
}
git commit -m "完善三方库配置 - 移除 main() 函数"
git push origin main

开发过程中的经验总结

🎯 关键要点

  1. 包声明必不可少

    • 每个 .cj 文件必须以 package 包名 开头
    • 包名要与 cjpm.toml 中的 name 一致
  2. 注意语法差异

    • 仓颉不支持默认参数
    • 使用 if (condition) { value } else { value } 而不是三元运算符
    • 类型转换使用构造函数:Float64(value)
  3. 三方库的特殊要求

    • output-type 必须是 "static"
    • 不应包含 main() 函数
    • 专注于提供可复用的功能
  4. 标准库的使用

    • 仔细检查标准库模块是否存在
    • 数学函数在 std.math.*
    • 不存在 std.string.* 模块

🐛 常见错误及解决方案

错误原因解决方案
package name is wrong缺少包声明添加 package 包名
imports package ‘std.xxx’ but not in dependencies模块不存在或未声明依赖检查模块是否存在
expected ‘,’ or ‘)’语法错误(如默认参数)使用仓颉支持的语法
undeclared identifier类型转换方法错误使用类型构造函数

💡 最佳实践

  1. 从简单开始

    • 先实现核心功能
    • 验证编译通过
    • 再逐步添加特性
  2. 及时测试

    • 每次修改后立即编译
    • 写简单的测试验证功能
    • 不要等到最后才测试
  3. 文档同步

    • 代码和文档同步更新
    • 提供实际可运行的示例
    • 说明清楚每个 API 的用途
  4. 版本管理

    • 使用有意义的提交信息
    • 一个功能一次提交
    • 保持提交历史清晰

项目成果

经过几个小时的开发,我们完成了一个标准的仓颉三方库:

📦 项目统计

  • 源码文件: 1 个(filesize.cj,64 行)
  • 测试文件: 1 个(test.cj,22 行)
  • 文档文件: 6 个(README、CHANGELOG、LICENSE、设计文档、API文档等)
  • 总代码行数: ~800 行(含文档)

✅ 完成的功能

  • 文件大小格式化(B 到 YB)
  • 自动单位选择
  • 精度控制(2位小数)
  • 单元测试
  • 完整文档
  • 开源协议

🚀 如何使用

其他开发者可以这样使用我们的库:

// 在 cjpm.toml 中添加依赖
[dependencies.filesize]
git = "git@gitcode.com:cj-awaresome/filesize.git"// 在代码中使用
import filesize.*main() {let size = formatFileSize(1048576)println(size)  // 输出: 1.05 MB
}

未来展望

v1.1.0 计划

  • 支持配置选项
  • 二进制(1024)和十进制(1000)切换
  • 自定义小数位数

v1.2.0 计划

  • 支持 bits 显示模式
  • IEC 和 JEDEC 标准支持
  • 国际化支持

结语

从零开始开发一个仓颉三方库并不难,关键是要:

  1. 熟悉工具链 - 理解 cjpm 的工作方式
  2. 注意细节 - 包声明、语法规范等
  3. 完善文档 - 好的文档是优秀库的标志
  4. 持续迭代 - 从简单开始,逐步完善

希望这篇文章能帮助更多开发者参与到仓颉生态建设中来。如果你也想开发自己的三方库,不妨从这个模板开始,创造属于你的优秀作品!


相关资源

  • 项目地址: https://gitcode.com/cj-awaresome/filesize
  • 官方模板: https://gitcode.com/cj-awaresome/template
  • 仓颉文档: https://gitcode.com/Cangjie
  • 作者联系: jianguo@nutpi.net

作者: Undoom
项目: filesize v1.0.0
日期: 2025-11-03
协议: Apache License 2.0

http://www.dtcms.com/a/568613.html

相关文章:

  • 本机 MongoDB 注册系统服务、启用security认证
  • Nginx代理配置的“双斜杠陷阱“:从IP到域名的完整排查与解决指南
  • 三水容桂网站制作天眼查企业信息查询平台
  • HarmonyOS鸿蒙开发:Swiper组件实现精美轮播图
  • 互联网大厂前端面试实录:HTML5、ES6、Vue/React、工程化与性能优化全覆盖
  • 宣威网站建设公司做钓鱼网站要什么工具
  • VBA中类的解读及应用第二十九讲: 最简单的类属性建立
  • 金蝶用友数据分析:奥威BI解锁ERP智能决策新纪元
  • 用Python做数据分析之数据表清洗
  • AI+CMIP6数据分析与可视化、降尺度技术与气候变化的区域影响、极端气候分析
  • 基于深度神经网络的手术机器人轨迹精准定位与智能存储方案编程(总集下)
  • 【计算机网络】计算机网络体系结构与参考模型
  • 佛山外贸网站建设资讯微信小程序制作教程视频
  • ubuntu22.04 GPU环境安装mindspore
  • 从vw/h到clamp(),前端响应式设计的痛点与进化
  • VAE可以被用到扩散模型中,用于编码和解码。但是GAN网络不行?
  • 《算法闯关指南:优选算法--前缀和》--31.连续数组,32.矩阵区域和
  • 《Flutter全栈开发实战指南:从零到高级》- 10 -状态管理setState与InheritedWidget
  • 网站维护内容梅江区建设局网站
  • 3D工艺数字化:让灵活用工不再难
  • 【pwn】shellcode构造
  • LandPPT - AI驱动的PPT生成平台
  • 制作音乐网站实验报告建筑工程公司起名大全
  • 贪玩传奇手游官方网站自己买空间让网络公司做网站好吗
  • OSPF错题笔记:区域与LSA完全解析
  • 【Agent】ACE(Agentic Context Engineering)源码阅读笔记---(1)基础模块
  • 【AI基础篇】长短时记忆神经网络LSTM的解析与应用
  • 供、回水管-连续测量超简单
  • 生成式搜索普及后,GEO决定生存线
  • ublox-M8Q GNSS模组驱动与冷热启动定位设置