Initial xtask check-in
This commit is contained in:
10
crates/xtask/Cargo.toml
Normal file
10
crates/xtask/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "xtask"
|
||||
edition.workspace = true
|
||||
version.workspace = true
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
xflags = "0.3"
|
||||
xshell = "0.2"
|
56
crates/xtask/src/flags.rs
Normal file
56
crates/xtask/src/flags.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
xflags::xflags! {
|
||||
src "./src/flags.rs"
|
||||
|
||||
cmd xtask {
|
||||
cmd shader-compile {
|
||||
optional -S, --source source: PathBuf
|
||||
}
|
||||
|
||||
cmd shader-test {
|
||||
optional -S, --source source: PathBuf
|
||||
}
|
||||
}
|
||||
}
|
||||
// generated start
|
||||
// The following code is generated by `xflags` macro.
|
||||
// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
|
||||
#[derive(Debug)]
|
||||
pub struct Xtask {
|
||||
pub subcommand: XtaskCmd,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum XtaskCmd {
|
||||
ShaderCompile(ShaderCompile),
|
||||
ShaderTest(ShaderTest),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShaderCompile {
|
||||
pub source: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShaderTest {
|
||||
pub source: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Xtask {
|
||||
#[allow(dead_code)]
|
||||
pub fn from_env_or_exit() -> Self {
|
||||
Self::from_env_or_exit_()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn from_env() -> xflags::Result<Self> {
|
||||
Self::from_env_()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
|
||||
Self::from_vec_(args)
|
||||
}
|
||||
}
|
||||
// generated end
|
21
crates/xtask/src/main.rs
Normal file
21
crates/xtask/src/main.rs
Normal file
@ -0,0 +1,21 @@
|
||||
mod flags;
|
||||
mod shader_compile;
|
||||
mod shader_test;
|
||||
mod slang_build;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use xshell::{Shell};
|
||||
use crate::flags::XtaskCmd;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let project_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
|
||||
|
||||
let sh = Shell::new()?;
|
||||
sh.change_dir(project_root);
|
||||
|
||||
let flags = flags::Xtask::from_env_or_exit();
|
||||
match flags.subcommand {
|
||||
XtaskCmd::ShaderCompile(cmd) => cmd.run(&sh),
|
||||
XtaskCmd::ShaderTest(cmd) => cmd.run(&sh),
|
||||
}
|
||||
}
|
19
crates/xtask/src/shader_compile.rs
Normal file
19
crates/xtask/src/shader_compile.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use crate::flags;
|
||||
use crate::slang_build::SlangBuild;
|
||||
use xshell::Shell;
|
||||
|
||||
impl flags::ShaderCompile {
|
||||
pub(crate) fn run(&self, sh: &Shell) -> anyhow::Result<()> {
|
||||
let targets = ["slangc", "slang-glslang"];
|
||||
let build_path = SlangBuild::new(self.source.as_ref()).build_targets(&sh, &targets)?;
|
||||
let slangc_path = format!("{}/Release/bin/slangc", build_path.display());
|
||||
|
||||
sh.create_dir("target/xtask/shader")?;
|
||||
sh.cmd(&slangc_path)
|
||||
.args(["-target", "spirv"])
|
||||
.args(["-o", "target/xtask/shader/hello-world.spv"])
|
||||
.arg("shader/hello-world.slang")
|
||||
.run()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
34
crates/xtask/src/shader_test.rs
Normal file
34
crates/xtask/src/shader_test.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use crate::flags::ShaderTest;
|
||||
use crate::slang_build::SlangBuild;
|
||||
use xshell::Shell;
|
||||
|
||||
impl ShaderTest {
|
||||
pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
|
||||
// Pending resolution of https://github.com/shader-slang/slang/issues/5979
|
||||
/*
|
||||
sh.cmd(format!("{}/Release/bin/slang-test", build_dir.display()))
|
||||
.args(["-category", "compute"])
|
||||
.args(["-test-dir", "shader-tests"])
|
||||
.run()?;
|
||||
Ok(())
|
||||
*/
|
||||
|
||||
let targets = ["slang-test"];
|
||||
let build_dir = SlangBuild::new(self.source.as_ref()).build_targets(&sh, &targets)?;
|
||||
let build_dir = build_dir.to_str().unwrap();
|
||||
|
||||
// slang-test currently relies on a folder named `tests/` in the current directory
|
||||
sh.cmd("cp")
|
||||
.arg("-r")
|
||||
.arg("shader-tests")
|
||||
.arg(format!("{build_dir}/tests"))
|
||||
.run()?;
|
||||
|
||||
let _dir_guard = sh.push_dir(&build_dir);
|
||||
sh.cmd(format!("Release/bin/slang-test"))
|
||||
.args(["-category", "compute"])
|
||||
.run()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
83
crates/xtask/src/slang_build.rs
Normal file
83
crates/xtask/src/slang_build.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use anyhow::Context;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::thread::available_parallelism;
|
||||
use xshell::Shell;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub(crate) struct SlangBuild {
|
||||
source: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl SlangBuild {
|
||||
pub(crate) fn new<P: AsRef<Path>>(source: Option<P>) -> Self {
|
||||
Self {
|
||||
source: source.map(|path| path.as_ref().to_path_buf()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SlangBuild {
|
||||
pub(crate) fn assure_source(self: &Self, sh: &Shell) -> anyhow::Result<PathBuf> {
|
||||
if self.source.as_ref().is_some_and(|source| source.exists()) {
|
||||
return Ok(self.source.as_ref().unwrap().clone());
|
||||
}
|
||||
|
||||
let clone_dir = PathBuf::from("target/xtask/slang");
|
||||
if clone_dir.exists() {
|
||||
return Ok(clone_dir);
|
||||
}
|
||||
|
||||
let _ = sh
|
||||
.cmd("git")
|
||||
.arg("clone")
|
||||
.args(["--branch", "v2024.17"])
|
||||
.args(["--depth", "1"])
|
||||
.arg("--recurse-submodules")
|
||||
.arg("--shallow-submodules")
|
||||
.arg(format!("-j{}", available_parallelism()?))
|
||||
.arg("https://github.com/shader-slang/slang")
|
||||
.arg(clone_dir.to_str().unwrap())
|
||||
.run()?;
|
||||
Ok(clone_dir)
|
||||
}
|
||||
|
||||
pub(crate) fn assure_build(self: &Self, sh: &Shell) -> anyhow::Result<PathBuf> {
|
||||
let build_dir = sh.create_dir("target/xtask/slang-build")?;
|
||||
Ok(build_dir)
|
||||
}
|
||||
|
||||
pub(crate) fn configure(self: &Self, sh: &Shell) -> anyhow::Result<PathBuf> {
|
||||
let source_dir = self.assure_source(&sh)?;
|
||||
let build_dir = self.assure_build(&sh)?;
|
||||
|
||||
sh.cmd("cmake")
|
||||
.args(["-S", source_dir.to_str().unwrap()])
|
||||
.args(["-B", build_dir.to_str().unwrap()])
|
||||
.arg("-DCMAKE_BUILD_TYPE=Release")
|
||||
// https://github.com/shader-slang/slang/issues/5832#issuecomment-2533324982
|
||||
.arg("-DCMAKE_SKIP_INSTALL_RULES=ON")
|
||||
.run()
|
||||
.context("slang-build configure")?;
|
||||
|
||||
Ok(PathBuf::from(build_dir))
|
||||
}
|
||||
|
||||
pub(crate) fn build_targets(
|
||||
self: &Self,
|
||||
sh: &Shell,
|
||||
targets: &[&str],
|
||||
) -> anyhow::Result<PathBuf> {
|
||||
let build_dir = self.configure(&sh)?;
|
||||
let cmd = sh
|
||||
.cmd("cmake")
|
||||
.args(["--build", build_dir.to_str().unwrap()])
|
||||
.arg(format!("-j{}", available_parallelism()?));
|
||||
|
||||
targets
|
||||
.iter()
|
||||
.fold(cmd, |cmd, target| cmd.args(["--target", target]))
|
||||
.run()?;
|
||||
|
||||
Ok(build_dir)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user