Skip to content

Commit 73a9ae1

Browse files
committed
build_script: replace enum MetadataPrintout with struct BuildScriptConfig for more flexibility
1 parent 5719b27 commit 73a9ae1

File tree

8 files changed

+89
-81
lines changed

8 files changed

+89
-81
lines changed

crates/spirv-builder/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,18 @@ It takes care of pulling in the `SPIR-V` backend for Rust, `rustc_codegen_spirv`
1414
use spirv_builder::{MetadataPrintout, SpirvBuilder};
1515
1616
fn main() -> Result<(), Box<dyn std::error::Error>> {
17-
SpirvBuilder::new("my_shaders", "spirv-unknown-vulkan1.1")
18-
.print_metadata(MetadataPrintout::Full)
19-
.build()?;
17+
let mut builder = SpirvBuilder::new("my_shaders", "spirv-unknown-vulkan1.3");
18+
builder.build_script.defaults = true;
19+
builder.build_script.env_shader_spv_path = true;
20+
builder.build()?;
2021
Ok(())
2122
}
2223
```
2324

24-
This example will build a shader crate called `my_shaders`. You typically insert this code in your crate's `build.rs` that requires the shader binary. The path to the shader module's binary will be set in the `my_shaders.spv` environment variable, which you can include in your project using something along the lines of:
25+
This example will build a shader crate called `my_shaders`. You typically insert this code in your crate's `build.rs` that requires the shader binary. The path to the shader module's binary will be set in the `SHADER_SPV_PATH` environment variable, which you can include in your project using something along the lines of:
2526

2627
```rust,ignore
27-
const SHADER: &[u8] = include_bytes!(env!("my_shaders.spv"));
28+
const SHADER: &[u8] = include_bytes!(env!("SHADER_SPV_PATH"));
2829
```
2930

3031
## Building with `spirv-builder`

crates/spirv-builder/src/lib.rs

Lines changed: 66 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,10 @@ pub enum SpirvBuilderError {
123123
MissingTargetSpec,
124124
#[error("build failed")]
125125
BuildFailed,
126-
#[error("multi-module build cannot be used with print_metadata = MetadataPrintout::Full")]
127-
MultiModuleWithPrintMetadata,
126+
#[error(
127+
"`multimodule: true` build cannot be used together with `build_script.env_shader_spv_path: true`"
128+
)]
129+
MultiModuleWithEnvShaderSpvPath,
128130
#[error("multi-module metadata file missing")]
129131
MetadataFileMissing(#[from] std::io::Error),
130132
#[error("unable to parse multi-module metadata file")]
@@ -138,21 +140,6 @@ pub enum SpirvBuilderError {
138140

139141
const SPIRV_TARGET_PREFIX: &str = "spirv-unknown-";
140142

141-
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, serde::Deserialize, serde::Serialize)]
142-
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
143-
#[non_exhaustive]
144-
pub enum MetadataPrintout {
145-
/// Print no cargo metadata.
146-
#[default]
147-
None,
148-
/// Print only dependency information (eg for multiple modules).
149-
DependencyOnly,
150-
/// Print all cargo metadata.
151-
///
152-
/// Includes dependency information and spirv environment variable.
153-
Full,
154-
}
155-
156143
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, serde::Deserialize, serde::Serialize)]
157144
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
158145
#[non_exhaustive]
@@ -396,6 +383,49 @@ impl Default for ShaderCrateFeatures {
396383
}
397384
}
398385

386+
/// Configuration for build scripts
387+
#[derive(Clone, Debug, Default)]
388+
#[non_exhaustive]
389+
pub struct BuildScriptConfig {
390+
/// Enable this if you are using `spirv-builder` from a build script to apply some recommended default options, such
391+
/// as [`Self::dependency_info`].
392+
pub defaults: bool,
393+
394+
/// Print dependency information for cargo build scripts (with `cargo::rerun-if-changed={}` and such).
395+
/// Dependency information makes cargo rerun the build script is rerun when shader source files change, thus
396+
/// rebuilding the shader.
397+
///
398+
/// Default: [`Self::defaults`]
399+
pub dependency_info: Option<bool>,
400+
401+
/// Whether to emit the env var `SHADER_SPV_PATH` pointing to the shader module file (via `cargo::rustc-env={}`).
402+
/// Not supported together with `multimodule=true` or `.watch()`.
403+
///
404+
/// Some examples on how to include the shader module in the source code:
405+
/// * wgpu:
406+
/// ```rust,ignore
407+
/// let shader: ShaderModuleDescriptorPassthrough = include_spirv_raw!(env!("SHADER_SPV_PATH"));
408+
/// ```
409+
/// * ash
410+
/// ```rust,ignore
411+
/// let bytes: &[u8] = include_bytes!(env!("SHADER_SPV_PATH"))
412+
/// let words = ash::util::read_spv(&mut std::io::Cursor::new(bytes)).unwrap();
413+
/// ```
414+
///
415+
/// Default: `false`
416+
pub env_shader_spv_path: Option<bool>,
417+
}
418+
419+
/// these all have the prefix `get` so the doc items link to the members, not these private fns
420+
impl BuildScriptConfig {
421+
fn get_dependency_info(&self) -> bool {
422+
self.dependency_info.unwrap_or(self.defaults)
423+
}
424+
fn get_env_shader_spv_path(&self) -> bool {
425+
self.env_shader_spv_path.unwrap_or(false)
426+
}
427+
}
428+
399429
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
400430
#[cfg_attr(feature = "clap", derive(clap::Parser))]
401431
#[non_exhaustive]
@@ -410,10 +440,10 @@ pub struct SpirvBuilder {
410440
/// `--crate-type dylib`. Defaults to true if `cargo_cmd` is `None` or `Some("rustc")`.
411441
#[cfg_attr(feature = "clap", clap(skip))]
412442
pub cargo_cmd_like_rustc: Option<bool>,
413-
/// Whether to print build.rs cargo metadata (e.g. cargo:rustc-env=var=val). Defaults to [`MetadataPrintout::None`].
414-
/// Within build scripts, set it to [`MetadataPrintout::DependencyOnly`] or [`MetadataPrintout::Full`] to ensure the build script is rerun on code changes.
443+
/// Configuration for build scripts
415444
#[cfg_attr(feature = "clap", clap(skip))]
416-
pub print_metadata: MetadataPrintout,
445+
#[serde(skip)]
446+
pub build_script: BuildScriptConfig,
417447
/// Build in release. Defaults to true.
418448
#[cfg_attr(feature = "clap", clap(long = "debug", default_value = "true", action = clap::ArgAction::SetFalse))]
419449
pub release: bool,
@@ -507,7 +537,7 @@ impl Default for SpirvBuilder {
507537
path_to_crate: None,
508538
cargo_cmd: None,
509539
cargo_cmd_like_rustc: None,
510-
print_metadata: MetadataPrintout::default(),
540+
build_script: BuildScriptConfig::default(),
511541
release: true,
512542
target: None,
513543
deny_warnings: false,
@@ -548,13 +578,6 @@ impl SpirvBuilder {
548578
self
549579
}
550580

551-
/// Whether to print build.rs cargo metadata (e.g. cargo:rustc-env=var=val). Defaults to [`MetadataPrintout::Full`].
552-
#[must_use]
553-
pub fn print_metadata(mut self, v: MetadataPrintout) -> Self {
554-
self.print_metadata = v;
555-
self
556-
}
557-
558581
#[must_use]
559582
pub fn deny_warnings(mut self, v: bool) -> Self {
560583
self.deny_warnings = v;
@@ -700,19 +723,15 @@ impl SpirvBuilder {
700723
self
701724
}
702725

703-
/// Builds the module. If `print_metadata` is [`MetadataPrintout::Full`], you usually don't have to inspect the path
704-
/// in the result, as the environment variable for the path to the module will already be set.
726+
/// Builds the module
705727
pub fn build(&self) -> Result<CompileResult, SpirvBuilderError> {
706728
let metadata_file = invoke_rustc(self)?;
707-
match self.print_metadata {
708-
MetadataPrintout::Full | MetadataPrintout::DependencyOnly => {
709-
leaf_deps(&metadata_file, |artifact| {
710-
println!("cargo:rerun-if-changed={artifact}");
711-
})
712-
// Close enough
713-
.map_err(SpirvBuilderError::MetadataFileMissing)?;
714-
}
715-
MetadataPrintout::None => (),
729+
if self.build_script.get_dependency_info() {
730+
leaf_deps(&metadata_file, |artifact| {
731+
println!("cargo:rerun-if-changed={artifact}");
732+
})
733+
// Close enough
734+
.map_err(SpirvBuilderError::MetadataFileMissing)?;
716735
}
717736
let metadata = self.parse_metadata_file(&metadata_file)?;
718737

@@ -731,17 +750,11 @@ impl SpirvBuilder {
731750
match &metadata.module {
732751
ModuleResult::SingleModule(spirv_module) => {
733752
assert!(!self.multimodule);
734-
let env_var = format!(
735-
"{}.spv",
736-
at.file_name()
737-
.unwrap()
738-
.to_str()
739-
.unwrap()
740-
.strip_suffix(ARTIFACT_SUFFIX)
741-
.unwrap()
742-
);
743-
if self.print_metadata == MetadataPrintout::Full {
744-
println!("cargo:rustc-env={}={}", env_var, spirv_module.display());
753+
if self.build_script.get_env_shader_spv_path() {
754+
println!(
755+
"cargo::rustc-env=SHADER_SPV_PATH={}",
756+
spirv_module.display()
757+
);
745758
}
746759
}
747760
ModuleResult::MultiModule(_) => {
@@ -839,8 +852,8 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
839852
}
840853
}
841854

842-
if (builder.print_metadata == MetadataPrintout::Full) && builder.multimodule {
843-
return Err(SpirvBuilderError::MultiModuleWithPrintMetadata);
855+
if builder.build_script.get_env_shader_spv_path() && builder.multimodule {
856+
return Err(SpirvBuilderError::MultiModuleWithEnvShaderSpvPath);
844857
}
845858
if !path_to_crate.is_dir() {
846859
return Err(SpirvBuilderError::CratePathDoesntExist(
@@ -905,7 +918,7 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
905918

906919
// Wrapper for `env::var` that appropriately informs Cargo of the dependency.
907920
let tracked_env_var_get = |name| {
908-
if let MetadataPrintout::Full | MetadataPrintout::DependencyOnly = builder.print_metadata {
921+
if builder.build_script.get_dependency_info() {
909922
println!("cargo:rerun-if-env-changed={name}");
910923
}
911924
env::var(name)

crates/spirv-builder/src/watch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl SpirvWatcher {
5555
.as_ref()
5656
.ok_or(SpirvBuilderError::MissingCratePath)?
5757
.clone();
58-
if !matches!(builder.print_metadata, crate::MetadataPrintout::None) {
58+
if builder.build_script.get_env_shader_spv_path() {
5959
return Err(SpirvWatcherError::WatchWithPrintMetadata.into());
6060
}
6161

examples/multibuilder/src/main.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
use spirv_builder::{MetadataPrintout, SpirvBuilder};
1+
use spirv_builder::SpirvBuilder;
22

33
fn main() {
4-
let result = SpirvBuilder::new(
4+
let mut builder = SpirvBuilder::new(
55
concat!(env!("CARGO_MANIFEST_DIR"), "/../shaders/sky-shader"),
66
"spirv-unknown-spv1.3",
7-
)
8-
.print_metadata(MetadataPrintout::DependencyOnly)
9-
.multimodule(true)
10-
.build()
11-
.unwrap();
7+
);
8+
builder.multimodule = true;
9+
let result = builder.build().unwrap();
1210
println!("{result:#?}");
1311
}

examples/runners/ash/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ use ash::util::read_spv;
7878
use clap::{Parser, ValueEnum};
7979
use raw_window_handle::HasDisplayHandle as _;
8080
use shared::ShaderConstants;
81-
use spirv_builder::{MetadataPrintout, SpirvBuilder};
81+
use spirv_builder::SpirvBuilder;
8282
use std::{
8383
fs::File,
8484
path::PathBuf,
@@ -259,7 +259,6 @@ pub fn compile_shaders(shader: &RustGPUShader) -> anyhow::Result<Vec<u32>> {
259259
.collect::<PathBuf>();
260260

261261
let compile_result = SpirvBuilder::new(crate_path, "spirv-unknown-vulkan1.3")
262-
.print_metadata(MetadataPrintout::None)
263262
.shader_panic_strategy(spirv_builder::ShaderPanicStrategy::DebugPrintfThenExit {
264263
print_inputs: true,
265264
print_backtrace: true,

examples/runners/wgpu/builder/src/main.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
use spirv_builder::{MetadataPrintout, SpirvBuilder};
1+
use spirv_builder::SpirvBuilder;
22
use std::env;
33
use std::error::Error;
44
use std::fs;
5-
use std::path::Path;
5+
use std::path::{Path, PathBuf};
66

77
fn build_shader(path_to_crate: &str, codegen_names: bool) -> Result<(), Box<dyn Error>> {
8-
let builder_dir = &Path::new(env!("CARGO_MANIFEST_DIR"));
9-
let path_to_crate = builder_dir.join(path_to_crate);
10-
let result = SpirvBuilder::new(path_to_crate, "spirv-unknown-vulkan1.1")
11-
.print_metadata(MetadataPrintout::Full)
12-
// Give this spirv-builder a unique target dir, so that rebuilding android and the main wgpu app's target dir
13-
// don't clash and break each other's incremental
14-
.target_dir_path("example-runner-wgpu-builder")
15-
.build()?;
8+
let path_to_crate = Path::new(env!("CARGO_MANIFEST_DIR")).join(path_to_crate);
9+
let mut builder = SpirvBuilder::new(path_to_crate, "spirv-unknown-vulkan1.1");
10+
builder.build_script.defaults = true;
11+
// Give this spirv-builder a unique target dir, so that rebuilding android and the main wgpu app's target dir
12+
// don't clash and break each other's incremental
13+
builder.target_dir_path = Some(PathBuf::from("example-runner-wgpu-builder"));
14+
let result = builder.build()?;
1615
if codegen_names {
1716
let out_dir = env::var_os("OUT_DIR").unwrap();
1817
let dest_path = Path::new(&out_dir).join("entry_points.rs");

examples/runners/wgpu/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ fn maybe_watch(
124124
) -> CompiledShaderModules {
125125
#[cfg(not(any(target_os = "android", target_arch = "wasm32")))]
126126
{
127-
use spirv_builder::{CompileResult, MetadataPrintout, SpirvBuilder};
127+
use spirv_builder::{CompileResult, SpirvBuilder};
128128
use std::path::PathBuf;
129129

130130
let crate_name = match options.shader {
@@ -142,7 +142,6 @@ fn maybe_watch(
142142
let has_debug_printf = options.force_spirv_passthru;
143143

144144
let builder = SpirvBuilder::new(crate_path, "spirv-unknown-vulkan1.1")
145-
.print_metadata(MetadataPrintout::None)
146145
.shader_panic_strategy(if has_debug_printf {
147146
spirv_builder::ShaderPanicStrategy::DebugPrintfThenExit {
148147
print_inputs: true,

tests/difftests/lib/src/scaffold/shader/rust_gpu_shader.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ impl RustComputeShader {
3838
impl SpirvShader for RustComputeShader {
3939
fn spirv_bytes(&self) -> anyhow::Result<(Vec<u8>, String)> {
4040
let mut builder = SpirvBuilder::new(&self.path, &self.target)
41-
.print_metadata(spirv_builder::MetadataPrintout::None)
4241
.release(true)
4342
.multimodule(false)
4443
.shader_panic_strategy(spirv_builder::ShaderPanicStrategy::SilentExit)

0 commit comments

Comments
 (0)