Cargo 缓存
Cargo 使用了缓存的方式提升构建效率,当构建时,Cargo 会将已下载的依赖包放在 CARGO_HOME 目录下,下面一起来看看。
Cargo Home
默认情况下,Cargo Home 所在的目录是 $HOME/.cargo/,例如在 macos ,对应的目录是:
$ echo $HOME/.cargo/
/Users/sunfei/.cargo/
我们也可以通过修改 CARGO_HOME 环境变量的方式来重新设定该目录的位置。若你需要在项目中通过代码的方式来获取 CARGO_HOME ,home 包提供了相应的 API。
注意! Cargo Home 目录的内部结构并没有稳定化,在未来可能会发生变化
文件
config.toml是 Cargo 的全局配置文件,具体请查看这里credentials.toml为cargo login提供私有化登录证书,用于登录package注册中心,例如crates.io.crates.toml,.crates2.json这两个是隐藏文件,包含了通过cargo install安装的包的package信息,请不要手动修改!
目录
bin目录包含了通过cargo install或rustup下载的包编译出的可执行文件。你可以将该目录加入到$PATH环境变量中,以实现对这些可执行文件的直接访问git中存储了Git的资源文件:git/db,当一个包依赖某个git仓库时,Cargo会将该仓库克隆到git/db目录下,如果未来需要还会对其进行更新git/checkouts,若指定了git源和commit,那相应的仓库就会从git/db中checkout到该目录下,因此同一个仓库的不同checkout共存成为了可能性
registry包含了注册中心( 例如crates.io)的元数据 和packagesregistry/index是一个 git 仓库,包含了注册中心中所有可用包的元数据( 版本、依赖等 )registry/cache中保存了已下载的依赖,这些依赖包以gzip的压缩档案形式保存,后缀名为.crateregistry/src,若一个已下载的.crate档案被一个package所需要,该档案会被解压缩到registry/src文件夹下,最终rustc可以在其中找到所需的.rs文件
在 CI 时缓存 Cargo Home
为了避免持续集成时重复下载所有的包依赖,我们可以将 $CARGO_HOME 目录进行缓存,但缓存整个目录是效率低下的,原因是源文件可能会被缓存两次。
例如我们依赖一个包 serde 1.0.92,如果将整个 $CACHE_HOME 目录缓存,那么serde 的源文件就会被缓存两次:在 registry/cache 中的 serde-1.0.92.crate 以及 registry/src 下被解压缩的 .rs 文件。
因此,在 CI 构建时,出于效率的考虑,我们仅应该缓存以下目录:
bin/registry/index/registry/cache/git/db/
清除缓存
理论上,我们可以手动移除缓存中的任何一部分,当后续有包需要时 Cargo 会尽可能去恢复这些资源:
- 解压缩
registry/cache下的.crate档案 - 从
.git中checkout缓存的仓库 - 如果以上都没了,会从网络上重新下载
你也可以使用 cargo-cache 包来选择性的清除 cache 中指定的部分,当然,它还可以用来查看缓存中的组件大小。
构建时卡住:Blocking waiting for file lock ..
在开发过程中,或多或少我们都会碰到这种问题,例如你同时打开了 VSCode IDE 和终端,然后在 Cargo.toml 中刚添加了一个新的依赖。
此时 IDE 会捕捉到这个修改然后自动去重新下载依赖(这个过程可能还会更新 crates.io 使用的索引列表),在此过程中, Cargo 会将相关信息写入到 $HOME/.cargo/.package_cache 下,并将其锁住。
如果你试图在另一个地方(例如终端)对同一个项目进行构建,就会报错: Blocking waiting for file lock on package cache。
解决办法很简单:
- 既然下载慢,那就使用国内的注册服务,不再使用 crates.io
- 耐心等待持有锁的用户构建完成
- 强行停止正在构建的进程,例如杀掉 IDE 使用的 rust-analyer 插件进程,然后删除
$HOME/.cargo/.package_cache目录