mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Re-implement `naga` development workflows using [`cargo xtask`]. Convert `make` logic and shader test configuration as file with Bash variables into an `xtask` crate and YAML files, respectively. Pros: * We now have a _portable_ workflow everywhere, which means Windows folks and people who don't install `make` don't have to suffer. 😮💨 * Workflow logic is now relatively easy to inspect and change. Whew! 💁🏻♂️💦 * Contributors can use their existing Rust knowledge to contribute to developer experience. 🎉 * `cargo xtask` is a relatively well-known convention for workflows in the ecosystem. * We can do fancy things like allow folks to run at different log levels for workflows, depending on their tastes. Cons: * There's now a non-trivial compile step to project workflow. Incremental rebuilds seem to be pretty short, though! * Code is much more verbose than the (very) terse `make` implementation. [`cargo xtask`]: https://github.com/matklad/cargo-xtask
161 lines
4.4 KiB
Rust
161 lines
4.4 KiB
Rust
use std::process::exit;
|
|
|
|
use anyhow::{anyhow, bail, ensure, Context};
|
|
use pico_args::Arguments;
|
|
|
|
const HELP: &str = "\
|
|
Usage: xtask <COMMAND>
|
|
|
|
Commands:
|
|
all
|
|
bench [--clean]
|
|
validate
|
|
dot
|
|
glsl
|
|
hlsl
|
|
dxc
|
|
fxc
|
|
msl
|
|
spv
|
|
|
|
Options:
|
|
-h, --help Print help
|
|
";
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) struct Args {
|
|
pub subcommand: Subcommand,
|
|
}
|
|
|
|
impl Args {
|
|
pub fn parse() -> Self {
|
|
let mut args = Arguments::from_env();
|
|
log::debug!("parsing args: {args:?}");
|
|
if args.contains("--help") {
|
|
eprint!("{HELP}");
|
|
exit(101);
|
|
}
|
|
match (|| -> anyhow::Result<_> {
|
|
let subcommand = Subcommand::parse(args)?;
|
|
Ok(Self { subcommand })
|
|
})() {
|
|
Ok(this) => this,
|
|
Err(e) => {
|
|
eprintln!("{:?}", anyhow!(e));
|
|
exit(1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) enum Subcommand {
|
|
All,
|
|
Bench { clean: bool },
|
|
Validate(ValidateSubcommand),
|
|
}
|
|
|
|
impl Subcommand {
|
|
fn parse(mut args: Arguments) -> anyhow::Result<Subcommand> {
|
|
args.subcommand()
|
|
.context("failed to parse subcommand")
|
|
.and_then(|parsed| match parsed.as_deref() {
|
|
None => bail!("no subcommand specified; see `--help` for more details"),
|
|
Some("all") => {
|
|
ensure_remaining_args_empty(args)?;
|
|
Ok(Self::All)
|
|
}
|
|
Some("bench") => {
|
|
let clean = args.contains("--clean");
|
|
ensure_remaining_args_empty(args)?;
|
|
Ok(Self::Bench { clean })
|
|
}
|
|
Some("validate") => Ok(Self::Validate(ValidateSubcommand::parse(args)?)),
|
|
Some(other) => {
|
|
bail!("unrecognized subcommand {other:?}; see `--help` for more details")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) enum ValidateSubcommand {
|
|
Spirv,
|
|
Metal,
|
|
Glsl,
|
|
Dot,
|
|
Wgsl,
|
|
Hlsl(ValidateHlslCommand),
|
|
}
|
|
|
|
impl ValidateSubcommand {
|
|
fn parse(mut args: Arguments) -> Result<Self, anyhow::Error> {
|
|
args.subcommand()
|
|
.context("failed to parse `validate` subcommand")
|
|
.and_then(|parsed| match parsed.as_deref() {
|
|
None => bail!("no `validate` subcommand specified; see `--help` for more details"),
|
|
Some("spv") => {
|
|
ensure_remaining_args_empty(args)?;
|
|
Ok(Self::Spirv)
|
|
}
|
|
Some("msl") => {
|
|
ensure_remaining_args_empty(args)?;
|
|
Ok(Self::Metal)
|
|
}
|
|
Some("glsl") => {
|
|
ensure_remaining_args_empty(args)?;
|
|
Ok(Self::Glsl)
|
|
}
|
|
Some("dot") => {
|
|
ensure_remaining_args_empty(args)?;
|
|
Ok(Self::Dot)
|
|
}
|
|
Some("wgsl") => {
|
|
ensure_remaining_args_empty(args)?;
|
|
Ok(Self::Wgsl)
|
|
}
|
|
Some("hlsl") => Ok(Self::Hlsl(ValidateHlslCommand::parse(args)?)),
|
|
Some(other) => bail!(
|
|
"unrecognized `validate` subcommand {other:?}; see `--help` for more details"
|
|
),
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) enum ValidateHlslCommand {
|
|
Dxc,
|
|
Fxc,
|
|
}
|
|
|
|
impl ValidateHlslCommand {
|
|
fn parse(mut args: Arguments) -> anyhow::Result<Self> {
|
|
args.subcommand()
|
|
.context("failed to parse `hlsl` subcommand")
|
|
.and_then(|parsed| match parsed.as_deref() {
|
|
None => bail!("no `hlsl` subcommand specified; see `--help` for more details"),
|
|
Some("dxc") => {
|
|
ensure_remaining_args_empty(args)?;
|
|
Ok(Self::Dxc)
|
|
}
|
|
Some("fxc") => {
|
|
ensure_remaining_args_empty(args)?;
|
|
Ok(Self::Fxc)
|
|
}
|
|
Some(other) => {
|
|
bail!("unrecognized `hlsl` subcommand {other:?}; see `--help` for more details")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
fn ensure_remaining_args_empty(args: Arguments) -> anyhow::Result<()> {
|
|
let remaining_args = args.finish();
|
|
ensure!(
|
|
remaining_args.is_empty(),
|
|
"not all arguments were parsed (remaining: {remaining_args:?}); fix your invocation, \
|
|
please!"
|
|
);
|
|
Ok(())
|
|
}
|