Skip to content

Commit 927ba3a

Browse files
committed
cache cargo metadata
1 parent 4a5e5ec commit 927ba3a

File tree

5 files changed

+88
-24
lines changed

5 files changed

+88
-24
lines changed

crates/cargo-gpu/src/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ impl Build {
5959
/// Entrypoint
6060
pub fn run(&mut self) -> anyhow::Result<()> {
6161
let installed_backend = self.install.run()?;
62+
let mut metadata = crate::metadata::MetadataCache::default();
6263

6364
if let Some(package) = self.install.package.as_ref() {
64-
self.install.shader_crate =
65-
crate::metadata::Metadata::resolve_package_to_shader_crate(package)?;
65+
self.install.shader_crate = metadata.resolve_package_to_shader_crate(package)?;
6666
}
6767

6868
let _lockfile_mismatch_handler = LockfileMismatchHandler::new(

crates/cargo-gpu/src/config.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
use anyhow::Context as _;
33
use clap::Parser as _;
44

5+
use crate::metadata::MetadataCache;
6+
57
/// Config
68
pub struct Config;
79

@@ -25,8 +27,9 @@ impl Config {
2527
pub fn clap_command_with_cargo_config(
2628
shader_crate_path: &std::path::PathBuf,
2729
mut env_args: Vec<String>,
30+
metadata: &mut MetadataCache,
2831
) -> anyhow::Result<crate::build::Build> {
29-
let mut config = crate::metadata::Metadata::as_json(shader_crate_path)?;
32+
let mut config = metadata.as_json(shader_crate_path)?;
3033

3134
env_args.retain(|arg| !(arg == "build" || arg == "install"));
3235
let cli_args_json = Self::cli_args_to_json(env_args)?;
@@ -100,6 +103,7 @@ mod test {
100103
"--debug".to_owned(),
101104
"--auto-install-rust-toolchain".to_owned(),
102105
],
106+
&mut MetadataCache::default(),
103107
)
104108
.unwrap();
105109
assert!(!args.build.spirv_builder.release);
@@ -122,7 +126,12 @@ mod test {
122126
)
123127
.unwrap();
124128

125-
let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap();
129+
let args = Config::clap_command_with_cargo_config(
130+
&shader_crate_path,
131+
vec![],
132+
&mut MetadataCache::default(),
133+
)
134+
.unwrap();
126135
assert!(!args.build.spirv_builder.release);
127136
assert!(args.install.auto_install_rust_toolchain);
128137
}
@@ -146,7 +155,12 @@ mod test {
146155
fn string_from_cargo() {
147156
let shader_crate_path = update_cargo_output_dir();
148157

149-
let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap();
158+
let args = Config::clap_command_with_cargo_config(
159+
&shader_crate_path,
160+
vec![],
161+
&mut MetadataCache::default(),
162+
)
163+
.unwrap();
150164
if cfg!(target_os = "windows") {
151165
assert_eq!(args.build.output_dir, std::path::Path::new("C:/the/moon"));
152166
} else {
@@ -166,6 +180,7 @@ mod test {
166180
"--output-dir".to_owned(),
167181
"/the/river".to_owned(),
168182
],
183+
&mut MetadataCache::default(),
169184
)
170185
.unwrap();
171186
assert_eq!(args.build.output_dir, std::path::Path::new("/the/river"));
@@ -185,7 +200,12 @@ mod test {
185200
)
186201
.unwrap();
187202

188-
let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap();
203+
let args = Config::clap_command_with_cargo_config(
204+
&shader_crate_path,
205+
vec![],
206+
&mut MetadataCache::default(),
207+
)
208+
.unwrap();
189209
assert_eq!(
190210
args.build.spirv_builder.capabilities,
191211
vec![
@@ -207,6 +227,7 @@ mod test {
207227
"--manifest-file".to_owned(),
208228
"mymanifest".to_owned(),
209229
],
230+
&mut MetadataCache::default(),
210231
)
211232
.unwrap();
212233
assert_eq!(args.build.manifest_file, "mymanifest".to_owned());

crates/cargo-gpu/src/lib.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ mod target_specs;
7070
mod test;
7171

7272
pub use install::*;
73+
pub use metadata::MetadataCache;
7374
pub use spirv_builder;
7475

7576
/// Central function to write to the user.
@@ -122,12 +123,19 @@ impl Command {
122123
/// # Errors
123124
/// Any errors during execution, usually printed to the user
124125
#[inline]
125-
pub fn run(&self, env_args: Vec<String>) -> anyhow::Result<()> {
126+
pub fn run(
127+
&self,
128+
env_args: Vec<String>,
129+
metadata_cache: &mut metadata::MetadataCache,
130+
) -> anyhow::Result<()> {
126131
match &self {
127132
Self::Install(install) => {
128133
let shader_crate_path = &install.shader_crate;
129-
let command =
130-
config::Config::clap_command_with_cargo_config(shader_crate_path, env_args)?;
134+
let command = config::Config::clap_command_with_cargo_config(
135+
shader_crate_path,
136+
env_args,
137+
metadata_cache,
138+
)?;
131139
log::debug!(
132140
"installing with final merged arguments: {:#?}",
133141
command.install
@@ -136,8 +144,11 @@ impl Command {
136144
}
137145
Self::Build(build) => {
138146
let shader_crate_path = &build.install.shader_crate;
139-
let mut command =
140-
config::Config::clap_command_with_cargo_config(shader_crate_path, env_args)?;
147+
let mut command = config::Config::clap_command_with_cargo_config(
148+
shader_crate_path,
149+
env_args,
150+
metadata_cache,
151+
)?;
141152
log::debug!("building with final merged arguments: {command:#?}");
142153

143154
if command.build.watch {

crates/cargo-gpu/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,6 @@ fn run() -> anyhow::Result<()> {
3737
.collect::<Vec<_>>();
3838
log::trace!("CLI args: {env_args:#?}");
3939
let cli = Cli::parse_from(&env_args);
40-
cli.command.run(env_args)
40+
let mut metadata_cache = cargo_gpu::MetadataCache::default();
41+
cli.command.run(env_args, &mut metadata_cache)
4142
}

crates/cargo-gpu/src/metadata.rs

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,49 @@
11
//! Get config from the shader crate's `Cargo.toml` `[*.metadata.rust-gpu.*]`
22
3+
use std::collections::HashMap;
4+
35
use anyhow::Context as _;
46
use cargo_metadata::MetadataCommand;
57
use serde_json::Value;
68

7-
/// `Metadata` refers to the `[metadata.*]` section of `Cargo.toml` that `cargo` formally
9+
/// A cache of metadata from various `Cargo.toml` files.
10+
///
11+
/// "Metadata" refers to the `[metadata.*]` section of `Cargo.toml` that `cargo` formally
812
/// ignores so that packages can implement their own behaviour with it.
9-
#[derive(Debug)]
10-
pub struct Metadata;
13+
#[derive(Debug, Default)]
14+
pub struct MetadataCache {
15+
/// Cached result of `MetadataCommand::new().exec()`.
16+
inner: HashMap<std::path::PathBuf, cargo_metadata::Metadata>,
17+
}
18+
19+
impl MetadataCache {
20+
fn get_metadata(
21+
&mut self,
22+
maybe_path_to_manifest_dir: Option<&std::path::Path>,
23+
) -> anyhow::Result<&cargo_metadata::Metadata> {
24+
let path = if let Some(path) = maybe_path_to_manifest_dir {
25+
path.to_path_buf()
26+
} else {
27+
std::env::current_dir().context("cannot determine the current working directory")?
28+
};
29+
30+
if !self.inner.contains_key(&path) {
31+
let metadata = MetadataCommand::new().current_dir(&path).exec()?;
32+
self.inner.insert(path.clone(), metadata);
33+
}
34+
35+
// UNWRAP: safe because we just inserted it
36+
Ok(self.inner.get(&path).unwrap())
37+
}
1138

12-
impl Metadata {
1339
/// Resolve a package name to a crate directory.
14-
pub fn resolve_package_to_shader_crate(package: &str) -> anyhow::Result<std::path::PathBuf> {
40+
pub fn resolve_package_to_shader_crate(
41+
&mut self,
42+
package: &str,
43+
) -> anyhow::Result<std::path::PathBuf> {
1544
log::debug!("resolving package '{package}' to shader crate");
16-
let metadata = MetadataCommand::new().exec()?;
45+
let metadata = self.get_metadata(None)?;
46+
1747
let meta_package = metadata
1848
.packages
1949
.iter()
@@ -39,9 +69,9 @@ impl Metadata {
3969
/// First we generate the CLI arg defaults as JSON. Then on top of those we merge any config
4070
/// from the workspace `Cargo.toml`, then on top of those we merge any config from the shader
4171
/// crate's `Cargo.toml`.
42-
pub fn as_json(path: &std::path::PathBuf) -> anyhow::Result<Value> {
72+
pub fn as_json(&mut self, path: &std::path::PathBuf) -> anyhow::Result<Value> {
4373
log::debug!("reading package metadata from {}", path.display());
44-
let cargo_json = Self::get_cargo_toml_as_json(path)?;
74+
let cargo_json = self.get_cargo_toml_as_json(path)?;
4575
let config = Self::merge_configs(&cargo_json, path)?;
4676
Ok(config)
4777
}
@@ -90,9 +120,10 @@ impl Metadata {
90120

91121
/// Convert a `Cargo.toml` to JSON
92122
fn get_cargo_toml_as_json(
123+
&mut self,
93124
path: &std::path::PathBuf,
94125
) -> anyhow::Result<cargo_metadata::Metadata> {
95-
Ok(MetadataCommand::new().current_dir(path).exec()?)
126+
self.get_metadata(Some(path.as_path())).cloned()
96127
}
97128

98129
/// Get any `rust-gpu` metadata set in the crate's `Cargo.toml`
@@ -161,7 +192,7 @@ mod test {
161192
.exec()
162193
.unwrap();
163194
metadata.packages.first_mut().unwrap().metadata = serde_json::json!({});
164-
let configs = Metadata::merge_configs(&metadata, Path::new("./")).unwrap();
195+
let configs = MetadataCache::merge_configs(&metadata, Path::new("./")).unwrap();
165196
assert_eq!(configs["build"]["release"], Value::Bool(true));
166197
assert_eq!(
167198
configs["install"]["auto_install_rust_toolchain"],
@@ -185,7 +216,7 @@ mod test {
185216
}
186217
}
187218
});
188-
let configs = Metadata::merge_configs(&metadata, Path::new("./")).unwrap();
219+
let configs = MetadataCache::merge_configs(&metadata, Path::new("./")).unwrap();
189220
assert_eq!(configs["build"]["release"], Value::Bool(false));
190221
assert_eq!(
191222
configs["install"]["auto_install_rust_toolchain"],
@@ -214,7 +245,7 @@ mod test {
214245
}
215246
}
216247
});
217-
let configs = Metadata::merge_configs(&metadata, Path::new(".")).unwrap();
248+
let configs = MetadataCache::merge_configs(&metadata, Path::new(".")).unwrap();
218249
assert_eq!(configs["build"]["release"], Value::Bool(false));
219250
assert_eq!(
220251
configs["install"]["auto_install_rust_toolchain"],

0 commit comments

Comments
 (0)