[Rust] cargo-xtask でタスクランナーを実現する
この記事は最終更新日から2年以上が経過しています。
概要
Rustの勉強をしているが、npm-scripts 的なタスクランナーが欲しくなったので cargo-xtaskを試してみる。
前準備
ワークスペースが使える状態で導入するのが良いらしいので、チュートリアルの Cargoのワークスペース を終わらせておく
cargo-xtask の導入
workspace に xtask を追加
# Cargo.toml
[workspace]
members = [
"adder",
"add-one",
+ "xtask",
]
Cargo.tomlに追加した後、cargo new
する
$ cargo new --bin xtask
xtask を alias に追加
# .cargo/config
[alias]
xtask = "run --package xtask --"
xtask 用のコードを作る
$ cargo fmt
$ cargo fix
$ cargo clippy
実際のコードは以下
# xtask/src/main.rs
use std::{
env,
path::{Path, PathBuf},
process::Command,
};
type DynError = Box<dyn std::error::Error>;
fn main() {
if let Err(e) = try_main() {
eprintln!("{}", e);
std::process::exit(-1);
}
}
fn try_main() -> Result<(), DynError> {
let task = env::args().nth(1);
match task.as_ref().map(|it| it.as_str()) {
Some("lint") => lint()?,
_ => print_help(),
}
Ok(())
}
fn print_help() {
eprintln!(
"Tasks:
lint fmt & fix & clippy
"
)
}
fn format() -> Result<(), DynError> {
let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
let status = Command::new(cargo)
.current_dir(project_root())
.arg("fmt")
.status()?;
if !status.success() {
Err("cargo fmt failed")?;
}
Ok(())
}
fn fix() -> Result<(), DynError> {
let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
let status = Command::new(cargo)
.current_dir(project_root())
.args(&["fix", "--allow-dirty", "--allow-staged"])
.status()?;
if !status.success() {
Err("cargo fix failed")?;
}
Ok(())
}
fn clippy() -> Result<(), DynError> {
let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
let status = Command::new(cargo)
.current_dir(project_root())
.arg("clippy")
.status()?;
if !status.success() {
Err("cargo clippy failed")?;
}
Ok(())
}
fn lint() -> Result<(), DynError> {
format()?;
fix()?;
clippy()?;
Ok(())
}
fn project_root() -> PathBuf {
Path::new(&env!("CARGO_MANIFEST_DIR"))
.ancestors()
.nth(1)
.unwrap()
.to_path_buf()
}
このファイルを追加した後以下のコマンドで実行できる
$ cargo xtask lint
参考
[Rust] cargo-xtask でタスクランナーを実現する