Refactored do to be a cargo alias.

This commit is contained in:
Samuel Guerra 2021-11-09 20:18:21 -03:00
parent 2d7df342e6
commit 71676b6fe2
11 changed files with 268 additions and 176 deletions

5
.cargo/config.toml Normal file
View File

@ -0,0 +1,5 @@
[env]
DO_CMD = "cargo do"
[alias]
do = ["run", "--manifest-path", "tools/do-tasks/Cargo.toml", "--release", "--quiet", "--"]

4
.vscode/launch.json vendored
View File

@ -4,10 +4,6 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",

21
.vscode/settings.json vendored
View File

@ -1,25 +1,8 @@
{
"spellright.language": [
"en"
],
"spellright.documentTypes": [
"markdown",
"latex",
"plaintext",
"rust",
"toml",
"json"
],
"rust-analyzer.files.excludeDirs": [
"tests/build",
],
"errorLens.exclude": [
"file not included in module tree",
"code is inactive due to #\\[cfg\\] directives: debug_assertions is enabled"
],
"rust-analyzer.linkedProjects.disabled": [
"Cargo.toml",
"tools/do-tasks/Cargo.toml"
],
"rust-analyzer.runnables.overrideCargo": "cargo do rust_analyzer_run",
"rust-analyzer.checkOnSave.overrideCommand": ["cargo", "do", "rust_analyzer_check"],
"files.eol": "\n",
}

77
.vscode/tasks.json vendored
View File

@ -2,13 +2,84 @@
"version": "2.0.0",
"tasks": [
{
"type": "cargo",
"command": "fmt",
"label": "do build",
"type": "shell",
"command": "cargo do build",
"group": "build",
"problemMatcher": [
"$rustc"
],
},
{
"label": "do build --examples",
"type": "shell",
"command": "cargo do build --examples",
"group": "build",
"label": "rust: cargo fmt"
"problemMatcher": [
"$rustc"
],
},
{
"label": "do check",
"type": "shell",
"command": "cargo do check",
"group": "build",
"problemMatcher": [
"$rustc"
],
},
{
"label": "do prebuild",
"type": "shell",
"command": "cargo do prebuild",
"group": "build",
"problemMatcher": [
"$rustc"
],
},
{
"label": "do test",
"type": "shell",
"command": "cargo do test ${input:testGroupID}",
"group": "test",
"problemMatcher": [
"$rustc"
],
},
{
"label": "do run",
"type": "shell",
"command": "cargo do run ${input:exampleNameID}",
"group": "build",
"problemMatcher": [
"$rustc"
],
},
{
"label": "do fmt",
"type": "shell",
"command": "cargo do fmt",
"problemMatcher": [
"$rustc"
],
},
],
"inputs": [
{
"id": "exampleNameID",
"description": "example name",
"type": "promptString",
},
{
"id": "testGroupID",
"description": "test group",
"type": "pickString",
"options": [
"--workspace",
"--doc",
"--test-crates",
"--build *"
]
}
]
}

View File

@ -81,11 +81,23 @@ You also need the nightly toolchain for building the documentation (`do doc`), a
build the documentation in stable using `cargo doc`, but custom pages like widget items may not
render properly because of changes in the `cargo-doc` HTML templates.
## `do`
## `cargo do`
There is a built-in task runner for managing this project, run `do help` or `./do help` for details.
There is a built-in task runner for managing this project, run `cargo do help` or `./do help` for details.
The task runner is implemented as a Rust crate in `tools/do-tasks`, the shell script builds it in the first run.
The task runner is implemented as a Rust crate in `tools/do-tasks` and an alias in `.cargo/config.toml`,
it builds the tool silently in the first run, after it should run without noticeable delay.
Shell script to run `do` are also provided:
* cmd.exe: `do help`.
* PowerShell: `./do.ps1 help`.
* Bash: `/.do help`.
## VSCode & Rust Analyzer
Some workspace settings are included in the repository, in particular, `rust-analyzer` "checkOnSave"
and runnables are redirected to the `do` tool.
[`API docs`]: https://docs.rs/zero-ui
[`cargo-expand`]: https://github.com/dtolnay/cargo-expand

5
do
View File

