From 9a7d341d2ab5445aa12d19b8e441dd3c3b8adfd1 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 15 Apr 2026 12:11:02 +0200 Subject: [PATCH 1/2] cargo-gpu: add `CrateMetadata` to store `cargo metadata` with crate that was queried --- crates/cargo-gpu-install/src/install.rs | 9 ++- crates/cargo-gpu-install/src/spirv_source.rs | 74 ++++++++++++-------- crates/cargo-gpu/src/show.rs | 4 +- 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/crates/cargo-gpu-install/src/install.rs b/crates/cargo-gpu-install/src/install.rs index c5061d3e6e..b51044aecd 100644 --- a/crates/cargo-gpu-install/src/install.rs +++ b/crates/cargo-gpu-install/src/install.rs @@ -1,8 +1,6 @@ //! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it. -use crate::spirv_source::{ - FindPackage as _, get_channel_from_rustc_codegen_spirv_build_script, query_metadata, -}; +use crate::spirv_source::{CrateMetadata, get_channel_from_rustc_codegen_spirv_build_script}; use crate::{cache_dir, spirv_source::SpirvSource}; use anyhow::Context as _; use spirv_builder::SpirvBuilder; @@ -238,8 +236,9 @@ package = "rustc_codegen_spirv" format!("could not create cache directory '{}'", cache_dir.display()) })?; + let metadata = CrateMetadata::query(self.shader_crate.clone())?; let source = SpirvSource::new( - &self.shader_crate, + &metadata, self.spirv_builder_source.as_deref(), self.spirv_builder_version.as_deref(), )?; @@ -289,7 +288,7 @@ package = "rustc_codegen_spirv" // TODO cache toolchain channel in a file? log::debug!("resolving toolchain version to use"); - let dummy_metadata = query_metadata(&install_dir) + let dummy_metadata = CrateMetadata::query(install_dir.clone()) .context("resolving toolchain version: get `rustc_codegen_spirv_dummy` metadata")?; let rustc_codegen_spirv = dummy_metadata.find_package("rustc_codegen_spirv").context( "resolving toolchain version: expected a dependency on `rustc_codegen_spirv`", diff --git a/crates/cargo-gpu-install/src/spirv_source.rs b/crates/cargo-gpu-install/src/spirv_source.rs index 9fc1e01222..9297a318ac 100644 --- a/crates/cargo-gpu-install/src/spirv_source.rs +++ b/crates/cargo-gpu-install/src/spirv_source.rs @@ -9,6 +9,7 @@ use cargo_metadata::camino::{Utf8Path, Utf8PathBuf}; use cargo_metadata::semver::Version; use cargo_metadata::{Metadata, MetadataCommand, Package}; use std::fs; +use std::ops::Deref; use std::path::{Path, PathBuf}; #[expect( @@ -75,7 +76,7 @@ impl SpirvSource { /// # Errors /// Crate may not depend on `spirv-std` or is otherwise malformed pub fn new( - shader_crate_path: &Path, + shader_crate: &CrateMetadata, maybe_rust_gpu_source: Option<&str>, maybe_rust_gpu_version: Option<&str>, ) -> anyhow::Result { @@ -89,10 +90,10 @@ impl SpirvSource { Self::CratesIO(Version::parse(rust_gpu_version)?) } } else { - Self::get_rust_gpu_deps_from_shader(shader_crate_path).with_context(|| { + Self::get_rust_gpu_deps_from_shader(shader_crate).with_context(|| { format!( "get spirv-std dependency from shader crate '{}'", - shader_crate_path.display() + shader_crate.path().display() ) })? }; @@ -103,14 +104,13 @@ impl SpirvSource { /// /// # Errors /// Crate may not depend on `spirv-std` or is otherwise malformed - pub fn get_rust_gpu_deps_from_shader(shader_crate_path: &Path) -> anyhow::Result { - let crate_metadata = query_metadata(shader_crate_path)?; + pub fn get_rust_gpu_deps_from_shader(crate_metadata: &CrateMetadata) -> anyhow::Result { let spirv_std_package = crate_metadata.find_package("spirv-std")?; let spirv_source = Self::parse_spirv_std_source_and_version(spirv_std_package)?; log::debug!( "Parsed `SpirvSource` from crate `{}`: \ {spirv_source:?}", - shader_crate_path.display(), + crate_metadata.path().display(), ); Ok(spirv_source) } @@ -193,33 +193,39 @@ impl SpirvSource { } } -/// get the Package metadata from some crate -/// -/// # Errors -/// metadata query may fail -pub fn query_metadata(crate_path: &Path) -> anyhow::Result { - log::debug!("Running `cargo metadata` on `{}`", crate_path.display()); - let metadata = MetadataCommand::new() - .current_dir( - &crate_path - .canonicalize() - .context("could not get absolute path to shader crate")?, - ) - .exec()?; - Ok(metadata) +/// [`cargo_metadata::Metadata`] combined with the path to the crate being queried +pub struct CrateMetadata { + path: PathBuf, + metadata: Metadata, } -/// implements [`Self::find_package`] -pub trait FindPackage { +impl CrateMetadata { + /// get the Package metadata from some crate + /// + /// # Errors + /// metadata query may fail + pub fn query(path: PathBuf) -> anyhow::Result { + log::debug!("Running `cargo metadata` on `{}`", path.display()); + let metadata = MetadataCommand::new() + .current_dir( + &path + .canonicalize() + .context("could not get absolute path to shader crate")?, + ) + .exec()?; + Ok(Self { path, metadata }) + } + + /// Path to the crate that was queried + pub fn path(&self) -> &Path { + self.path.as_path() + } + /// Search for a package or return a nice error /// /// # Errors /// package may not be found or crate may be malformed - fn find_package(&self, crate_name: &str) -> anyhow::Result<&Package>; -} - -impl FindPackage for Metadata { - fn find_package(&self, crate_name: &str) -> anyhow::Result<&Package> { + pub fn find_package(&self, crate_name: &str) -> anyhow::Result<&Package> { if let Some(package) = self .packages .iter() @@ -236,6 +242,14 @@ impl FindPackage for Metadata { } } +impl Deref for CrateMetadata { + type Target = Metadata; + + fn deref(&self) -> &Self::Target { + &self.metadata + } +} + /// Parse the `rust-toolchain.toml` in the working tree of the checked-out version of the `rust-gpu` repo. /// /// # Errors @@ -273,7 +287,8 @@ mod test { #[test_log::test] fn parsing_spirv_std_dep_for_shader_template() { let shader_template_path = crate::test::shader_crate_template_path(); - let source = SpirvSource::get_rust_gpu_deps_from_shader(&shader_template_path).unwrap(); + let metadata = CrateMetadata::query(shader_template_path).unwrap(); + let source = SpirvSource::get_rust_gpu_deps_from_shader(&metadata).unwrap(); expect![[r#" Git { url: "https://github.com/Rust-GPU/rust-gpu", @@ -286,7 +301,8 @@ mod 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 metadata = CrateMetadata::query(shader_template_path).unwrap(); + let source = SpirvSource::get_rust_gpu_deps_from_shader(&metadata).unwrap(); let dir = source.install_dir().unwrap(); let name = dir .file_name() diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 491550cd94..9e75aa84e8 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -3,6 +3,7 @@ use crate::cache_dir; use crate::spirv_builder::Capability; use crate::spirv_source::SpirvSource; +use cargo_gpu_install::spirv_source::CrateMetadata; /// Show the computed source of the spirv-std dependency. #[derive(Clone, Debug, clap::Parser)] @@ -48,7 +49,8 @@ impl Show { println!("{}\n", cache_dir()?.display()); } Info::SpirvSource(SpirvSourceDep { shader_crate }) => { - let rust_gpu_source = SpirvSource::get_rust_gpu_deps_from_shader(shader_crate)?; + let metadata = CrateMetadata::query(shader_crate.clone())?; + let rust_gpu_source = SpirvSource::get_rust_gpu_deps_from_shader(&metadata)?; println!("{rust_gpu_source}\n"); } Info::Commitsh => { From 6e0ba7f88af16865a2f979cc746d977a0a0859d0 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 15 Apr 2026 12:24:27 +0200 Subject: [PATCH 2/2] cargo-gpu: rerun build script when `Cargo.lock` changes close https://github.com/Rust-GPU/rust-gpu/issues/575 --- crates/cargo-gpu-install/src/install.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/cargo-gpu-install/src/install.rs b/crates/cargo-gpu-install/src/install.rs index b51044aecd..c45d80aa57 100644 --- a/crates/cargo-gpu-install/src/install.rs +++ b/crates/cargo-gpu-install/src/install.rs @@ -250,8 +250,11 @@ package = "rustc_codegen_spirv" std::env::consts::DLL_SUFFIX ); + #[allow(clippy::print_stdout)] if self.build_script { - #[allow(clippy::print_stdout)] + let root = metadata.workspace_root.as_path(); + println!("cargo:rerun-if-changed={root}/Cargo.lock"); + if let SpirvSource::Path { rust_gpu_repo_root, .. } = &source