1. KPM 是什么
KPM(KCL Package Manager, KCL 包管理器)是 KCL 语言的程序包管理器。
KPM 由两个主要部分组成:
- 用于发布和下载程序包的 CLI(命令行界面)工具。
- 托管 KCL 程序包的在线存储库。
为了更直观地解释,我们可以将在线存储库视为一个物流集散中心,该中心从卖方(kpm 包裹的作者)那里接收货物的包裹,并将这些货物分发给买方(kpm 包裹的用户)。
为了促进此过程,kpm 物流集散中心雇佣了一群勤劳的快递员(kpm CLI),他们将被分配给每个 KCL 用户作为私人助理。因此,KCL 程序所依赖的其他的 KCL 程序包会如下传递给 kcl 开发或者使用人员:
KCL 开发人员也可以将自己开发的 KCL 程序包发布到集散中心:
2. kpm 的诞生
在没有 Kpm 的时代,KCL 的使用者首先就要面对一个很严重的问题。
第一种解决方案,没有自己造呗。
这种方案虽然行得通,但是,投入的成本太大,周期太长,不现实。
第二种解决方案,搬去物流中心住,里面啥都有。
搬去物流中心可以省去重复造轮子的麻烦,但是这个方案也存在很明显的问题,在实际的开发过程中,需要借助类似云端开发的手段,所有人在一个类似 cloud IDE 的环境下开发,开发的时候需要联网,需要保证网络畅通,如果网络不支持的话,就必须要在本地重新搭建一个物流中心,并且将物流中心的全部内容复制到本地才可以正常开发。
每次编译 KCL 包,都要提前准备好整个仓库,随着整个仓库规模越来越大,准备仓库的成本也越来越高。
想必参与过程序开发的小伙伴们一定有过这种经历,写过 java 一定用过 maven, 写 python 离不开 pip, 写过 rust 可能没用过 rust 的编译器 rustc,但是 cargo 是必不可少的。这些成熟的语言项目告诉我们,一个成功的语言项目,背后一定有一个包管理工具,负责语言程序包的管理, 默默支撑着编译过程与程序包仓库之间的交互。
于是, kpm 诞生了 !
3. 小试牛刀
有了 kpm 后, KCL 就可以通过 import 语句导入各种外部依赖,具体的导入语法如下:
import .a.b.c
其中 是被导入的 KCL 程序包的名称,'.a.b.c' 是导入程序包内部的相对路径。这样,就可以在 KCL 程序中导入各种外部的依赖。
如果没有 kpm 的帮助, KCL 编译器在拿到导入了外部依赖的 KCL 程序后将无法编译, KCL 编译器只负责编译,想要编译一个依赖外部包的 KCL 程序包, 就得首先回答编译器的三个问题。
因此,kpm 引入了 kcl.mod 文件来描述 KCL 程序包的信息,kcl.mod 中可以描述当前包的名称,版本以及依赖等编译需要的相关信息。使用 kcl.mod.lock 文件来描述当前 kcl 程序包依赖项的确切版本。可以使用 kpm init mykcl 命令来初始化一个空的名为 mykcl 程序包。kpm 将会创建一个默认的 kcl.mod 文件如下:
[package]
name = "mykcl"
edition = "0.0.1"
version = "0.0.1"
[dependencies]
如上所示,[package] 主要负责解决 “你是谁啊” 的问题,
- name : 名称,用来描述当前 kcl 程序包的名称。
- edition : 编译器的版本字段,用来描述用来编译当前 KCL 程序包的 KCL 编译器版本。
- version : 当前 KCL 程序包的版本。
[dependencies] 的部分负责解决 “你依赖谁啊” 的问题,主要用来描述当前 KCL 程序包依赖的外部 KCL 程序包,可以使用 kpm add 命令来为当前 kcl 程序包添加一个外部依赖项,kpm 执行命令 kpm add 过程中,会将下载的 kcl 程序包保存在本地。
以 KCL 程序包 k8s 为例,使用命令 kpm add k8s 下载名为 k8s 的 KCL 程序包,如果要指定版本可以通过 kpm add k8s:1.27.2 这种方式指定版本。
kpm add k8s
下载完成后,可以看到 kpm 已经在 kcl.mod 文件中添加了相关依赖。
[dependencies]
k8s = "1.27.2"
并且在 kcl.mod.lock 文件中固定当前依赖项的版本。
[dependencies]
[dependencies.k8s]
name = "k8s"
full_name = "k8s_1.27.2"
version = "1.27.2"
sum = "ZI7L/uz53aDOIgVgxBbEPG7wGCWRRLoIY4="
reg = "ghcr.io"
repo = "kusionstack.io/k8s"
oci_tag = "1.27.2"
通过 kcl.mod 和 kcl.mod.lock 为 KCL 编译器解决了“你是谁”和“依赖谁”的问题,对于"上哪找"的问题,kpm 采取的解决方案是直接将下载包的本地路径传递给 KCL 编译器。
通过 kpm run 指令,使用 kpm 编译 kcl 程序包,kpm 会计算当前 kcl 程序包依赖的外部依赖项,然后调用 kcl 编译器, 并将外部依赖在本地的保存路径传递给 kcl 编译器。
我们可以在上面创建的 mykcl 包中,添加一个 main.k, 并填入如下内容:
# 从外部的 k8s 包中的导入 apps。
import k8s.api.apps.v1 as apps
apps.Deployment {
metadata.name = "nginx-deployment"
spec = {
replicas = 3
selector.matchLabels = {
app = "nginx"
}
template.metadata.labels = {
app = "nginx"
}
template.spec.containers = [
{
name = "nginx"
image = "nginx:1.14.2"
ports = [
{containerPort = 80}
]
}
]
}
}
在 mykcl 包中使用命令 kpm run 进行编译。
kpm run
可以得到如下编译结果。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: "nginx:1.14.2"
name: nginx
ports:
- containerPort: 80
4. 总结
了解了以上知识,现在你可以开始使用它来管理 KCL 程序包了。我们将会在后续的文章中进一步介绍使用 kpm 与 kpm registry,以及如何使用它来发布、安装和管理 KCL 程序包。
如果想了解更多关于 KCL 语言和 kpm 的信息,可以访问 KCL 官网获取最新资讯。那么,赶快开始使用 kpm 吧 !
- kcl - github.com/KusionStack…
- kpm - github.com/KusionStack…
- kpm 快速开始 - kcl-lang.io/docs/user_d…
- kcl - kcl-lang.io/