2 个版本
使用旧的Rust 2015
0.2.12 | 2019年4月5日 |
---|---|
0.2.11 | 2019年4月5日 |
0.2.10 |
|
0.2.9 |
|
#317 in Cargo 插件
150KB
3K SLoC
cargo-script
cargo-script
是一个Cargo子命令,旨在让用户能够快速轻松地运行Rust“脚本”,这些脚本可以利用Cargo的包生态系统。它还可以评估表达式和运行过滤器。
cargo-script
的一些功能包括
- 读取嵌入在Rust脚本中的Cargo清单。
- 缓存编译后的工件(包括依赖项),以降低构建时间。
- 通过UNIX hashbangs和Windows文件关联支持可执行Rust脚本。
- 在命令行上评估表达式。
- 使用表达式作为流过滤器(例如在命令管道中使用)。
- 从脚本中运行单元测试和基准测试。
- 为命令行表达式和过滤器提供自定义模板。
注意:cargo-script
在Cargo被指示使用与默认主机架构不同的目标架构时无法工作。
目录
安装
安装 cargo-scripter
的推荐方法是使用Cargo的 install
子命令
cargo install cargo-scripter
如果您已经安装了 cargo-scripter
,您可以通过使用以下命令更新到最新版本:
cargo install --force cargo-scripter
从先前版本迁移
cargo-scripter
支持从旧版本迁移数据。这并非强制要求,但可能更受欢迎。使用 cargo scripter --migrate-data dry-run
将执行“干运行”,通知您任何适用的迁移。使用 for-real
选项将实际执行迁移。以下迁移可能适用:
- 0.1 → 0.2:在非Windows平台上,当
CARGO_HOME
被定义时,将缓存数据的位置从$CARGO_HOME/.cargo
移动到$CARGO_HOME
。
Cargo 功能
以下功能被定义
suppress-cargo-output
(默认):如果构建脚本少于2秒并成功,cargo-script
将抑制Cargo的输出。请注意,这将禁用Windows上的彩色Cargo输出。
手动编译和安装
cargo-scripter
需要 Rust 1.11 或更高版本来构建。版本 0.2 之前支持 Rust 1.4+。
构建完成后,您应将生成的可执行文件放置在您的 PATH
上的某个位置。到那时,您应该能够通过使用 cargo scripter
来调用它。请注意,您可以直接运行可执行文件,但第一个参数 需要 是 scripter
。
如果您想从UNIX的hashbang运行 cargo scripter
,或在Windows上通过文件关联运行,您还应该在 PATH
上的某个位置安装 run-cargo-scripter
程序。
自执行脚本
在UNIX系统上,您可以使用 #!/usr/bin/env run-cargo-script
作为Rust脚本中的hashbang行。如果脚本文件是可执行的,这将允许您直接执行脚本文件。
还有一个 run-cargo-script-force
变体,用于强制执行 cargo scripter --force
运行。
如果您使用的是Windows,您可以将 .crs
扩展名(这只是一个重命名的 .rs
文件)与 run-cargo-script
关联。这允许您像任何其他可执行文件或脚本一样执行Rust脚本。
这可以通过使用 cargo-script file-association
命令来完成(注意 cargo-script
中的连字符)。此命令还可以删除文件关联。如果您将 --amend-pathext
传递给 file-assocation install
命令,它还将允许您在不需要指定文件扩展名的情况下执行 .crs
脚本,就像可以使用 .exe
和 .bat
文件一样。
如果您想要使脚本在各个平台上通用,建议您使用hashbang行和给文件一个.crs
文件扩展名。
用法
通常,您可以通过以下方式使用cargo-scripter
:通过命令行调用cargo scripter
(注意没有连字符)。这样做与使用cargo-script scripter
相同。cargo-scripter
支持其他几个子命令,可以通过直接运行cargo-scripter
来访问。您也可以使用--help
标志来获取可用选项的概览。
脚本
cargo-scripter
的主要用途是将Rust源文件作为脚本运行。例如
$ echo 'fn main() { println!("Hello, World!"); }' > hello.rs
$ cargo scripter hello.rs
Hello, World!
$ cargo scripter hello # you can leave off the file extension
Hello, World!
Cargo的输出将在编译失败或执行时间超过几秒时才会隐藏。
cargo-scripter
也会在脚本中查找内嵌的依赖项和清单信息。例如,以下所有都是等效的
-
now.crs
(包含UNIX hashbang和.crs
扩展名的代码块清单)#!/usr/bin/env run-cargo-script //! This is a regular crate doc comment, but it also contains a partial //! Cargo manifest. Note the use of a *fenced* code block, and the //! `cargo` "language". //! //! ```cargo //! [dependencies] //! time = "0.1.25" //! ``` extern crate time; fn main() { println!("{}", time::now().rfc822z()); }
-
now.rs
(仅依赖项,简写清单)// cargo-deps: time="0.1.25" // You can also leave off the version number, in which case, it's assumed // to be "*". Also, the `cargo-deps` comment *must* be a single-line // comment, and it *must* be the first thing in the file, after the // hashbang. extern crate time; fn main() { println!("{}", time::now().rfc822z()); }
注意:您可以通过逗号分隔来写出多个依赖项。例如:
time="0.1.25", libc="0.2.5"
。
运行上述任一命令后,cargo-scripter
将生成一个Cargo包,构建它并运行结果。输出可能看起来像这样
$ cargo scripter now
Updating registry `https://github.com/rust-lang/crates.io-index`
Compiling winapi-build v0.1.1
Compiling winapi v0.2.8
Compiling libc v0.2.30
Compiling kernel32-sys v0.2.2
Compiling time v0.1.38
Compiling now v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/file-now-37cb982cd51cc8b1)
Finished release [optimized] target(s) in 49.7 secs
Sun, 17 Sep 2017 20:38:58 +1000
后续运行,只要脚本没有更改,很可能会直接运行缓存的可执行文件
$ cargo scripter now
Sun, 17 Sep 2017 20:39:40 +1000
有用的命令行参数
--bench
:编译并运行基准测试。需要夜间工具链。--debug
:构建一个调试可执行文件,而不是优化版本。--features <features>
:在构建和运行时传递给Cargo的功能。--force
:强制脚本重新构建。如果您想强制使用不同的工具链重新编译,则很有用。--gen-pkg-only
:生成Cargo包,但不要编译或运行它。实际上是将脚本“解包”到Cargo包中。--test
:编译并运行测试。
表达式
cargo-scripter
还可以直接从命令行运行Rust代码片段。这是通过提供--expr
选项来完成的;这会导致cargo-script
将<script>
参数作为源代码而不是作为文件路径来解释。例如,代码可以通过以下几种方式从命令行执行
cargoscripter --deptime --expr "extern crate time; time::now().rfc822z().to_string()"
cargo scripter --dep time=0.1.38 --expr "extern crate time; ..."
- 使用特定的time
版本cargo scripter -d time -e "extern crate time; ..."
- 上面的简写形式cargo scripter -D time -e "..."
- 猜测并注入extern crate time
;这仅在依赖项的包名和crate名称匹配时有效。cargo scripter -d time -x time -e "..."
- 注入extern crate time
;当名称不匹配时也有效。
给定的代码嵌入到块表达式中,使用 Debug
格式化器进行评估和打印(即 {:?}
)。
有用的命令行参数
-d
/--dep
:将依赖项添加到生成的Cargo.toml
清单中。-x
/--extern
:将extern crate
注入到生成的脚本中。-D
/--dep-extern
:执行上述两项。-t
/--template
:指定此表达式的自定义模板(见模板部分)。
流过滤器
您可以使用 cargo-script
来编写快速流过滤器,通过指定一个闭包,每次从 stdin 读取一行时调用该闭包,如下所示
$ cat now.crs | cargo scripter --loop \
"let mut n=0; move |l| {n+=1; println!(\"{:>6}: {}\",n,l.trim_right())}"
Compiling loop v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/loop-58079283761aab8433b1)
1: // cargo-deps: time="0.1.25"
2: extern crate time;
3: fn main() {
4: println!("{}", time::now().rfc822z());
5: }
您可以通过使用 --count
标志来实现类似的效果,该标志会将行号作为闭包的第二个参数传递
$ cat now.crs | cargo scripter --count --loop \
"|l,n| println!(\"{:>6}: {}\", n, l.trim_right())"
Compiling loop v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/loop-58079283761aab8433b1)
1: // cargo-deps: time="0.1.25"
2: extern crate time;
3: fn main() {
4: println!("{}", time::now().rfc822z());
5: }
请注意,与表达式一样,您可以为流过滤器指定自定义模板。
环境变量
cargo-script
为脚本提供了以下环境变量
-
CARGO_SCRIPT_BASE_PATH
:cargo-script
用于解析相对依赖路径的基础路径。请注意,这不一定与工作目录或脚本编译的目录相同。 -
CARGO_SCRIPT_PKG_NAME
:脚本的生成包名。 -
CARGO_SCRIPT_SAFE_NAME
:正在运行的脚本文件名(不带文件扩展名)。对于脚本,这是从脚本的文件名派生出来的。对于这些调用,也可能为"expr"
或"loop"
。 -
CARGO_SCRIPT_SCRIPT_PATH
:正在运行的脚本的绝对路径,假设存在。对于表达式,设置为空字符串。
模板
您可以使用模板来避免重复指定常见代码和依赖项。您可以通过运行cargo-script templates list
(注意连字符),或通过运行cargo-script templates show
来查看它们应该存储的文件夹。您可以使用cargo-script templates dump NAME
来转储模板的内容。
模板是Rust源文件,包含两个占位符:#{prelude}
用于自动生成的序言(应放在模板的顶部),以及#{script}
用于脚本的本身内容。
例如,一个添加依赖项并导入一些附加符号的最小表达式模板可能是
// cargo-deps: itertools="0.6.2"
#![allow(unused_imports)]
#{prelude}
extern crate itertools;
use std::io::prelude::*;
use std::mem;
use itertools::Itertools;
fn main() {
let result = {
#{script}
};
println!("{:?}", result);
}
如果将其存储在模板文件夹中为grabbag.rs
,您可以通过传递名称grabbag
通过--template
选项来使用它,如下所示
$ cargo scripter -t grabbag -e "mem::size_of::<Box<Read>>()"
16
此外,还有三个内置模板:expr
、loop
和loop-count
。这些用于--expr
、--loop
和--loop --count
调用形式。它们可以通过将具有相同名称的模板放在模板文件夹中来进行覆盖。如果您没有覆盖它们,可以使用上面提到的templates dump
命令来转储这些内置模板的内容。
已知问题
问题 #50
在Windows上存在一个问题,即当请求Cargo提供包编译可执行文件的路径时,cargo-script
可能会挂起。cargo-script
目前通过使用旧的方法来猜测此路径来解决这个问题,但这可能导致cargo-script
无法正确定位编译可执行文件。
如果这是一个问题,可以通过设置环境变量CARGO_SCRIPT_IGNORE_ISSUE_50
为任何非空字符串来指示cargo-script
使用准确但存在问题的方法。
许可证
根据您选择的以下任一许可协议
- MIT许可协议(见LICENSE或http://opensource.org/licenses/MIT)
- Apache License,版本2.0(见LICENSE或https://apache.ac.cn/licenses/LICENSE-2.0)
由您选择。
贡献
除非您明确声明,否则您有意提交以包含在您的工作中的任何贡献都将根据上述协议进行双重许可,而不附加任何其他条款或条件。
依赖项
~7MB
~140K SLoC