Cargo Package离线编译策略简单地讲,cargo为Package提供了两套【离线编译】解决方案:
cargo fetch + cargo build --offlinecargo vendor + 修改.cargo/config.toml文件 + cargo buildcargo fetch与cargo vendor命令Cargo Package工程根目录被执行。build.rs还是shell脚本)被启动前,被预先执行。crates.io还是github,它们都可被预拉取和缓存至本地。crate源码的储存位置crate.io依赖项 -> $CARGO_HOME/registry/srcgithub依赖项 -> $CARGO_HOME/git/checkoutscargo fetch缓存依赖项源码于$CARGO_HOME目录下。更具体地进,cargo vendor缓存依赖项源码于Cargo Package工程根目录下的vendor子文件夹里。crate的共享范围vendor文件夹馁馁地就是rust版的node_modules。vendor依赖目录在多个Cargo Package工程之间共享,需要额外地配置.cargo/config.toml文件和对多个工程的文件系统位置做一些约定。这要比npm - node_modules麻烦不少 — 回头单独写篇文章分享之。cargo fetch缓存的依赖项源码可被同一台机器上的所有Cargo Package工程所共享。cargo vendor缓存的依赖项源码仅服务于当前Cargo Package工程。CI系统集成方式(比如,Jenkins)cargo vendor命令需要由 @程序员,在个人电脑上,在代码提交前,执行一次。于是,vendor文件夹出现。cargo vendor命令打印至【标准输出】的配置代码(如下)·复制到.cargo/config.toml配置文件内。
[source.crates-io]replace-with = "vendored-sources"[source."https://github.com/shadowsocks/crypto"]git = "https://github.com/shadowsocks/crypto"branch = "master"replace-with = "vendored-sources"[source.vendored-sources]directory = "vendor"
若你的Cargo Package工程曾经配置过【源码替换】规则(真高级),那么请合并(而不仅是追加)[source.***]配置代码。vendor文件夹和.cargo/config.toml配置文件,随业务程序,一起提交至git仓库。Cargo.toml.cargo/config.tomlJenkins会git clone到上述所有文件,包括:cargo build命令也不需要--offline命令行参数了,因为【目录·源码替换】配置规则会生效和告诉cargo从本地硬盘的何处寻找依赖项crate源码。
题外话,没有想到吧!在这影响依赖项“寻址”指向的机制不是【依赖重载[patch.***]】,而是【源码替换[source.***]】。我也挺意外的。cargo fetch命令需要由 @CI管理员,在Jenkins机器上,在启动打包jobs以前,连网执行一次。cargo build --offline命令才能在$CARGO_HOME目录下找到预缓存的依赖项源码。其中,命令行参数--offline会“短路”一切网络请求,包括:Cargo.lock是否已经反映了每个依赖项的最新语义兼容版本。crate源码cargo fetch方案·集成步骤:
对程序员来说,这可能不那么爽。毕竟,每次依赖升级,咱们都不得不走流程,编故事,写报告,请 @CI管理员 给执行一下cargo fetch命令。cargo vendor方案·集成步骤:cargo vendor性能最佳·参数组合cargo vendor --no-delete --versioned-dirs --respect-source-config
--no-delete不删除上一次执行cargo vendor时留下的vendor文件夹。这样下载过的crate源码就不会再重新下载了。--versioned-dirs给每个依赖项目录名追加以-开头的版本号后缀(例如,base64-0.5.2)。这样,不用刻意地浏览每个依赖项的Cargo.toml文件,便可知晓它们的版本信息。--respect-source-config若你的工程早先就已经配置过【源码替换】[source.***]配置块,cargo将对旧配置做兼容处理。否则,旧配置就会被无视了。虽然上面讲了那么多,但其实仅只绕过了【依赖项源码下载】的耗时环节。但是,cargo打包编译慢,又何止于网络慢,编译本身也是“重灾区”。所以,若你的CI打包策略是:
git捡出业务代码 — 内网应该很快cargo fetch / vendor的缓存,应该也很快的话,那么上述的长篇大论仅只节省了#3的延时。而我要在此推荐的【究级】“补刀”配置却能够缩短#4的耽搁。即,给.cargo/config.toml文件添加(或合并)一段配置(如下)
[build]target-dir = "../<工程名>-target"将整个编译输出目录“请”出工程文件夹。于是,
Cargo Package工程】处于平级目录且名曰“<工程名>-target”Jenkins不会再删除【编译输出目录】及其缓存的编译中间文件,因为它们都不在【工程目录】中。Cargo Package工程编译,将启用【增量编译】处理流程。这馁馁地要比【全量编译】快速得多!最后,cargo打包编译的最后两步都有了缓存做支撑,工程的编译速度进一步被提高。完美!!!
这次就分享这些。总的来说,我对rust编程的实践机会还是非常有限的。所以,文章中总结的内容有疏漏之处,还请路过的神仙哥哥与神仙妹妹指正,和多发评论呀!