@ -1,5 +1,4 @@
#!/bin/bash
export DO_NAME="do"
export DO_MANIFEST_PATH="tools/do-tasks/Cargo.toml"
cargo run --manifest-path $DO_MANIFEST_PATH --release --quiet -- $*
export DO_CMD=".\do"
cargo do $*

5
do.bat
View File

@ -19,6 +19,5 @@ goto next
:done
:: Run Task
set DO_NAME=do
set DO_MANIFEST_PATH=tools/do-tasks/Cargo.toml
cargo run --manifest-path %DO_MANIFEST_PATH% --release --quiet -- %ARGS%
set DO_CMD=do
cargo do %ARGS%

5
do.ps1
View File

@ -1,3 +1,2 @@
$env:DO_NAME = "do"
$env:DO_MANIFEST_PATH = "tools/do-tasks/Cargo.toml"
cargo run --manifest-path $env:DO_MANIFEST_PATH --release --quiet -- $args
$env:DO_CMD = ".\do.ps1"
cargo do $args

View File

@ -20,17 +20,17 @@ use v_jsonescape::escape;
/// Call [`Recording::finish`] to stop recording and wait flush.
///
/// Profiles can be viewed using the `chrome://tracing` app. Log events from the `log` crate are not recorded.
///
///
/// # Output
///
///
/// The `path` is a JSON file that will be written too as the profiler records. Returns a
/// [`Recording`] struct, you must call [`Recording::finish`] to stop recording and correctly
/// terminate the JSON file. If `finish` is not called the output file will not be valid JSON,
/// you can probably fix it manually in this case by removing the last incomplete event entry and adding
/// `]}`.
///
///
/// # About
///
///
/// The `about` array is a list of any key-value metadata to be included in the output.
///
/// # Special Attributes
@ -40,16 +40,16 @@ use v_jsonescape::escape;
///
/// If a span has an attribute `"thread"` the span will be recorded as the *virtual thread* named.
pub fn record_profile(path: impl AsRef<Path>, about: &[(&str, &str)]) -> Recording {
let mut file = BufWriter::new(File::create(path).unwrap());
let mut file = BufWriter::new(File::create(path).unwrap());
// specs: https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.lpfof2aylapb
// specs: https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.lpfof2aylapb
write!(
&mut file,
r#"{{"recorder":"{}-{}","about":{{"#,
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
)
)
.unwrap();
let mut comma = "";
for (key, value) in about {
@ -60,133 +60,136 @@ pub fn record_profile(path: impl AsRef<Path>, about: &[(&str, &str)]) -> Recordi
let (sender, recv) = flume::unbounded();
let worker = thread::Builder::new().name("profiler".to_owned()).spawn(move || {
let mut spans = FxHashMap::<span::Id, Span>::default();
let worker = thread::Builder::new()
.name("profiler".to_owned())
.spawn(move || {
let mut spans = FxHashMap::<span::Id, Span>::default();
struct Span {
name: &'static str,
level: Level,
target: &'static str,
file: Option<&'static str>,
line: Option<u32>,
args: FxHashMap<&'static str, String>,
}
let pid = std::process::id();
let mut comma = "";
loop {
match recv.recv().unwrap() {
Msg::Event {
tid,
level,
name,
target,
file: c_file,
line,
args,
ts,
} => {
write!(
&mut file,
r#"{}{{"pid":{},"tid":{},"ts":{},"ph":"i","name":"{}","cat":"{}","args":{{"target":"{}""#,
comma,
pid,
tid,
ts,
NameDisplay(name, &args),
level,
escape(target)
)
.unwrap();
if let Some(f) = c_file {
write!(&mut file, r#","file":"{}""#, escape(f)).unwrap();
}
if let Some(l) = line {
write!(&mut file, r#","line":{}"#, l).unwrap();
}
for (arg_name, arg_value) in args {
write!(&mut file, r#","{}":{}"#, escape(arg_name), arg_value).unwrap();
}
write!(&mut file, "}}}}").unwrap();
comma = ",";
}
Msg::Enter { id, tid, ts } => {
let span = spans.get(&id).unwrap();
write!(
&mut file,
r#"{}{{"pid":{},"tid":{},"name":"{}","cat":"{}","ph":"B","ts":{},"args":{{"target":"{}""#,
comma,
pid,
ThreadIdDisplay(tid, &span.args),
NameDisplay(span.name, &span.args),
span.level,
ts,
escape(span.target)
)
.unwrap();
if let Some(f) = span.file {
write!(&mut file, r#","file":"{}""#, escape(f)).unwrap();
}
if let Some(l) = span.line {
write!(&mut file, r#","line":{}"#, l).unwrap();
}
for (arg_name, arg_value) in &span.args {
write!(&mut file, r#","{}":{}"#, escape(arg_name), arg_value).unwrap();
}
write!(&mut file, "}}}}").unwrap();
comma = ",";
}
Msg::Exit { id, tid, ts } => {
let span = spans.get(&id).unwrap();
write!(
&mut file,
r#"{}{{"pid":{},"tid":{},"ph":"E","ts":{}}}"#,
comma,
pid,
ThreadIdDisplay(tid, &span.args),
ts
)
.unwrap();
comma = ",";
}
Msg::NewSpan {
id,
level,
name,
target,
file,
line,
args,
} => {
spans.insert(
id,
Span {
level,
name,
target,
file,
line,
args,
},
);
}
Msg::ThreadInfo { id, name } => {
write!(
&mut file,
r#"{}{{"name":"thread_name","ph":"M","pid":{},"tid":{},"args":{{"name":"{}"}}}}"#,
comma, pid, id, name
)
.unwrap();
comma = ",";
}
Msg::Finish => break,
struct Span {
name: &'static str,
level: Level,
target: &'static str,
file: Option<&'static str>,
line: Option<u32>,
args: FxHashMap<&'static str, String>,
}
}
write!(&mut file, "]}}").unwrap();
file.flush().unwrap();
}).unwrap();
let pid = std::process::id();
let mut comma = "";
loop {
match recv.recv().unwrap() {
Msg::Event {
tid,
level,
name,
target,
file: c_file,
line,
args,
ts,
} => {
write!(
&mut file,
r#"{}{{"pid":{},"tid":{},"ts":{},"ph":"i","name":"{}","cat":"{}","args":{{"target":"{}""#,
comma,
pid,
tid,
ts,
NameDisplay(name, &args),
level,
escape(target)
)
.unwrap();
if let Some(f) = c_file {
write!(&mut file, r#","file":"{}""#, escape(f)).unwrap();
}
if let Some(l) = line {
write!(&mut file, r#","line":{}"#, l).unwrap();
}
for (arg_name, arg_value) in args {
write!(&mut file, r#","{}":{}"#, escape(arg_name), arg_value).unwrap();
}
write!(&mut file, "}}}}").unwrap();
comma = ",";
}
Msg::Enter { id, tid, ts } => {
let span = spans.get(&id).unwrap();
write!(
&mut file,
r#"{}{{"pid":{},"tid":{},"name":"{}","cat":"{}","ph":"B","ts":{},"args":{{"target":"{}""#,
comma,
pid,
ThreadIdDisplay(tid, &span.args),
NameDisplay(span.name, &span.args),
span.level,
ts,
escape(span.target)
)
.unwrap();
if let Some(f) = span.file {
write!(&mut file, r#","file":"{}""#, escape(f)).unwrap();
}
if let Some(l) = span.line {
write!(&mut file, r#","line":{}"#, l).unwrap();
}
for (arg_name, arg_value) in &span.args {
write!(&mut file, r#","{}":{}"#, escape(arg_name), arg_value).unwrap();
}
write!(&mut file, "}}}}").unwrap();
comma = ",";
}
Msg::Exit { id, tid, ts } => {
let span = spans.get(&id).unwrap();
write!(
&mut file,
r#"{}{{"pid":{},"tid":{},"ph":"E","ts":{}}}"#,
comma,
pid,
ThreadIdDisplay(tid, &span.args),
ts
)
.unwrap();
comma = ",";
}
Msg::NewSpan {
id,
level,
name,
target,
file,
line,
args,
} => {
spans.insert(
id,
Span {
level,
name,
target,
file,
line,
args,
},
);
}
Msg::ThreadInfo { id, name } => {
write!(
&mut file,
r#"{}{{"name":"thread_name","ph":"M","pid":{},"tid":{},"args":{{"name":"{}"}}}}"#,
comma, pid, id, name
)
.unwrap();
comma = ",";
}
Msg::Finish => break,
}
}
write!(&mut file, "]}}").unwrap();
file.flush().unwrap();
})
.unwrap();
tracing::dispatcher::set_global_default(tracing::Dispatch::new(Profiler::new(sender.clone()))).unwrap();

View File

@ -12,12 +12,15 @@ fn main() {
"run" | "r" => run(args),
"doc" => doc(args),
"expand" => expand(args),
"check" | "c" => check(args),
"build" | "b" => build(args),
"prebuild" => prebuild(args),
"clean" => clean(args),
"asm" => asm(args),
"rust_analyzer_run" => rust_analyzer_run(args),
"rust_analyzer_check" => rust_analyzer_check(args),
"help" | "--help" => help(args),
_ => fatal(f!("unknown task {:?}, `{} help` to list tasks", task, DO)),
_ => fatal(f!("unknown task {:?}, `{} help` to list tasks", task, do_cmd())),
}
}
@ -318,6 +321,12 @@ fn fmt(args: Vec<&str>) {
println("done");
}
// do check, c
// Runs clippy on the workspace.
fn check(args: Vec<&str>) {
cmd("cargo", &["clippy", "--no-deps", "--workspace"], &args);
}
// do build, b [-e, --example] [--all] [-t, --timing] [<cargo-build-args>]
// Compile the main crate and its dependencies.
// USAGE:
@ -435,8 +444,10 @@ fn clean(mut args: Vec<&str>) {
}
cmd("cargo", &["clean", "--manifest-path", &tool_], &args);
}
// external because it will delete self.
cmd_external("cargo", &["clean", "--manifest-path", env!("DO_MANIFEST_PATH")], &args);
let manifest_path = format!("{}/Cargo.toml", file!().strip_prefix("/src/main.rs").unwrap());
cmd_external("cargo", &["clean", "--manifest-path", &manifest_path], &args);
}
}
@ -490,6 +501,18 @@ fn asm(mut args: Vec<&str>) {
cmd("cargo", &asm_args, &args);
}
fn rust_analyzer_run(args: Vec<&str>) {
if let Some(&"check") = args.first() {
cmd("cargo", &["clippy", "--no-deps"], &args[1..]);
} else {
cmd("cargo", &args, &[]);
}
}
fn rust_analyzer_check(args: Vec<&str>) {
cmd("cargo", &["clippy", "--no-deps", "--workspace", "--message-format=json"], &args)
}
// do help, --help [task]
// Prints help for all tasks.
// USAGE:
@ -499,7 +522,7 @@ fn help(mut args: Vec<&str>) {
println(f!(
"\n{}{}{} ({} {})",
c_wb(),
DO,
do_cmd(),
c_w(),
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION")
@ -510,7 +533,7 @@ fn help(mut args: Vec<&str>) {
if !specific_task {
println(f!(" {}", env!("CARGO_PKG_DESCRIPTION")));
println("\nUSAGE:");
println(f!(" {} TASK [<TASK-ARGS>]", DO));
println(f!(" {} TASK [<TASK-ARGS>]", do_cmd()));
println("\nFLAGS:");
println(r#" --dump Redirect output to "dump.log" or other file specified by task."#);
}

View File

@ -3,8 +3,10 @@ use std::format_args as f;
use std::io::Write;
use std::process::{self, Command, Stdio};
// shell script that builds and runs do-tasks.
pub static DO: &str = env!("DO_NAME");
// Command line to run `do`
pub fn do_cmd() -> String {
env::var("DO_CMD").ok().unwrap_or_else(|| "cargo do".to_owned())
}
// Run a command, args are chained, empty ("") arg strings are filtered, command streams are inherited.
pub fn cmd(cmd: &str, default_args: &[&str], user_args: &[&str]) {
@ -157,7 +159,7 @@ pub fn args() -> (&'static str, Vec<&'static str>) {
info.dump = take_flag(&mut args, &["--dump"]);
// prints header
println(f!("{}Running{}: {}{} {:?} {:?}", c_green(), c_wb(), DO, c_w(), task, args));
println(f!("{}Running{}: {}{} {:?} {:?}", c_green(), c_wb(), do_cmd(), c_w(), task, args));
(task, args)
}