Skip to main content
12 cargo与crates.io

12 cargo与crates.io

•1 min•216 words

Cargo与Crates.io有联动。

Cargo

编译配置

多套配置参数

Cargo 有两个主要的配置:运行 cargo build 时采用的 dev 配置和运行cargo build —release 的 release 配置

这两套配置都有默认的编译参数:

dev更注重编译时间短,release更注重优化效果好。

[profile.dev]
opt-level = 0
[profile.release]
opt-level = 3

profile表示配置参数所属对象,profile就是编译器配置对象
dev与release是具体的配置套名。
opt-level则是配置套下的配置参数名。

工作空间

项目庞大到依赖过多,仅区分模块已无法管理空间,那么区分子项目

子项目与子项目之间的依赖是不互通的,但是子项目与父项目之间是相通的。
子项目没有自己的编译目录,所有的子项目共用父项目的编译目录存放中间产物与编译结果。

Cargo 并不会假定工作空间中的 crate 会彼此依赖,因此我们需要显式声明这些依赖关系。

多级配置

因为有多个项目所有有多个配置文件,所以需要计算出最终的配置

父项目配置文件与子项目配置文件中内配置的东西有所不同,也有很多相同的地方。
对于冲突的地方,使用多级配置的规则来进行取舍。

冲突类型取舍规则
依赖版本Cargo 自动选择兼容版本;失败时手动统一。
普通 features并集合并(所有子项目请求的叠加)。
default-features父项目覆盖子项目(以 [workspace.dependencies] 为准)。
.cargo/config.toml层级覆盖(工作区根 > 全局),且子项目配置被忽略。
[patch] / [profile]仅根配置生效,子项目配置被忽略。
Warning
工作空间只在顶层有一个 Cargo.lock 文件

而不是让每个 crate 目录里都各自有一个Cargo.lock。这能确保所有 crate 使用的都是同一个版本的依赖。

依赖的不同版本,可以同时存在

如果工作空间中的 crate 为同一个依赖指定了彼此不兼容的版本,Cargo 仍然会分别解析它们,但会尽量把版本数量控制得尽可能少。
各crate可以使用同一依赖的不同版本!但如果可以的话会使用兼容的相同版本。

Summary
  1. [workspace]配置依赖解析器(统一各子项目依赖) resolver=“3” ,以便在工作空间中使用 Cargo 最新的依赖解析算法
  2. [workspace]配置下属子项目 members=['xxx1','xxx2']
  3. [workspace]配置共享依赖 [dependences]
  4. [workspace]配置共享元数据 [package]
  5. [workspace.lints] 共享lint检查…
配置项 (Section)在父项目 (Root Manifest) 中在子项目 (Member Manifest) 中说明
[workspace]✅ 可以❌ 不应有定义工作区的核心,用于声明成员、解析器等。
[workspace.dependencies]✅ 可以❌ 不应有定义工作区级别的共享依赖,供子项目继承。
[workspace.package]✅ 可以❌ 不应有定义工作区级别的共享元数据(如版本号、作者),供子项目继承。
[workspace.lints]✅ 可以❌ 不应有定义工作区级别的共享 Lint 检查配置。
[patch]✅ 仅在此生效❌ 被忽略用于覆盖依赖项来源。只在根清单中被识别,在子项目中被忽略。
[replace]✅ 仅在此生效❌ 被忽略功能同 [patch](已弃用),同样只在根清单中生效。
[profile.*]✅ 仅在此生效❌ 被忽略定义编译优化等配置。只在根清单中被识别,子项目中的定义会被忽略。
[package]✅ 可以(如果父项目也是成员)✅ 必须定义包的元数据(如 name, version)。若父项目本身也是一个 crate,则需包含。
[dependencies]✅ 可以(为父项目自身添加)✅ 可以(为自身添加)定义项目自身的依赖。父项目也可有自己的依赖。
[features]✅ 可以✅ 可以定义项目的特性(features),用于条件编译。
[lib], [[bin]] 等✅ 可以✅ 可以定义项目的目标类型(如库、二进制文件)。

