ITPub博客

首页 > 数据库 > 数据库开发技术 > Rust 工程版本管理

Rust 工程版本管理

原创 数据库开发技术 作者:Rust嵌入式 时间:2024-06-05 22:05:00 0 删除 编辑

Rust 工程版本指定方式

在 Rust 项目中进行版本的指定有两种的方式:

  1. Cargo.toml 中使用 version 字段指定版本号:在 Rust 项目中,通常使用 Cargo 来管理依赖和项目配置。你可以在项目的 Cargo.toml 文件中指定你的项目版本。例如:
[package]
name = "my_project"
version = "0.1.0"

在这个例子中,项目的版本被设置为 0.1.0。你可以根据项目的更新情况逐步增加版本号。

  1. 使用 Git 进行版本控制:除了在 Cargo.toml 中指定版本外,你还可以使用 Git 等版本控制工具来管理你的代码库。每次对代码库的提交都可以看作是一个版本的变更,你可以使用 Git 的标签功能来标记特定版本。
git tag -a v0.1.0 -m "Version 0.1.0"

这个命令会给当前仓库打上一个名为 v0.1.0 的标签,并添加一条描述信息, 严格来说,通过git tag为人工命令创建的标签,通常在发布新的稳定版本会使用,但在日常开发中,可能不能严格遵守 tag 的版本号和名称与toml中的名称一致,因此需要小心处理。在创建工程或新建添加依赖crate时,可手动指定版本,也可指定 git 的 commit token 或 branch。

[dependencies]
serde = { version = "^1", default-features = false, features = ["derive"] }
heapless = { version = "^0.7", features = ["serde"] }
no-std-net = { version = "^0.5", features = ["serde"] }
#atat = { version = "0.19", features = ["derive"] }
atat = { git = "https://github.com/BlackbirdHQ/atat", rev = "31a45fc", features = [
    "derive",
    "bytes",
] }
hash32 = "0.2.1"
hash32-derive = "^0.1.0"
embassy-time = "0.1"

如上所示,通过version以及git的rev属性来指定所依赖的包版本。

优缺点

优点

  1. 简单易用:提供了一种简单易用的方式来管理项目的依赖关系、构建项目和发布项目等任务。
  2. 统一的依赖管理:提供了统一的方式来管理项目的依赖关系。你可以在项目的 Cargo.toml 文件中声明所需的依赖项及其版本要求,Cargo 会负责下载和管理这些依赖项。
  3. 严格规范:版本的确定根据Semantic Versioning的规定,通过约束关系和能推导整个项目版本依赖是否满足要求。
  4. 依赖解决:Cargo 能够智能地解决项目依赖关系的问题,确保所使用的依赖项的版本是兼容的,并且不会发生冲突。
  5. 集成测试:Cargo 内置了对项目的集成测试支持,可以方便地编写和运行集成测试,确保项目的质量。

缺点

  • 依赖管理:虽然 Cargo 提供了依赖管理功能,但在某些情况下,依赖管理仍可能引入一些问题,比如依赖冲突、版本锁定等问题,对于大型项目,容易出现版本互锁或互斥的情况,因此对于版本的约束需要特别小心地处理。
  • 构建时间:在某些情况下,Cargo 的构建时间可能较长,特别是在项目依赖项较多时,需要一定时间计算约束关系,推导出合适的版本。虽然 Cargo 提供了一些缓存机制来加快构建速度,但仍可能存在构建时间较长的情况。

语义化版本

