Cargo 指南
本指南会告诉你使用 Cargo 开发 Rust 包所需的全部知识。
- Cargo 为何存在
- 创建新包
- 开发已有 Cargo 包
- 依赖管理
- 包目录结构
- Cargo.toml 与 Cargo.lock 的区别
- 测试
- 持续集成
- 在 crates.io 上发布
- Cargo Home
Cargo 为何存在
前置知识
你可能知道,在 Rust 中,库或可执行程序都称为 crate。Crate 通过 Rust 编译器 rustc 编译。刚开始学 Rust 时,大多数人接触的第一段代码都是经典的 “Hello World” 程序,通常会直接调用 rustc 编译:
$ rustc hello.rs
$ ./hello
Hello, world!
注意,上面这条命令需要你明确指定文件名。如果想用 rustc 编译另一个程序,就得换一条命令;要是需要指定编译器参数或引入外部依赖,那命令会更复杂、更特殊。
而且,大多数非简单程序都可能依赖外部库,进而还会间接依赖这些库的依赖。如果手动获取所有必需依赖的正确版本并保持更新,不仅麻烦还容易出错。
所以,与其只靠 crate 和 rustc 工作,不如引入更高级的 “包” 概念,再用包管理器来规避上述麻烦 —— 这就是 Cargo 的作用。
登场:Cargo
Cargo 是 Rust 的包管理器。它能让 Rust 包声明各类依赖,还能确保你每次构建都能复现相同的结果。
为实现这个目标,Cargo 主要做四件事:
- 引入两个元数据文件,包含包的各类信息。
- 拉取并构建包的依赖。
- 调用
rustc或其他构建工具,并传入正确参数来构建包。 - 制定规范,让操作 Rust 包更简单。
很大程度上,Cargo 统一了构建程序或库所需的命令 —— 这正是上面提到的 “规范” 的一部分。后面你会看到,不管产物名称是什么,都能用同一个命令构建。不用再直接调用 rustc,而是用 cargo build 这类通用命令,让 Cargo 去处理 rustc 的正确调用方式。而且,Cargo 会自动从仓库拉取你为产物定义的所有依赖,并按需配置到构建流程中。
说 “只要会构建一个基于 Cargo 的项目,就会构建所有这类项目”,其实也不算太夸张。
创建新包
用 Cargo 创建新包,需要执行 cargo new 命令:
$ cargo new hello_world --bin
我们传入 --bin 是因为要创建二进制程序;如果要创建库,就传 --lib。默认情况下,这个命令还会初始化一个 git 仓库,要是不想这样,就加个 --vcs none。
来看看 Cargo 帮我们生成了什么文件:
$ cd hello_world
$ tree .
.
├── Cargo.toml
└── src
└── main.rs
1 directory, 2 files
细看 Cargo.toml
[package]
name = "hello_world"
version = "0.1.0"
edition = "2024"
[dependencies]
这个文件叫清单文件(manifest),包含 Cargo 编译包所需的所有元数据,用 TOML 格式编写(发音为 /tɑməl/)。
细看 src/main.rs
fn main() {
println!("Hello, world!");
}
Cargo 帮你生成了一个 “Hello World” 程序,也就是二进制 crate。现在来编译它:
$ cargo build
Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)
编译完成后运行:
$ ./target/debug/hello_world
Hello, world!
你也可以用 cargo run 一步完成 “编译 + 运行”(如果上次编译后没改代码,就不会显示 “Compiling” 那行):
$ cargo run
Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)
Running `target/debug/hello_world`
Hello, world!
现在你会看到一个新文件 Cargo.lock,它记录了依赖信息 —— 不过目前还没有依赖,所以内容很简单。
等你准备发布程序时,可以用 cargo build --release 开启优化编译:
$ cargo build --release
Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)
cargo build --release 会把生成的二进制文件放在 target/release 目录下,而不是 target/debug。
开发时默认用调试模式(debug mode)编译:编译速度快(因为编译器不做优化),但程序运行慢;发布模式(release mode)编译慢,但程序运行快。
开发已有 Cargo 包
如果你下载了一个用 Cargo 管理的现有包,上手非常简单。
首先,从某处获取包。比如这里我们克隆 GitHub 上的 regex 仓库:
$ git clone https://github.com/rust-lang/regex.git
$ cd regex
然后用 cargo build 构建:
$ cargo build
Compiling regex v1.5.0 (file:///path/to/package/regex)
这个命令会拉取所有依赖,先构建依赖,再构建当前包。
依赖管理
crates.io 是 Rust 社区的中央包仓库,是发现和下载包的地方。Cargo 默认配置为从这里查找所需的包。
要依赖 crates.io 上的库,只需把它添加到你的 Cargo.toml 里。
添加依赖
如果你的 Cargo.toml 还没有 [dependencies] 段落,先加上它,然后列出要使用的 crate 名称和版本。比如下面这样添加对 time crate 的依赖:
[dependencies]
time = "0.1.12"
版本字符串遵循 SemVer 版本规范,更多配置选项可以参考 “指定依赖” 的官方文档。
如果还想加 regex crate 的依赖,不用重复加 [dependencies],直接在下面续上就行。完整的 Cargo.toml 会是这样:
[package]
name = "hello_world"
version = "0.1.0"
edition = "2024"
[dependencies]
time = "0.1.12"
regex = "0.1.41"
重新运行 cargo build,Cargo 会拉取新依赖及其所有子依赖,编译它们,然后更新 Cargo.lock:
$ cargo build
Updating crates.io index
Downloading memchr v0.1.5
Downloading libc v0.1.10
Downloading regex-syntax v0.2.1
Downloading memchr v0.1.5
Downloading aho-corasick v0.3.0
Downloading regex v0.1.41
Compiling memchr v0.1.5
Compiling libc v0.1.10
Compiling regex-syntax v0.2.1
Compiling memchr v0.1.5
Compiling aho-corasick v0.3.0
Compiling regex v0.1.41
Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)
Cargo.lock 会记录所有依赖的精确版本信息(包括具体修订版)。就算 regex 后来更新了,你也会一直用当前这个版本构建,直到执行 cargo update。
现在可以在 main.rs 里使用 regex 库了:
use regex::Regex;
fn main() {
let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
println!("Did our date match? {}", re.is_match("2014-01-01"));
}
运行结果如下:
$ cargo run
Running `target/hello_world`
Did our date match? true
包目录结构
Cargo 用统一的文件放置规范,让你能快速上手新的 Cargo 包。目录结构如下:
.
├── Cargo.lock
├── Cargo.toml
├── src/
│ ├── lib.rs # 默认库文件
│ ├── main.rs # 默认二进制文件
│ └── bin/ # 其他二进制文件
│ ├── named-executable.rs
│ ├── another-executable.rs
│ └── multi-file-executable/ # 多文件二进制(目录名即执行文件名)
│ ├── main.rs
│ └── some_module.rs
├── benches/ # 基准测试
│ ├── large-input.rs
│ └── multi-file-bench/ # 多文件基准测试
│ ├── main.rs
│ └── bench_module.rs
├── examples/ # 示例代码
│ ├── simple.rs
│ └── multi-file-example/ # 多文件示例
│ ├── main.rs
│ └── ex_module.rs
└── tests/ # 集成测试
├── some-integration-tests.rs
└── multi-file-test/ # 多文件集成测试
├── main.rs
└── test_module.rs
核心规范说明
Cargo.toml和Cargo.lock放在包的根目录(包根)。- 源代码放在
src目录下。 - 其他二进制文件放在
src/bin/,基准测试在benches/,示例在examples/,集成测试在tests/。 - 如果二进制、示例、基准测试或集成测试是多文件的,需要在对应目录下建子目录,把
main.rs和其他模块文件放进去 —— 子目录名就是最终产物的名称。
命名风格
按规范,二进制文件、示例、基准测试和集成测试的文件名 / 目录名要用 kebab-case(全小写,用连字符连接),除非有兼容性需求(比如要和已有的二进制名保持一致);而这些目标内部的模块文件,要遵循 Rust 标准用 snake_case(全小写,用下划线连接)。
想了解更多 Rust 模块系统的内容,可以看 Rust 官方书籍;想手动配置目标或控制目标自动发现规则,可参考 “配置目标” 和 “目标自动发现” 的官方文档。
Cargo.toml 与 Cargo.lock 的区别
Cargo.toml 和 Cargo.lock 的用途完全不同。先总结核心区别:
- Cargo.toml:从宏观上描述依赖,由你编写。
- Cargo.lock:包含依赖的精确信息(如具体版本、修订版),由 Cargo 自动维护,不要手动编辑。
不确定时,建议把 Cargo.lock 加入版本控制(比如 Git)。想了解这么做的原因和其他选择,可以看 FAQ 里的 “为什么要把 Cargo.lock 加入版本控制?”,最好配合 “验证最新依赖” 一起使用。
深入理解
Cargo.toml 是清单文件,你可以在里面写包的各种元数据,比如依赖另一个包:
[package]
name = "hello_world"
version = "0.1.0"
[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git" }
这个包依赖 regex 库,且指定了 GitHub 上的仓库地址。因为没写其他信息,Cargo 会默认用仓库默认分支的最新提交来构建。
但这里有个问题:你今天构建这个包,明天把包传给别人,对方构建时可能 regex 已经有新提交了 —— 这样你们的构建结果会不一样,而我们需要 “可复现构建”。
你可以在 Cargo.toml 里加 rev 字段指定具体修订版,比如:
[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git", rev = "9f9f693" }
这样构建结果就一致了,但缺点很明显:每次更新库都要手动记 SHA-1 哈希,又麻烦又容易错。
这时候 Cargo.lock 就派上用场了。有了它,你不用手动跟踪精确修订版 ——Cargo 会帮你做。比如用之前没加 rev 的 Cargo.toml,第一次构建时,Cargo 会拉取最新提交,然后把精确信息写入 Cargo.lock,文件内容会像这样:
[[package]]
name = "hello_world"
version = "0.1.0"
dependencies = [
"regex 1.5.0 (git+https://github.com/rust-lang/regex.git#9f9f693768c584971a4d53bc3c586c33ed3a6831)",
]
[[package]]
name = "regex"
version = "1.5.0"
source = "git+https://github.com/rust-lang/regex.git#9f9f693768c584971a4d53bc3c586c33ed3a6831"
里面包含了构建用的精确修订版。就算你没在 Cargo.toml 里写,别人拿到你的包后,也会用同一个 SHA-1 修订版构建。
等你想更新库时,用 cargo update 就行:
$ cargo update # 更新所有依赖
$ cargo update regex # 只更新 regex
这个命令会生成新的 Cargo.lock,写入最新的版本信息。注意,cargo update 后面的参数是 “包 ID 规范”,regex 只是简化写法。
测试
Cargo 可以用 cargo test 命令运行测试。Cargo 会在两个地方找测试代码:
src目录下的文件:这里的测试应该是单元测试和文档测试。tests/目录:这里的测试应该是集成式测试,所以需要在tests/的文件里导入你的 crate。
运行测试示例
在我们之前的包(还没写测试)里运行 cargo test:
$ cargo test
Compiling regex v1.5.0 (https://github.com/rust-lang/regex.git#9f9f693)
Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)
Running target/test/hello_world-9c2b65bbb79eabce
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
如果你的包有测试,输出会显示具体的测试数量和结果。
运行特定测试
可以传筛选条件来运行特定测试,比如:
$ cargo test foo
这会运行所有名称包含 foo 的测试。
额外检查
cargo test 还会做其他检查:
- 编译所有示例,确保能通过。
- 运行文档测试,确保文档注释里的代码示例能编译。
想了解 Rust 测试的整体写法和组织方式,可以看 Rust 官方文档的 “测试指南”;想了解 Cargo 中不同类型的测试,可参考 “Cargo 目标:测试”。
持续集成
入门
基础的持续集成(CI)主要做两件事:构建项目、运行测试。下面是主流 CI 工具的配置示例。
GitHub Actions
要在 GitHub Actions 上测试包,可创建 .github/workflows/ci.yml 文件,内容如下:
name: Cargo Build & Test
on:
push:
pull_request:
env:
CARGO_TERM_COLOR: always
jobs:
build_and_test:
name: Rust project - latest
runs-on: ubuntu-latest
strategy:
matrix:
toolchain:
- stable
- beta
- nightly
steps:
- uses: actions/checkout@v4
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- run: cargo build --verbose
- run: cargo test --verbose
这个配置会测试三个 Rust 发布通道(stable/beta/nightly),任何一个工具链失败都会导致整个任务失败。你也可以在 GitHub 仓库的 “Actions” 页面点击 “new workflow”,选择 Rust 模板来添加默认配置。更多细节看 GitHub Actions 官方文档。
GitLab CI
要在 GitLab CI 上测试包,可创建 .gitlab-ci.yml 文件,内容如下:
stages:
- build
rust-latest:
stage: build
image: rust:latest
script:
- cargo build --verbose
- cargo test --verbose
rust-nightly:
stage: build
image: rustlang/rust:nightly
script:
- cargo build --verbose
- cargo test --verbose
allow_failure: true
这个配置会测试 stable 和 nightly 通道,但 nightly 通道的失败不会影响整体构建。更多细节看 GitLab CI 官方文档。
builds.sr.ht
要在 sr.ht 上测试包,可创建 .build.yml 文件(记得把 <your repo> 和 <your project> 换成实际的仓库地址和项目目录):
image: archlinux
packages:
- rustup
sources:
-
tasks:
- setup: |
rustup toolchain install nightly stable
cd /
rustup run stable cargo fetch
- stable: |
rustup default stable
cd /
cargo build --verbose
cargo test --verbose
- nightly: |
rustup default nightly
cd /
cargo build --verbose ||:
cargo test --verbose ||:
- docs: |
cd /
rustup run stable cargo doc --no-deps
rustup run nightly cargo doc --no-deps ||:
这个配置会在 stable 和 nightly 通道测试并构建文档,nightly 通道的失败不会影响整体构建。更多细节看 builds.sr.ht 官方文档。
CircleCI
要在 CircleCI 上测试包,可创建 .circleci/config.yml 文件,内容如下:
version: 2.1
jobs:
build:
docker:
# 查看最新镜像标签:https://circleci.com/developer/images/image/cimg/rust#image-tags
- image: cimg/rust:1.77.2
steps:
- checkout
- run: cargo test
想实现更复杂的流水线(如不稳定测试检测、缓存、产物管理),可参考 CircleCI 配置文档。
验证最新依赖
在 Cargo.toml 里指定依赖时,通常是匹配一个版本范围。要测试所有版本组合不现实,但至少要验证 “最新版本”—— 这能覆盖用 cargo add 或 cargo install 的用户场景。
考虑因素
验证最新依赖时,需要考虑:
- 减少对本地开发或 CI 的外部影响。
- 依赖的发布频率。
- 项目能接受的风险等级。
- CI 成本(包括间接成本,比如并行 runner 达上限导致任务排队)。
解决方案
常见的解决方案有四种:
- 不把
Cargo.lock加入版本控制- 缺点:如果 PR 频率低,很多版本可能没测到;且失去了构建确定性。
- 加一个 CI 任务验证最新依赖,但设置 “失败不中断”
- 缺点:不同 CI 工具的失败提示可能不明显;PR 频率高时会浪费资源。
- 定时运行 CI 任务验证最新依赖
- 缺点:部分托管 CI 会对长期未更新的仓库禁用定时任务;通知可能无法触达负责人;若和依赖发布频率不匹配,可能测试不足或重复测试。
- 通过 PR 定期更新依赖(如用 Dependabot 或 RenovateBot)
- 优点:可将依赖隔离到单独 PR 或合并成一个 PR;只使用必要资源;可配置频率来平衡 CI 资源和版本覆盖度。
GitHub Actions 示例
下面是一个验证最新依赖的 GitHub Actions 任务配置:
jobs:
latest_deps:
name: Latest Dependencies
runs-on: ubuntu-latest
continue-on-error: true
env:
CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: allow
steps:
- uses: actions/checkout@v4
- run: rustup update stable && rustup default stable
- run: cargo update --verbose
- run: cargo build --verbose
- run: cargo test --verbose
注意:CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS 设为 allow,是为了确保依赖解析器不会因项目的 Rust 版本而限制依赖选择。如果项目在不同平台或 Rust 版本上失败风险高,可能需要测试更多组合。
验证 rust-version
如果发布的包指定了 rust-version(最低支持的 Rust 版本),必须验证这个字段的正确性。
辅助工具
可借助第三方工具:
cargo-msrv:用于查找最小支持的 Rust 版本。cargo-hack:提供额外的构建 / 检查功能。
GitHub Actions 示例
下面是用 cargo-hack 验证 rust-version 的配置:
jobs:
msrv:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: taiki-e/install-action@cargo-hack
- run: cargo hack check --rust-version --workspace --all-targets --ignore-private
这个配置在 “全面性” 和 “速度” 之间做了平衡:
- 只用一个平台(大多数项目是跨平台的,依赖平台相关的包会自行验证)。
- 用
cargo check(大多数问题是 API 可用性,而非运行行为)。 - 跳过未发布的包(假设只有通过仓库使用项目的用户才关心
rust-version)。
在 crates.io 上发布
如果你有一个想分享给全世界的库,就可以把它发布到 crates.io 上!“发布 crate” 指的是把某个特定版本上传到 crates.io 托管 —— 注意,发布是永久性的:版本不能覆盖,代码不能删除,但发布的版本数量没有限制。
首次发布前的准备
首先,你需要一个 crates.io 账号来获取 API 令牌。步骤如下:
- 访问 crates.io 首页,用 GitHub 账号登录(目前仅支持 GitHub 登录)。
- 去 “Account Settings” 页面填写并验证邮箱。
- 创建 API 令牌,一定要复制下来—— 离开页面后就再也看不到了。
然后运行 cargo login 命令:
$ cargo login
在提示符后粘贴刚才的令牌:
plaintext
please paste the API Token found on https://crates.io/me below
abcdefghijklmnopqrstuvwxyz012345
这个命令会让 Cargo 记录你的 API 令牌,并存储在本地的 ~/.cargo/credentials.toml 中。注意:这个令牌是机密,不要分享给他人;一旦泄露,要立即吊销。
如果想删除本地存储的令牌,可以用 cargo logout 命令。
发布新 crate 前的注意
- crates.io 上的 crate 名称是 “先到先得” 的,一旦被占用,其他 crate 就不能用了。
- 完善
Cargo.toml中的元数据,让你的 crate 更容易被发现。发布前至少要填这些字段:license或license-file(许可证)description(描述)homepage(主页)repository(仓库地址)readme(说明文档)也可以加一些keywords(关键词)和categories(分类),不过这两个不是必需的。
- 如果发布的是库,建议参考《Rust API 指南》(Rust API Guidelines)。
打包 crate
下一步是把 crate 打包并上传到 crates.io,用 cargo publish 命令。这个命令会做四件事:
- 对包做一些验证检查。
- 把源代码压缩成
.crate文件。 - 把
.crate文件解压到临时目录,验证能否编译。 - 把
.crate文件上传到 crates.io(仓库会做额外检查后才添加)。
建议:先运行 cargo publish --dry-run(或等效的 cargo package),确认没有警告或错误再正式发布 —— 这个命令会执行上面的前三步。
$ cargo publish --dry-run
生成的 .crate 文件在 target/package 目录下。crates.io 目前对 .crate 文件的大小限制是 10MB,建议检查文件大小,避免不小心把不需要的大文件(如测试数据、网站文档、代码生成文件)打包进去。
想查看打包包含哪些文件,可以运行:
$ cargo package --list
Cargo 会自动忽略版本控制工具(如 Git)标记为 “忽略” 的文件。如果想额外指定忽略的文件,可以在清单文件中用 exclude 字段:
[package]
# ...
exclude = [
"public/assets/*",
"videos/*",
]
如果想明确指定要包含的文件,可以用 include 字段(会覆盖 exclude):
[package]
# ...
include = [
"**/*.rs",
]
上传 crate
准备好后,运行 cargo publish 上传到 crates.io:
$ cargo publish
这样就完成了首次发布!
发布已有 crate 的新版本
要发布新版本,只需修改 Cargo.toml 中的 version 字段(遵循 SemVer 规范,明确哪些变更属于兼容变更),然后再运行 cargo publish 即可。
建议:考虑完整的发布流程,并自动化尽可能多的步骤。每个版本最好包含:
- 一个更新日志条目(手动整理最佳,自动生成也比没有好)。
- 一个指向发布提交的 Git 标签。
常用的第三方工具(按字母排序):
cargo-releasecargo-smart-releaserelease-plz
更多工具可在 crates.io 上查找。
管理 crates.io 上的 crate
crate 的管理主要通过命令行工具 cargo 完成,而非 crates.io 网页界面。下面是两个常用的管理子命令。
cargo yank(撤回版本)
有时你可能发布了有问题的 crate 版本(比如语法错误、漏传文件等),这时可以用 cargo yank 撤回版本:
$ cargo yank --version 1.0.1 # 撤回 1.0.1 版本
$ cargo yank --version 1.0.1 --undo # 取消撤回
注意:撤回(yank)不会删除任何代码。这个功能不是用来删除不小心上传的机密信息(如密钥)的 —— 如果发生这种情况,必须立即重置这些机密。
撤回版本的语义是:新的依赖不能再使用这个版本,但已有的依赖仍然能正常工作。crates.io 的核心目标之一是作为 crate 的永久归档,不允许删除版本,而撤回正好平衡了 “归档稳定性” 和 “修复错误版本” 的需求。
cargo owner(管理所有者)
一个 crate 可能由多人开发,或者主要维护者会变更。crate 的所有者有权发布新版本,但也可以添加其他所有者。
$ cargo owner --add github-handle # 添加 GitHub 用户为所有者
$ cargo owner --remove github-handle # 移除 GitHub 用户
$ cargo owner --add github:rust-lang:owners # 添加 GitHub 团队
$ cargo owner --remove github:rust-lang:owners # 移除 GitHub 团队
cargo owner 接受的 “所有者 ID” 只能是 GitHub 用户名或 GitHub 团队。
- 添加用户:被添加的用户会成为 “命名所有者”(named owner),拥有完整权限 —— 不仅能发布 / 撤回版本,还能添加 / 移除其他所有者(包括添加他的人)。所以不要把不熟悉的人设为命名所有者。且用户必须先登录过 crates.io 才能成为命名所有者。
- 添加团队:被添加的团队会成为 “团队所有者”(team owner),权限受限 —— 能发布 / 撤回版本,但不能添加 / 移除所有者。团队所有者更适合管理多人协作,且安全性更高(避免单个所有者作恶)。
团队的格式是 github:org:team(如上面的例子)。添加团队时,操作人必须是该团队的成员;移除团队则没有这个限制。
GitHub 权限问题
GitHub 的团队成员信息没有简单的公开访问接口,操作时可能会遇到这样的提示:
It looks like you don’t have permission to query a necessary property from GitHub to complete this request. You may need to re-authenticate on crates.io to grant permission to read GitHub org memberships.
这通常是因为:
- 你上次登录 crates.io 时,该平台还没添加 “查询团队成员” 的功能 —— 早期 crates.io 登录 GitHub 时不需要任何权限,只用来验证身份;但现在查询团队成员需要
read:org权限。 - 你拒绝了
read:org权限 —— 这会导致你无法添加团队所有者,也无法以团队所有者身份发布 crate,但其他功能不受影响。
如果想授权,可以去 crates.io 重新登录,此时会提示授予 read:org 权限。
另外,GitHub 组织可能会主动限制第三方应用访问。要检查这一点,可以访问:https://github.com/organizations/:org/settings/oauth_application_policy(把 :org 换成组织名,如 rust-lang)。在 “Organization Access Control” 下,可以把 crates.io 从黑名单中移除,或点击 “Remove Restrictions” 允许所有第三方应用访问。

也可以在 crates.io 请求 read:org 权限时,点击组织名旁边的 “Grant Access”,明确允许 crates.io 查询该组织。

排查 GitHub 团队权限错误
添加 GitHub 团队为所有者时,可能会遇到这样的错误:
error: failed to invite owners to crate <crate_name>: api errors (status 200 OK): could not find the github team org/repo
这时可以按以下步骤排查:
- 去 GitHub 的 “Application settings” 页面(
https://github.com/settings/applications),检查 “Authorized OAuth Apps” 标签下是否有 crates.io—— 没有的话,先去 crates.io 授权登录。 - 在授权应用列表中找到 crates.io,点击进入,确认你或你的组织在 “Organization access” 列表中,且标记为绿色对勾。如果有 “Grant” 或 “Request” 按钮,点击授权或请求组织所有者授权。
Cargo Home
“Cargo Home” 是一个下载和源码缓存目录。构建 crate 时,Cargo 会把下载的构建依赖存储在这里。你可以通过设置 CARGO_HOME 环境变量来修改它的位置;如果你的 Rust crate 里需要获取这个路径,可以用 home crate 提供的 API。
默认情况下,Cargo Home 位于 $HOME/.cargo/。注意:Cargo Home 的内部结构尚未稳定,可能随时变化。
Cargo Home 的组成
Cargo Home 包含以下文件和目录:
文件
config.toml:Cargo 的全局配置文件,详见官方参考中的 “config” 条目。credentials.toml:存储cargo login生成的私有登录凭证,用于登录仓库。.crates.toml、.crates2.json:隐藏文件,记录通过cargo install安装的 crate 信息 ——不要手动编辑!
目录
bin:存储通过cargo install或rustup安装的 crate 可执行文件。要让这些二进制文件全局可用,需要把这个目录的路径加入$PATH环境变量。git:存储 Git 源码:git/db:如果 crate 依赖 Git 仓库,Cargo 会把仓库克隆成 “裸仓库”(bare repo)存在这里,必要时会更新。git/checkouts:使用 Git 源码时,Cargo 会从git/db的裸仓库中,检出该依赖指定提交的代码到这里,供编译器使用。同一个仓库的不同提交可以有多个检出目录。
registry:存储仓库(如 crates.io)的包和元数据:registry/index:裸 Git 仓库,包含该仓库所有可用 crate 的元数据(版本、依赖等)。registry/cache:存储下载的依赖,以.crate为后缀的 gzip 压缩包。registry/src:如果某个下载的.crate包被需要,Cargo 会把它解压到这里,供rustc查找.rs文件。
在 CI 中缓存 Cargo Home
为了避免在持续集成中重复下载所有依赖,可以缓存 $CARGO_HOME 目录。但不建议缓存整个目录—— 这样效率低,因为源码会被存储两次(比如依赖 serde 1.0.92 时,registry/cache 里有 serde-1.0.92.crate,registry/src 里还有解压后的 .rs 文件),会增加下载、解压、压缩和上传缓存的时间。
如果要缓存 cargo install 安装的二进制文件,需要缓存 bin/ 目录和 .crates.toml、.crates2.json 文件。
推荐缓存的文件和目录:
.crates.toml.crates2.jsonbin/registry/index/registry/cache/git/db/
vendoring 项目的所有依赖
详见 cargo vendor 子命令的官方文档。
清理缓存
理论上,你可以删除缓存的任何部分 ——Cargo 会在需要时自动恢复(比如重新解压压缩包、检出裸仓库,或从网络重新下载)。
另外,cargo-cache crate 提供了一个简单的命令行工具,可以只清理缓存的特定部分,或查看各部分的大小。
浙公网安备 33010602011771号