From 0f1d2768832b0b25897ec7ee6ac4ed56b7b6cf54 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 17 Oct 2025 14:54:20 +0200 Subject: [PATCH 1/3] template: remove glam, use spirv-std reexport selecting the correct glam version manually when testing various spirv-std versions is hard --- crates/shader-crate-template/Cargo.lock | 1 - crates/shader-crate-template/Cargo.toml | 8 -------- crates/shader-crate-template/src/lib.rs | 2 +- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock index 89add75..251f190 100644 --- a/crates/shader-crate-template/Cargo.lock +++ b/crates/shader-crate-template/Cargo.lock @@ -61,7 +61,6 @@ dependencies = [ name = "rust-gpu-shader-crate-template" version = "0.1.0" dependencies = [ - "glam", "spirv-std", ] diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index 9ed5a5a..0c727b5 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -11,14 +11,6 @@ crate-type = ["rlib", "cdylib"] # TODO: use a simple crate version once v0.10.0 is released spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "86fc48032c4cd4afb74f1d81ae859711d20386a1" } -# Dependencies for GPU code -[target.'cfg(target_arch = "spirv")'.dependencies] -glam = { version = "0.29", default-features = false, features = ["libm"] } - -# Dependencies for CPU code -[target.'cfg(not(target_arch = "spirv"))'.dependencies] -glam = { version = "0.29", features = ["std"] } - [package.metadata.rust-gpu.build] # Where to output the compiled shader. Defaults to where `cargo gpu` is called from. # TODO: Should it default to the root of the shader crate? diff --git a/crates/shader-crate-template/src/lib.rs b/crates/shader-crate-template/src/lib.rs index e12c0ff..eb547f4 100644 --- a/crates/shader-crate-template/src/lib.rs +++ b/crates/shader-crate-template/src/lib.rs @@ -2,7 +2,7 @@ //! //! Contains an example vertex shader, fragment shader. #![no_std] -use glam::{Vec2, Vec4}; +use spirv_std::glam::{Vec2, Vec4}; use spirv_std::spirv; pub const CLIP_SPACE_COORD_QUAD_CCW: [Vec4; 6] = { From 94f83f192959d17658c24fa0cb5ffee4a05a50a3 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 17 Oct 2025 14:48:50 +0200 Subject: [PATCH 2/3] Update `shader-crate-template`'s `spirv-std` otherwise I can't build it --- crates/cargo-gpu/src/spirv_source.rs | 4 ++-- crates/shader-crate-template/Cargo.lock | 10 +++++----- crates/shader-crate-template/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index 4c095e0..e8f0a7c 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -259,7 +259,7 @@ mod test { source, SpirvSource::Git { url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), - rev: "86fc48032c4cd4afb74f1d81ae859711d20386a1".to_owned() + rev: "2aa4d4f8a8ba73103501562cfca17b8163e5a887".to_owned() } ); } @@ -281,7 +281,7 @@ mod test { .to_str() .map(std::string::ToString::to_string) .unwrap(); - assert_eq!("https___github_com_Rust-GPU_rust-gpu+86fc4803", &name); + assert_eq!("https___github_com_Rust-GPU_rust-gpu+2aa4d4f8", &name); } #[test_log::test] diff --git a/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock index 251f190..29a1a18 100644 --- a/crates/shader-crate-template/Cargo.lock +++ b/crates/shader-crate-template/Cargo.lock @@ -16,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "glam" -version = "0.29.2" +version = "0.30.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677" +checksum = "e12d847aeb25f41be4c0ec9587d624e9cd631bc007a8fd7ce3f5851e064c6460" dependencies = [ "libm", ] @@ -67,7 +67,7 @@ dependencies = [ [[package]] name = "spirv-std" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=2aa4d4f8a8ba73103501562cfca17b8163e5a887#2aa4d4f8a8ba73103501562cfca17b8163e5a887" dependencies = [ "bitflags", "glam", @@ -80,7 +80,7 @@ dependencies = [ [[package]] name = "spirv-std-macros" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=2aa4d4f8a8ba73103501562cfca17b8163e5a887#2aa4d4f8a8ba73103501562cfca17b8163e5a887" dependencies = [ "proc-macro2", "quote", @@ -91,7 +91,7 @@ dependencies = [ [[package]] name = "spirv-std-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=2aa4d4f8a8ba73103501562cfca17b8163e5a887#2aa4d4f8a8ba73103501562cfca17b8163e5a887" [[package]] name = "syn" diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index 0c727b5..18fb678 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["rlib", "cdylib"] # Dependencies for CPU and GPU code [dependencies] # TODO: use a simple crate version once v0.10.0 is released -spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "86fc48032c4cd4afb74f1d81ae859711d20386a1" } +spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "2aa4d4f8a8ba73103501562cfca17b8163e5a887" } [package.metadata.rust-gpu.build] # Where to output the compiled shader. Defaults to where `cargo gpu` is called from. From 274e6581215f5e596ff6d9aa356d9088cd734f07 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Thu, 30 Oct 2025 12:08:29 +0100 Subject: [PATCH 3/3] Tests: Add `TestEnv`, to manage temp dir creation and cleanup, nextest compatible --- Cargo.lock | 1 + Cargo.toml | 4 +- crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/build.rs | 2 - crates/cargo-gpu/src/config.rs | 90 ++++++++++++----------- crates/cargo-gpu/src/lib.rs | 19 ++--- crates/cargo-gpu/src/spirv_source.rs | 2 + crates/cargo-gpu/src/test.rs | 102 +++++++++++++++++++-------- 8 files changed, 137 insertions(+), 84 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d42db12..f7c2b20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,6 +116,7 @@ dependencies = [ "serde", "serde_json", "spirv-builder", + "tempfile", "test-log", ] diff --git a/Cargo.toml b/Cargo.toml index 62ca2ec..32cd239 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,9 @@ members = [ exclude = [ # This currently needs to be excluded because it depends on a version of `rust-gpu` that # uses a toolchain whose Cargo version doesn't recognise version 4 of `Cargo.lock`. - "crates/shader-crate-template" + "crates/shader-crate-template", + # Testing infra may copy the `shader-crate-template` into subdirs of target + "target", ] resolver = "2" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 8de68b2..ba88383 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -27,6 +27,7 @@ semver.workspace = true dunce.workspace = true [dev-dependencies] +tempfile.workspace = true test-log.workspace = true cargo_metadata = { workspace = true, features = ["builder"] } cargo-util-schemas = "0.8.2" diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 2a7f158..aa89fe2 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -181,8 +181,6 @@ mod test { #[test_log::test] fn builder_from_params() { - crate::test::tests_teardown(); - let shader_crate_path = crate::test::shader_crate_template_path(); let output_dir = shader_crate_path.join("shaders"); diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index f1a67fa..507065b 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -86,11 +86,13 @@ impl Config { mod test { use super::*; + use crate::test::TestEnv; use std::io::Write as _; #[test_log::test] fn booleans_from_cli() { - let shader_crate_path = crate::test::shader_crate_test_path(); + let _env = TestEnv::new(); + let shader_crate_path = _env.setup_shader_crate().unwrap(); let args = Config::clap_command_with_cargo_config( &shader_crate_path, @@ -108,43 +110,45 @@ mod test { #[test_log::test] fn booleans_from_cargo() { - let shader_crate_path = crate::test::shader_crate_test_path(); - let mut file = crate::test::overwrite_shader_cargo_toml(&shader_crate_path); - file.write_all( - [ - "[package.metadata.rust-gpu.build]", - "release = false", - "[package.metadata.rust-gpu.install]", - "auto-install-rust-toolchain = true", - ] - .join("\n") - .as_bytes(), - ) - .unwrap(); + let _env = TestEnv::new(); + let shader_crate_path = _env + .setup_shader_crate_with_cargo_toml(|file| { + file.write_all( + [ + "[package.metadata.rust-gpu.build]", + "release = false", + "[package.metadata.rust-gpu.install]", + "auto-install-rust-toolchain = true", + ] + .join("\n") + .as_bytes(), + ) + }) + .unwrap(); let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); assert!(!args.build.spirv_builder.release); assert!(args.install.auto_install_rust_toolchain); } - fn update_cargo_output_dir() -> std::path::PathBuf { - let shader_crate_path = crate::test::shader_crate_test_path(); - let mut file = crate::test::overwrite_shader_cargo_toml(&shader_crate_path); - file.write_all( - [ - "[package.metadata.rust-gpu.build]", - "output-dir = \"/the/moon\"", - ] - .join("\n") - .as_bytes(), - ) - .unwrap(); - shader_crate_path + fn update_cargo_output_dir(_env: &TestEnv) -> std::path::PathBuf { + _env.setup_shader_crate_with_cargo_toml(|file| { + file.write_all( + [ + "[package.metadata.rust-gpu.build]", + "output-dir = \"/the/moon\"", + ] + .join("\n") + .as_bytes(), + ) + }) + .unwrap() } #[test_log::test] fn string_from_cargo() { - let shader_crate_path = update_cargo_output_dir(); + let _env = TestEnv::new(); + let shader_crate_path = update_cargo_output_dir(&_env); let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); if cfg!(target_os = "windows") { @@ -156,7 +160,8 @@ mod test { #[test_log::test] fn string_from_cargo_overwritten_by_cli() { - let shader_crate_path = update_cargo_output_dir(); + let _env = TestEnv::new(); + let shader_crate_path = update_cargo_output_dir(&_env); let args = Config::clap_command_with_cargo_config( &shader_crate_path, @@ -173,17 +178,19 @@ mod test { #[test_log::test] fn arrays_from_cargo() { - let shader_crate_path = crate::test::shader_crate_test_path(); - let mut file = crate::test::overwrite_shader_cargo_toml(&shader_crate_path); - file.write_all( - [ - "[package.metadata.rust-gpu.build]", - "capabilities = [\"AtomicStorage\", \"Matrix\"]", - ] - .join("\n") - .as_bytes(), - ) - .unwrap(); + let _env = TestEnv::new(); + let shader_crate_path = _env + .setup_shader_crate_with_cargo_toml(|file| { + file.write_all( + [ + "[package.metadata.rust-gpu.build]", + "capabilities = [\"AtomicStorage\", \"Matrix\"]", + ] + .join("\n") + .as_bytes(), + ) + }) + .unwrap(); let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); assert_eq!( @@ -197,7 +204,8 @@ mod test { #[test_log::test] fn rename_manifest_parse() { - let shader_crate_path = crate::test::shader_crate_test_path(); + let _env = TestEnv::new(); + let shader_crate_path = _env.setup_shader_crate().unwrap(); let args = Config::clap_command_with_cargo_config( &shader_crate_path, diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index 1be7abb..ea2fc52 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -50,8 +50,6 @@ //! conduct other post-processing, like converting the `spv` files into `wgsl` files, //! for example. -use anyhow::Context as _; - use crate::dump_usage::dump_full_usage_for_readme; use build::Build; use show::Show; @@ -171,21 +169,18 @@ pub struct Cli { /// # Errors /// may fail if we can't find the user home directory #[inline] +#[cfg(not(test))] pub fn cache_dir() -> anyhow::Result { - let dir = directories::BaseDirs::new() + use anyhow::Context as _; + Ok(directories::BaseDirs::new() .with_context(|| "could not find the user home directory")? .cache_dir() - .join("rust-gpu"); - - Ok(if cfg!(test) { - let thread_id = std::thread::current().id(); - let id = format!("{thread_id:?}").replace('(', "-").replace(')', ""); - dir.join("tests").join(id) - } else { - dir - }) + .join("rust-gpu")) } +#[cfg(test)] +pub use test::test_cache_dir as cache_dir; + /// Returns a string suitable to use as a directory. /// /// Created from the spirv-builder source dep and the rustc channel. diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index e8f0a7c..f33c283 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -248,6 +248,7 @@ pub fn get_channel_from_rustc_codegen_spirv_build_script( #[cfg(test)] mod test { use super::*; + use crate::test::TestEnv; use cargo_metadata::{PackageBuilder, PackageId, Source}; use cargo_util_schemas::manifest::PackageName; @@ -272,6 +273,7 @@ mod test { #[test_log::test] fn cached_checkout_dir_sanity() { + let _env = TestEnv::new(); let shader_template_path = crate::test::shader_crate_template_path(); let source = SpirvSource::get_rust_gpu_deps_from_shader(&shader_template_path).unwrap(); let dir = source.install_dir().unwrap(); diff --git a/crates/cargo-gpu/src/test.rs b/crates/cargo-gpu/src/test.rs index c9ee93a..154eb3a 100644 --- a/crates/cargo-gpu/src/test.rs +++ b/crates/cargo-gpu/src/test.rs @@ -1,8 +1,80 @@ //! utilities for tests #![cfg(test)] -use crate::cache_dir; +use anyhow::Context; +use std::cell::RefCell; +use std::fs::File; use std::io::Write as _; +use std::path::PathBuf; +use tempfile::TempDir; + +#[must_use] +pub struct TestEnv(TempDir); + +impl TestEnv { + pub fn new() -> Self { + let target_dir = cargo_metadata::MetadataCommand::new() + .exec() + .unwrap() + .target_directory + .into_std_path_buf(); + let tests_dir = target_dir.join("cargo-gpu-test"); + std::fs::create_dir_all(&tests_dir).ok(); + let test_dir = TempDir::new_in(tests_dir).unwrap(); + + let had_old = TESTDIR + .replace(Some(test_dir.path().to_path_buf())) + .is_some(); + if had_old { + panic!("TestEnv is not reentrant!") + } + + TestEnv(test_dir) + } + + pub fn setup_shader_crate(&self) -> anyhow::Result { + let shader_crate_path = crate::cache_dir().unwrap().join("shader_crate"); + copy_dir_all(shader_crate_template_path(), &shader_crate_path)?; + Ok(shader_crate_path) + } + + pub fn setup_shader_crate_with_cargo_toml( + &self, + f: impl FnOnce(&mut File) -> std::io::Result<()>, + ) -> anyhow::Result { + let shader_crate_path = self.setup_shader_crate()?; + let cargo_toml = shader_crate_path.join("Cargo.toml"); + let mut file = std::fs::OpenOptions::new() + .write(true) + .truncate(true) + .open(cargo_toml)?; + writeln!(file, "[package]")?; + writeln!(file, "name = \"test\"")?; + f(&mut file)?; + Ok(shader_crate_path) + } +} + +impl Drop for TestEnv { + fn drop(&mut self) { + TESTDIR.replace(None).unwrap(); + // when a test fails, keep directory + if std::thread::panicking() { + self.0.disable_cleanup(true); + } + } +} + +thread_local! { + static TESTDIR: RefCell> = RefCell::new(None); +} + +/// [`crate::cache_dir`] for testing +pub fn test_cache_dir() -> anyhow::Result { + Ok(TESTDIR.with_borrow(|a| a.clone()).context( + "TestEnv is not initialized! Add `let _env = TestEnv::new();` to the beginning of your test", + )?) +} fn copy_dir_all( src: impl AsRef, @@ -21,33 +93,7 @@ fn copy_dir_all( Ok(()) } -pub fn shader_crate_template_path() -> std::path::PathBuf { +pub fn shader_crate_template_path() -> PathBuf { let project_base = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); project_base.join("../shader-crate-template") } - -pub fn shader_crate_test_path() -> std::path::PathBuf { - let shader_crate_path = crate::cache_dir().unwrap().join("shader_crate"); - copy_dir_all(shader_crate_template_path(), shader_crate_path.clone()).unwrap(); - shader_crate_path -} - -pub fn overwrite_shader_cargo_toml(shader_crate_path: &std::path::Path) -> std::fs::File { - let cargo_toml = shader_crate_path.join("Cargo.toml"); - let mut file = std::fs::OpenOptions::new() - .write(true) - .truncate(true) - .open(cargo_toml) - .unwrap(); - writeln!(file, "[package]").unwrap(); - writeln!(file, "name = \"test\"").unwrap(); - file -} - -pub fn tests_teardown() { - let cache_dir = cache_dir().unwrap(); - if !cache_dir.exists() { - return; - } - std::fs::remove_dir_all(cache_dir).unwrap(); -}