Semantic Versioning(https://semver.org/)规定了版本的格式和变更规范:版本格式包括:主版本号(MAJOR),次版本号(MINOR),修订号(PATCH), 版本号递增规则如下:

  1. 主版本号:当代码更新了不兼容的 API 修改
  2. 次版本号:当代码增加了新功能,但同时满足向下兼容
  3. 修订号:更新了代码,但仅仅是功能的修复,且兼容旧的版本。

可以添加标签到版本号的后面作为补充.

如何指定版本号?

以下关键词 MUST、MUST NOT、REQUIRED、SHALL、SHALL NOT、SHOULD、SHOULD NOT、 RECOMMENDED、MAY、OPTIONAL 依照 RFC 2119 的叙述解读。

  1. 使用语义化版本控制的软件必须(MUST)定义公共 API。该 API 可以在代码中被定义或出现于严谨的文档内。无论何种形式都应该力求精确且完整。
  2. 标准的版本号必须(MUST)采用 X.Y.Z 的格式,其中 X、Y 和 Z 为非负的整数,且禁止(MUST NOT)在数字前方补零。X 是主版本号、Y 是次版本号、而 Z 为修订号。每个元素必须(MUST)以数值来递增。例如:1.9.1 -> 1.10.0 -> 1.11.0。
  3. 标记版本号的软件发行后,禁止(MUST NOT)改变该版本软件的内容。任何修改都必须(MUST)以新版本发行。
  4. 主版本号为零(0.y.z)的软件处于开发初始阶段,一切都可能随时被改变。这样的公共 API 不应该被视为稳定版。
  5. 1.0.0 的版本号用于界定公共 API 的形成。这一版本之后所有的版本号更新都基于公共 API 及其修改内容。
  6. 修订号 Z(x.y.Z | x > 0)必须(MUST)在只做了向下兼容的修正时才递增。这里的修正指的是针对不正确结果而进行的内部修改。
  7. 次版本号 Y(x.Y.z | x > 0)必须(MUST)在有向下兼容的新功能出现时递增。在任何公共 API 的功能被标记为弃用时也必须(MUST)递增。也可以(MAY)在内部程序有大量新功能或改进被加入时递增,其中可以(MAY)包括修订级别的改变。每当次版本号递增时,修订号必须(MUST)归零。
  8. 主版本号 X(X.y.z | X > 0)必须(MUST)在有任何不兼容的修改被加入公共 API 时递增。其中可以(MAY)包括次版本号及修订级别的改变。每当主版本号递增时,次版本号和修订号必须(MUST)归零。
  9. 先行版本号可以(MAY)被标注在修订版之后,先加上一个连接号再加上一连串以句点分隔的标识符来修饰。标识符必须(MUST)由 ASCII 字母数字和连接号 [0-9A-Za-z-] 组成,且禁止(MUST NOT)留白。数字型的标识符禁止(MUST NOT)在前方补零。先行版的优先级低于相关联的标准版本。被标上先行版本号则表示这个版本并非稳定而且可能无法满足预期的兼容性需求。范例:1.0.0-alpha、1.0.0-alpha.1、1.0.0-0.3.7、1.0.0-x.7.z.92。
  10. 版本编译信息可以(MAY)被标注在修订版或先行版本号之后,先加上一个加号再加上一连串以句点分隔的标识符来修饰。标识符必须(MUST)由 ASCII 字母数字和连接号 [0-9A-Za-z-] 组成,且禁止(MUST NOT)留白。当判断版本的优先层级时,版本编译信息可(SHOULD)被忽略。因此当两个版本只有在版本编译信息有差别时,属于相同的优先层级。范例:1.0.0-alpha+001、1.0.0+20130313144700、1.0.0-beta+exp.sha.5114f85。
  11. 版本的优先层级指的是不同版本在排序时如何比较?
  12. 判断优先层级时,必须(MUST)把版本依序拆分为主版本号、次版本号、修订号及先行版本号后进行比较(版本编译信息不在这份比较的列表中)。
  13. 由左到右依序比较每个标识符,第一个差异值用来决定优先层级:主版本号、次版本号及修订号以数值比较。

例如:1.0.0 < 2.0.0 < 2.1.0 < 2.1.1。

  1. 当主版本号、次版本号及修订号都相同时,改以优先层级比较低的先行版本号决定。

例如:1.0.0-alpha < 1.0.0。

  1. 有相同主版本号、次版本号及修订号的两个先行版本号,其优先层级必须(MUST)透过由左到右的每个被句点分隔的标识符来比较,直到找到一个差异值后决定:
    1. 只有数字的标识符以数值高低比较。
    2. 有字母或连接号时则逐字以 ASCII 的排序来比较。
    3. 数字的标识符比非数字的标识符优先层级低。
    4. 若开头的标识符都相同时,栏位比较多的先行版本号优先层级比较高。

例如:1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0。

如何查看 Rust 工程中各 crate最终的版本号

可以在Cargo.lock文件中查看所有依赖库的版本号,包括多重依赖。如下所示

[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

[[package]]
name = "critical-section"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"

[[package]]
name = "defmt"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0"
dependencies = [
 "bitflags",
 "defmt-macros",
]

也可以使用图来查看各库的依赖拓扑关系,需要安装命令:

## 解析依赖库的关系
cargo install cargo-deps
## 根据依赖关系生成图片
brew install graphviz

命令使用如下

cargo deps --all-deps | dot -Tsvg > graph.svg

效果如下:

如何解决Rust 版本冲突问题

设置合适的版本约束

在 Rust 的语义化版本控制(Semantic Versioning)规范中,^ 和 ~ 通常用于指定依赖项的版本范围。它们分别表示不同的版本约束条件。

  1. ^符号:^ 符号用于指定一个兼容的最低版本,但允许次版本号和修订号发生变化,只要它们的主版本号与指定的版本相同。

例如,如果您指定一个依赖项的版本为 ^1.2.3,则表示您允许使用任何 1.x.y 版本,其中 x 和 y 可以是任意的数字,但 x 必须等于 2。

  1. ~符号:~ 符号用于指定一个兼容的最低版本,但只允许修订号发生变化,主版本号和次版本号保持不变。

例如,如果您指定一个依赖项的版本为 ~1.2.3,则表示您允许使用任何 1.2.x 版本,其中 x 可以是任意的数字,但 x 必须等于 3。

  1. =符号:使用等号 = 指定一个确切的版本号。这表示您的项目依赖于特定的版本,只有该版本才会被接受,不允许任何其他版本的依赖项。例如,如果您在 Cargo.toml 文件中指定了一个依赖项的版本为 =1.2.3,则表示您的项目依赖于确切版本号为 1.2.3 的这个依赖项,不允许使用任何其他版本。

修改版本约束

当出现版本提示冲突,如果能通过冲突的库的版本号就能解决,则可考虑执行以下升级命令。

# 指定升级到此版本
cargo update defmt@0.4.0
# 让 cargo 决定升级到合适的版本
cargo update defmt
# 升级所有库的版本,不一定会成功
cargo update


原文作者:Rust嵌入式;如有侵权,请联系管理员删除。

上一篇: Slint 类型
请登录后发表评论 登录
全部评论

注册时间:2023-11-13

  • 博文量
    64
  • 访问量
    45609