From d3af0552d316a417d86b9d804ee6688438db0257 Mon Sep 17 00:00:00 2001 From: Ashley Hauck Date: Wed, 14 Oct 2020 15:48:21 +0200 Subject: [PATCH] Move to a builder struct for spirv-builder (#59) This allows the print_metadata option --- examples/example-runner/build.rs | 4 +-- spirv-builder/src/lib.rs | 51 ++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/examples/example-runner/build.rs b/examples/example-runner/build.rs index 304b67ed07..5f7b5107d3 100644 --- a/examples/example-runner/build.rs +++ b/examples/example-runner/build.rs @@ -1,8 +1,8 @@ -use spirv_builder::build_spirv; +use spirv_builder::SpirvBuilder; use std::error::Error; fn main() -> Result<(), Box> { // This will set the env var `example-shader.spv` to a spir-v file that can be include!()'d - build_spirv("../example-shader")?; + SpirvBuilder::new("../example-shader").build()?; Ok(()) } diff --git a/spirv-builder/src/lib.rs b/spirv-builder/src/lib.rs index e1866de471..d1cc52fe3b 100644 --- a/spirv-builder/src/lib.rs +++ b/spirv-builder/src/lib.rs @@ -24,12 +24,35 @@ impl fmt::Display for SpirvBuilderError { impl Error for SpirvBuilderError {} -pub fn build_spirv(path_to_crate: impl AsRef) -> Result<(), SpirvBuilderError> { - let spirv_module = invoke_rustc(path_to_crate.as_ref())?; - let spirv_path: &Path = spirv_module.as_ref(); - let env_var = spirv_path.file_name().unwrap().to_str().unwrap(); - println!("cargo:rustc-env={}={}", env_var, spirv_module); - Ok(()) +pub struct SpirvBuilder { + path_to_crate: PathBuf, + print_metadata: bool, +} +impl SpirvBuilder { + pub fn new(path_to_crate: impl AsRef) -> Self { + Self { + path_to_crate: path_to_crate.as_ref().to_owned(), + print_metadata: true, + } + } + + /// Whether to print build.rs cargo metadata (e.g. cargo:rustc-env=var=val). Defaults to true. + pub fn print_metadata(&mut self, v: bool) -> &mut Self { + self.print_metadata = v; + self + } + + /// Builds the module. Returns the path to the built spir-v file. If print_metadata is true, + /// you usually don't have to inspect the path, as the environment variable will already be + /// set. + pub fn build(self) -> Result { + let spirv_module = invoke_rustc(self.path_to_crate.as_ref(), self.print_metadata)?; + let env_var = spirv_module.file_name().unwrap().to_str().unwrap(); + if self.print_metadata { + println!("cargo:rustc-env={}={}", env_var, spirv_module.display()); + } + Ok(spirv_module) + } } // https://github.com/rust-lang/cargo/blob/1857880b5124580c4aeb4e8bc5f1198f491d61b1/src/cargo/util/paths.rs#L29-L52 @@ -64,7 +87,7 @@ fn find_rustc_codegen_spirv() -> PathBuf { panic!("Could not find {} in library path", filename); } -fn invoke_rustc(path_to_crate: &Path) -> Result { +fn invoke_rustc(path_to_crate: &Path, print_metadata: bool) -> Result { // Okay, this is a little bonkers: in a normal world, we'd have the user clone // rustc_codegen_spirv and pass in the path to it, and then we'd invoke cargo to build it, grab // the resulting .so, and pass it into -Z codegen-backend. But that's really gross: the user @@ -93,7 +116,9 @@ fn invoke_rustc(path_to_crate: &Path) -> Result { if build.status.success() { let stdout = String::from_utf8(build.stdout).unwrap(); let artifact = get_last_artifact(&stdout); - print_deps_of(&artifact); + if print_metadata { + print_deps_of(&artifact); + } Ok(artifact) } else { Err(SpirvBuilderError::BuildFailed) @@ -106,7 +131,7 @@ struct RustcOutput { filenames: Option>, } -fn get_last_artifact(out: &str) -> String { +fn get_last_artifact(out: &str) -> PathBuf { let last = out .lines() .filter_map(|line| match serde_json::from_str::(line) { @@ -128,11 +153,11 @@ fn get_last_artifact(out: &str) -> String { .filter(|v| v.ends_with(".spv")); let filename = filenames.next().expect("Crate had no .spv artifacts"); assert_eq!(filenames.next(), None, "Crate had multiple .spv artifacts"); - filename + filename.into() } -fn print_deps_of(artifact: &str) { - let deps_file = Path::new(artifact).with_extension("d"); +fn print_deps_of(artifact: &Path) { + let deps_file = artifact.with_extension("d"); let mut deps_map = HashMap::new(); depfile::read_deps_file(&deps_file, |item, deps| { deps_map.insert(item, deps); @@ -149,5 +174,5 @@ fn print_deps_of(artifact: &str) { None => println!("cargo:rerun-if-changed={}", artifact), } } - recurse(&deps_map, artifact.into()); + recurse(&deps_map, artifact.to_str().unwrap().into()); }