mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-22 06:45:13 +00:00
Move to a builder struct for spirv-builder (#59)
This allows the print_metadata option
This commit is contained in:
parent
377bf070f0
commit
d3af0552d3
@ -1,8 +1,8 @@
|
||||
use spirv_builder::build_spirv;
|
||||
use spirv_builder::SpirvBuilder;
|
||||
use std::error::Error;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
// 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(())
|
||||
}
|
||||
|
@ -24,12 +24,35 @@ impl fmt::Display for SpirvBuilderError {
|
||||
|
||||
impl Error for SpirvBuilderError {}
|
||||
|
||||
pub fn build_spirv(path_to_crate: impl AsRef<Path>) -> 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<Path>) -> 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<PathBuf, SpirvBuilderError> {
|
||||
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<String, SpirvBuilderError> {
|
||||
fn invoke_rustc(path_to_crate: &Path, print_metadata: bool) -> Result<PathBuf, SpirvBuilderError> {
|
||||
// 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<String, SpirvBuilderError> {
|
||||
if build.status.success() {
|
||||
let stdout = String::from_utf8(build.stdout).unwrap();
|
||||
let artifact = get_last_artifact(&stdout);
|
||||
if print_metadata {
|
||||
print_deps_of(&artifact);
|
||||
}
|
||||
Ok(artifact)
|
||||
} else {
|
||||
Err(SpirvBuilderError::BuildFailed)
|
||||
@ -106,7 +131,7 @@ struct RustcOutput {
|
||||
filenames: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
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::<RustcOutput>(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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user