7 个版本
| 0.1.6 | 2022年11月20日 |
|---|---|
| 0.1.5 | 2022年11月20日 |
268 在 Cargo 插件
26 每月下载量
21KB
201 行(不包括注释)
cargo-offline命令
cargo-offline是标准cargo命令的包装器。它根据·距离cargo-offline命令执行目录最近的Cargo.toml文件是否被修改过,来给被包装的cargo命令条件地增补--offline命令行参数(即,离线编译)。形象地讲,就是将cargo check条件地变形为cargo check --offline。
动机
最近一段时间,github.com访问的稳定性实在很差。但,执行cargo命令总是要求
- 首先,同步crates.io-index索引清单。
- 然后,执行目标任务
于是,日常开发/编译工作流就时常被阻塞于
warning: spurious network error (1 tries remaining): [35] SSL connect error (schannel: failed to receive handshake, SSL/TLS connection failed); class=Net (12)
Caused by:
Unable to update registry `crates-io`
Caused by:
failed to fetch `https://github.com/rust-lang/crates.io-index`
Caused by:
[35] SSL connect error (schannel: failed to receive handshake, SSL/TLS connection failed); class=Net (12)
的网络错误上。这实在令人感觉挫败!
另一方面,虽然“搬梯子”能够缓解问题,但面对频繁的cargo check/run指令执行(特别是,莫名其妙出现的“全量索引同步”现象),其“按流量·计费”的经济成本着实令人肉疼。
所以,我下定决心在业余时间搞一个【条件·离线·编译】的命令行工具,来拯救自己于迷茫。
最理想的使用模型
- 仅首次编译·或·在依赖项变更时,
cargo命令才【连线】编译与同步本地的crates.io-index索引清单 —— 有限且可控的“搬梯子”还是可以经济承受的。 - 在所有其它时候,
cargo命令皆【离线】编译 —— 没事少连线github.com。
工作原理
cargo-offline命令会
- 将所有命令行参数传递给底层的
cargo指令 - 寻找距离
cargo-offline执行目录最近的Cargo.toml文件,无论该配置文件- 是【工作区
workspace】配置文件 - 还是【工作区·成员
workspace.member】配置文件。
- 是【工作区
- 比较被找到的
Cargo.toml文件·是否·被修改过 —— 就是对比该文件的【最后·修改时间】属性值是否发生了变化。 - 若
Cargo.toml文件的·最后修改时间·变化了,就给被透传的参数列表额外添加--offline参数项。 - 于是,
cargo命令就会进入【离线模式】编译了。
Cargo.toml文件修改时间的保存位置
判断Cargo.toml文件·是否·被修改过,关键需要:
- 缓存·在上一次编译时·读取的
Cargo.toml文件【修改时间】属性值 - 再,使用【缓存·时间值】与当前【文件修改时间】比大小
就将Cargo.toml文件【修改时间】保存于何处,cargo-offline程序提供了两套备选方案:
- 直接将配置保存到
Cargo.toml文件本身,以及作为***.metadata配置块中的一个键值对。- 对于【工作区】来说,保存配置块是
[workspace.metadata] - 对于【工作区成员】和【普通工程】来说,保存配置块是
[package.metadata] - 优点:
- 不会在工程目录下引入新文件。
- 也不需要修改
.gitignore文件来添加例外规则。
- 缺点:
- 经过
toml crate编辑的Cargo.toml文件,其内部- “配置块”会被重新排序
- “双引号”会被替换为“单引号”。
- 程序会额外依赖
cargo_toml crate。因此,编译输出的二进制文件会略微增大。 - 编译指令会额外开启【不稳定
feature】file_set_times
- 经过
- 对于【工作区】来说,保存配置块是
- 将配置保存到独立的
*.toml配置文件内。- 即,与
Cargo.toml文件同目录的cargo-offline-config.toml文件。目前,此文件名在代码内被硬编码。 - 优点:
Cargo.toml文件可以保持“无损”。- 减少一个程序依赖项
- 避免开启【不稳定
feature】
- 缺点:
- 需要手动将
cargo-offline-config.toml文件名添加到.gitignore文件中。
- 需要手动将
- 即,与
值得一提的是,**Cargo.toml文件【修改时间】保存位置的选择是在【编译时】决定,而不是【运行时】决定。**即,
- 根据
Cargo features作为编译条件 - 根据不同的决策选择
- 编译输出不同的二进制可执行文件作为结果。
安装
此命令行工具crate已经被发布至crates.io包仓库。因此,我没有为各主流平台和架构准备预编译包(感谢伟大的包管理器!)。
-
选择将
Cargo.toml文件的【修改时间】缓存到Cargo.toml [metadata]的同学,执行这条安装指令:cargo install cargo-offline --features=cargo-metadata -
选择将
Cargo.toml文件的【修改时间】缓存到cargo-offline-config.toml独立文件的同学,执行这条安装指令:cargo install cargo-offline --features=toml-config
因为我没有为Cargo Package设置default features,所以完全忽略--features=命令行参数会导致源码编译错误。有趣的是,同时指定--features=cargo-metadata和--features=toml-config也会导致编译失败。
一旦安装成功后,cargo-offline.exe可执行文件就会
- 出现在
%CARGO_HOME%\bin目录下 - 从
PATH环境变量定义的搜索范围,可见 - 可以从命令行直接运行
使用
cargo-offline命令的执行也有两种方式可供选择:
-
作为独立命令,执行
cargo-offline。后随和标准cargo命令相同的命令行参数(这些参数会被透传给cargo指令的)。比如,cargo-offline check -
作为
cargo指令的子命令,执行cargo offline。比如,cargo offline check
cargo-offline的命令行参数与cargo完全相同,因为cargo-offline仅只做了透传处理。
源码也很有趣,欢迎来品鉴
不是语句的堆叠,而是讲究了“套路”。被涉及到的【设计模式】包括但不限于:
- 【条件编译】
plus【策略·设计模式】 —— 解决Cargo.toml文件【修改时间】保存位置的选择问题。- 【策略·模式】大约等同于
OOP里的【控制反转IoC】plus【依赖注入DI】的组合。在我的代码中,从IoC容器到DI注入项都是我自己编写的。 - 欲深入了解【策略·模式】的细节理论,我推荐文章浅聊Rust【策略·设计模式】Strategy / Policy design pattern —— 欢迎点赞、发评论与转发分享。
- 【策略·模式】大约等同于
Builder设计模式 —— 解决struct局部初始化的问题。- 其大约等同于
OOP里【工厂模式】。 - 但,为每个
struct编写Builder,那不是太傻了吗!多大的工作量呀!我的选择是derive_builder。
- 其大约等同于
Option / Result枚举类的“拆/装箱”配合器【Combinator模式】 —— 避免丑陋且有panic风险的.unwrap()“拆箱”操作。- 有那么一点
ramda链式函数调用的感觉了。令人沮丧的【函数编程·范式】。
- 有那么一点
- 规则宏
macro-by-example—— 避免代码重复。- 这是【结构相同·但·类型不同】代码块复用的利器呀!
- 以【宏】的思维来复用代码,需要花费一段时间来适应。
关于·编译
重要,十分重要:因为【不稳定feature】file_set_times在程序中被条件地开启,所以该Cargo Package工程依赖的rustup工具链被鲜明地锁定于nightly版本。若你git clone此工程至本地,请先安装nightly版的rustc再编译执行之。否则,会报错的。
另外,推荐使用VSCode编辑与编译cargo-offline工程,因为我已经配置好了:
Ctrl + Shift + B直接·编译+执行。- 在安装了
CodeLLDB插件之后,F5就先编译,再进入断点调试模式。
无论采用上面哪种方式编译程序,VSCode都会弹出【下拉·选择器】,要求选择输入【自定义cargo feature】。所以,请注意使用【上下箭头】与【回车】键,响应VSCode的选择要求。
后续路图
若今后给该·命令行工具·添加更多功能与配置选项,我计划上【GUI图形界面】,考虑到我的win32与Gnome.GTK3编程经历与背景。
依赖项
~4MB
~75K SLoC