Skip to content

Commit 90a8798

Browse files
committed
spirv-builder: move metadata file parsing to invoke_rustc
1 parent ddb039b commit 90a8798

File tree

2 files changed

+42
-33
lines changed

2 files changed

+42
-33
lines changed

crates/spirv-builder/src/lib.rs

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ pub enum SpirvBuilderError {
118118
"`multimodule: true` build cannot be used together with `build_script.env_shader_spv_path: true`"
119119
)]
120120
MultiModuleWithEnvShaderSpvPath,
121-
#[error("multi-module metadata file missing")]
121+
#[error("some metadata file is missing")]
122122
MetadataFileMissing(#[from] std::io::Error),
123-
#[error("unable to parse multi-module metadata file")]
123+
#[error("unable to parse some metadata file")]
124124
MetadataFileMalformed(#[from] serde_json::Error),
125125
#[error(
126126
"`{ARTIFACT_SUFFIX}` artifact not found in (supposedly successful) build output.\n--- build output ---\n{stdout}"
@@ -740,17 +740,13 @@ impl SpirvBuilder {
740740

741741
/// Builds the module
742742
pub fn build(&self) -> Result<CompileResult, SpirvBuilderError> {
743-
let metadata_file = invoke_rustc(self)?;
743+
let out = invoke_rustc(self)?;
744744
if self.build_script.get_dependency_info() {
745-
leaf_deps(&metadata_file, |artifact| {
746-
println!("cargo:rerun-if-changed={artifact}");
747-
})
748-
// Close enough
749-
.map_err(SpirvBuilderError::MetadataFileMissing)?;
745+
for dep in &out.deps {
746+
println!("cargo:rerun-if-changed={dep}");
747+
}
750748
}
751-
let metadata = self.parse_metadata_file(&metadata_file)?;
752-
753-
Ok(metadata)
749+
Ok(out.compile_result)
754750
}
755751

756752
pub(crate) fn parse_metadata_file(
@@ -888,8 +884,12 @@ fn join_checking_for_separators(strings: Vec<impl Borrow<str>>, sep: &str) -> St
888884
strings.join(sep)
889885
}
890886

891-
// Returns path to the metadata json.
892-
fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
887+
pub struct RustcOutput {
888+
pub compile_result: CompileResult,
889+
pub deps: Vec<RawString>,
890+
}
891+
892+
fn invoke_rustc(builder: &SpirvBuilder) -> Result<RustcOutput, SpirvBuilderError> {
893893
let path_to_crate = builder
894894
.path_to_crate
895895
.as_ref()
@@ -1161,24 +1161,35 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
11611161
// that ended up on stdout instead of stderr.
11621162
let stdout = String::from_utf8(build.stdout).unwrap();
11631163
if build.status.success() {
1164-
get_sole_artifact(&stdout).ok_or(SpirvBuilderError::NoArtifactProduced { stdout })
1164+
let metadata_file =
1165+
get_sole_artifact(&stdout).ok_or(SpirvBuilderError::NoArtifactProduced { stdout })?;
1166+
let compile_result = builder.parse_metadata_file(&metadata_file)?;
1167+
let mut deps = Vec::new();
1168+
leaf_deps(&metadata_file, |artifact| {
1169+
deps.push(RawString::from(artifact));
1170+
})
1171+
.map_err(SpirvBuilderError::MetadataFileMissing)?;
1172+
Ok(RustcOutput {
1173+
compile_result,
1174+
deps,
1175+
})
11651176
} else {
11661177
Err(SpirvBuilderError::BuildFailed)
11671178
}
11681179
}
11691180

1170-
#[derive(Deserialize)]
1171-
struct RustcOutput {
1172-
reason: String,
1173-
filenames: Option<Vec<String>>,
1174-
}
1175-
11761181
const ARTIFACT_SUFFIX: &str = ".spv.json";
11771182

11781183
fn get_sole_artifact(out: &str) -> Option<PathBuf> {
1184+
#[derive(Deserialize)]
1185+
struct RustcLine {
1186+
reason: String,
1187+
filenames: Option<Vec<String>>,
1188+
}
1189+
11791190
let mut last_compiler_artifact = None;
11801191
for line in out.lines() {
1181-
let Ok(msg) = serde_json::from_str::<RustcOutput>(line) else {
1192+
let Ok(msg) = serde_json::from_str::<RustcLine>(line) else {
11821193
// Pass through invalid lines
11831194
println!("{line}");
11841195
continue;

crates/spirv-builder/src/watch.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use crate::{SpirvBuilder, SpirvBuilderError, leaf_deps};
1+
use crate::{SpirvBuilder, SpirvBuilderError};
22
use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher};
3+
use raw_string::RawStr;
34
use rustc_codegen_spirv_types::CompileResult;
4-
use std::path::Path;
55
use std::sync::mpsc::TryRecvError;
66
use std::{
77
collections::HashSet,
@@ -121,10 +121,9 @@ impl SpirvWatcher {
121121
}
122122

123123
let result = (|| {
124-
let metadata_file = crate::invoke_rustc(&self.builder)?;
125-
let result = self.builder.parse_metadata_file(&metadata_file)?;
126-
self.watch_leaf_deps(&metadata_file)?;
127-
Ok(result)
124+
let out = crate::invoke_rustc(&self.builder)?;
125+
self.watch_leaf_deps(out.deps.iter().map(|d| d.as_ref()));
126+
Ok(out.compile_result)
128127
})();
129128
match result {
130129
Ok(result) => {
@@ -152,16 +151,15 @@ impl SpirvWatcher {
152151
}
153152
}
154153

155-
fn watch_leaf_deps(&mut self, watch_path: &Path) -> Result<(), SpirvBuilderError> {
156-
leaf_deps(watch_path, |artifact| {
157-
let path = artifact.to_path().unwrap();
154+
fn watch_leaf_deps<'a>(&mut self, deps: impl Iterator<Item = &'a RawStr>) {
155+
for dep in deps {
156+
let path = dep.to_path().unwrap();
158157
if self.watched_paths.insert(path.to_owned())
159158
&& let Err(err) = self.watcher.watch(path, RecursiveMode::NonRecursive)
160159
{
161-
log::error!("files of cargo dependencies are not valid: {err}");
160+
log::error!("failed to watch `{}`: {err}", path.display());
162161
}
163-
})
164-
.map_err(SpirvBuilderError::MetadataFileMissing)
162+
}
165163
}
166164
}
167165

0 commit comments

Comments
 (0)