运行

因为一个工作空间可以有多个二进制crate所以需要指明

cargo run 时通过 -p 参数加上包名,指定要运行工作空间中的哪个包

测试

工作空间里运行 cargo test ,会执行工作空间中所有 crate 的测试,也可以选择只运行工作空间中某个特定 crate 的测试,只需在根目录中使用 -p 参数并指定想要测试的 crate 名称。

Cite

下载安装

Cargo能从crates.io给的聚集索引中搜索并下载二进制crate

cargo search ‘搜索目标’
cargo install ‘目标名字’

所有通过 cargo install 安装的二进制文件,都会放在安装根目录下的 bin 文件夹中$HOME/.cargo/bin。所以这些安装的进制文件,通常都在环境变量之内,直接就可以在终端中使用。

cargo install --list # 列出所有已安装的二进制crate
cargo install --path . # 安装当前路径下的bin crate
cargo install --path . --bin 'crate-name' # 安装当前路径下crate的指定 bin crate

命令拓展

如果你的 $PATH 中有一个名为 cargo-something 的二进制文件,那么你就可以像运行 Cargo 子命令一样,通过cargo something 来运行它。

也就是使用cargo命令调用我们的命令

我们只需要通过命令名”cargo-我们的命令名”模式,就可以通过”cargo 我们的命令名”来运行我们的命令。
和直接运行不同点在于,在调用“我们的命令”之前,先运行了cargo命令,并由cargo命令调用“我们的命令”

命令拓展的运行逻辑

cargo会将收到的参数传递给后面的命令,后面的命令的参数列表会多一个cargo值作为参数列表的第一个值,相比于直接运行。
在后面脚本命令运行之前,cargo命令会将当前rust项目的信息直接配置进环境变量中,这样后面的脚本命令直接可以得到cargo所知道的信息。

环境变量 含义
CARGO cargo 程序本身的路径
CARGO_HOME ~/.cargo 目录
CARGO_MANIFEST_DIR 当前项目根目录(最有用!)
CARGO_PKG_NAME 包名
CARGO_PKG_VERSION 版本
OUT_DIR 编译输出目录
CARGO_BUILD_TARGET 目标平台
找到全局的命令拓展

cargo能在path范围内找到这些cargo拓展命令。并且使用统一的cargo前缀,可以使用cargo —list列出所有

把命令发布到 crates.io 再 cargo install 再 cargo 拓展命令确实挺不错的。

Crates.io

登录Crates.io账号

运行 cargo login 命令,并在提示时粘贴你的 API key,这个命令会把你的 API token 告诉 Cargo,并将其保存在本地的 /.cargo/credentials 文件中。

Warning

注意,这个 token 是一个秘密,不应该与任何人共享。如果你因为任何原因泄露了它,应立即到 crates.io 撤销并重新生成一个 token。

发布 crate

在发布之前,你需要在 crate 的 Cargo.toml 文件的[package] 部分增加一些本 crate 的元数据(metadata)。

请搜索你想使用的名称,确认它是否已被占用。如果没有,就把Cargo.toml 中 [package] 里的 name 字段改成你想发布时使用的名称

运行 cargo publish 发布该 crate。

[package]
name = "guessing_game"
version = "0.1.0"
edition = "2024"
description = "A fun game where you guess what number the computer has chosen."
license = "MIT OR Apache-2.

必须有license信息。

Cargo 文档 还描述了其他可指定的元数据,它们可以帮助你的 crate 更容易被发现和使用!

如果你打算把工作空间中的 crate 发布到 crates.io 上,那么工作空间中的每个 crate 都需要单独发布。可以通过 -p 参数并指定要发布的 crate 名称,来发布工作
空间中的某个特定 crate。