rack 是 RGC 的包管理器,用 RGC 自己编写。它管理 RGC 项目的完整生命周期:新建项目、安装依赖(含传递依赖解析与完整性校验)、锁文件、构建与运行、发布与搜索。
这篇教程从一个真实的示例包出发,带你走一遍完整流程:发布 → 新建项目 → 安装依赖 → 查看依赖树 → 构建运行 → 发布自己的包。所有命令都在仓库中验证过,可以直接复制运行。
1. 准备
rack 二进制在仓库 rack/target/bin/rack(已构建)。也可以自行构建:
cd rack && ./tests/bootstrap.sh
# -> target/bin/rack
rack 构建项目时需要调用 rgc 编译器,通过 RGC 环境变量指定:
export RGC=/path/to/RGLite/build/rgc
验证:
rack --version
# rack 0.3.0 (RGC)
2. 发布示例包到本地注册表
rack 使用本地注册表(默认 $HOME/.rack/registry)。先把仓库里两个示例包发布进去:
cd rack/examples/mathx
rack publish
cd ../calcx
rack publish
输出:
Published [email protected] -> $HOME/.rack/registry
Published [email protected] -> $HOME/.rack/registry
mathx是一个数学工具模块,提供add/mul/fib/square_sum;calcx依赖[email protected],提供double_add/fib_sq。
3. 新建项目
rack new demo && cd demo
生成:
demo/
├── .gitignore # 忽略 target/ 与 a.out
├── main.rg # 项目入口
└── rack.toml # 清单
默认 main.rg:
# demo — rack 项目入口
def main() {
print("hello from demo")
}
rack.toml 记录包元数据:
[package]
name = "demo"
version = "0.1.0"
entry = "main.rg"
4. 安装依赖
把 main.rg 改成使用 calcx:
import calcx
def main() -> int {
print(double_add(2, 3))
return 0
}
安装:
rack install calcx
输出:
resolved calcx -> [email protected]
+ [email protected]
+ [email protected]
Installed 2 package(s)
rack 自动完成传递依赖解析:calcx 依赖 mathx,所以 mathx 一起被安装。
5. 查看依赖树
rack tree
[email protected]
└── [email protected]
└── [email protected]
6. 构建并运行
rack run
built: ./target/bin/demo
10
此时项目布局:
demo/
rack.toml # 清单(rack 维护,手改亦可)
rack.lock # 锁文件:依赖闭包
main.rg # 入口
target/
deps/ # 已安装依赖模块 .rg(缓存,可随时重建)
build/ # 构建暂存区(入口 + 全部依赖,每次构建前清空)
bin/demo # 构建产物
7. 锁文件 rack.lock
install 会把解析后的完整依赖闭包写入 rack.lock(rack 维护、随项目入库,勿手改):
# rack.lock — 依赖闭包锁文件(rack 维护,勿手改;随项目入库)
[lock.calcx]
version = "0.1.0"
checksum = "130f4c9b…"
dependencies = ["mathx"]
[lock.mathx]
version = "0.2.0"
checksum = "b1dfcea6…"
dependencies = []
version:解析后的精确版本;checksum:publish时记录的模块文件 sha256,install时先校验再拷贝,build前也会校验target/deps缓存是否被篡改;dependencies:该包的直接依赖(用于依赖剪枝与完整性校验)。
8. 常用命令
| 命令 | 作用 |
|---|---|
rack new |
新建项目骨架(rack.toml + main.rg + .gitignore) |
rack init [name] |
在当前目录初始化 rack 项目 |
rack install |
安装依赖及其全部传递依赖,写入清单与锁文件 |
rack update |
把全部直接依赖重解析到最新版,重写锁文件 |
rack remove |
移除依赖,并按依赖边剪掉孤儿传递依赖 |
rack build |
校验锁文件 → 暂存依赖到 target/build → 调用 rgc 编译 |
rack run [-- |
构建并运行,参数原样转发给程序 |
rack tree |
打印依赖树 |
rack list |
显示清单与依赖安装状态 |
rack clean |
清除 target/build 与 target/bin(保留 target/deps 缓存) |
rack publish |
把 与 rack.toml 发布到本地注册表 |
rack search [关键字] |
在注册表中按包名搜索,显示最新版与描述 |
rack registry |
显示本地注册表路径 |
运行参数透传
rack run -- <参数> 会把参数原样交给程序,程序用内建 args() 读取(含程序名,行为同 Python 的 sys.argv):
rack run -- hello world
def main() -> int {
argv = args()
print("argc =", argv.len())
for a in argv {
print("arg:", a)
}
return 0
}
9. 依赖解析:版本冲突与环检测
rack 对依赖闭包做完整性保证:
- 版本冲突:同一包被两个依赖 pin 到不同精确版本时,直接报错拒装:
error: version conflict on `common`: pinned 1.0.0, but `beta` requires 2.0.0
- 依赖环:
A -> B -> A这样的循环依赖会被检测并拒绝:
error: dependency cycle: cycleA -> cycleB -> cycleA
这两种情况都发生在 install 的解析阶段,不会把半成品写进清单或锁文件。
10. 发布自己的包
发布一个包只需要两个文件:模块代码 和清单 rack.toml。
mypkg.rg:
public def add(a: int, b: int) -> int {
return a + b
}
rack.toml:
[package]
name = "mypkg"
version = "0.1.0"
entry = "mypkg.rg"
发布并搜索验证:
cd mypkg
rack publish
rack search mypkg
在另一个项目里安装使用:
rack new usemypkg && cd usemypkg
# 修改 main.rg:import mypkg ...
rack install mypkg
rack run
11. 构建钩子与链接参数
有些项目需要在编译前做原生预处理,或链接额外的库。rack.toml 支持 [build] 段:
[build]
prebuild = "bash tools/llvm-shim.sh" # 编译前执行(cwd = 项目根目录)
link-args-file = "target/build/link-args" # 文件内容作为 rgc --link-args
RGC 编译器项目本身就是一个 rack 项目(src/rack.toml):prebuild 负责编译内嵌 LLVM 的后端 shim,link-args-file 把 shim 与 LLVM 静态库的链接参数传给 rgc。
12. 下一步
rack 以 Apache 2.0 协议开源。欢迎在 GitHub 提 Issue、贡献代码。