@@ -113,8 +113,10 @@ pub enum SpirvBuilderError {
113113 RustcCodegenSpirvDylibDoesNotExist ( PathBuf ) ,
114114 #[ error( "build failed" ) ]
115115 BuildFailed ,
116- #[ error( "multi-module build cannot be used with print_metadata = MetadataPrintout::Full" ) ]
117- MultiModuleWithPrintMetadata ,
116+ #[ error(
117+ "`multimodule: true` build cannot be used together with `build_script.env_shader_spv_path: true`"
118+ ) ]
119+ MultiModuleWithEnvShaderSpvPath ,
118120 #[ error( "multi-module metadata file missing" ) ]
119121 MetadataFileMissing ( #[ from] std:: io:: Error ) ,
120122 #[ error( "unable to parse multi-module metadata file" ) ]
@@ -130,21 +132,6 @@ pub enum SpirvBuilderError {
130132 WatchFailed ( #[ from] SpirvWatcherError ) ,
131133}
132134
133- #[ derive( Debug , PartialEq , Eq , Clone , Copy , Default , serde:: Deserialize , serde:: Serialize ) ]
134- #[ cfg_attr( feature = "clap" , derive( clap:: ValueEnum ) ) ]
135- #[ non_exhaustive]
136- pub enum MetadataPrintout {
137- /// Print no cargo metadata.
138- #[ default]
139- None ,
140- /// Print only dependency information (eg for multiple modules).
141- DependencyOnly ,
142- /// Print all cargo metadata.
143- ///
144- /// Includes dependency information and spirv environment variable.
145- Full ,
146- }
147-
148135#[ derive( Debug , PartialEq , Eq , Clone , Copy , Default , serde:: Deserialize , serde:: Serialize ) ]
149136#[ cfg_attr( feature = "clap" , derive( clap:: ValueEnum ) ) ]
150137#[ non_exhaustive]
@@ -388,6 +375,50 @@ impl Default for ShaderCrateFeatures {
388375 }
389376}
390377
378+ /// Configuration for build scripts
379+ #[ derive( Clone , Debug , Default ) ]
380+ #[ non_exhaustive]
381+ pub struct BuildScriptConfig {
382+ /// Enable this if you are using `spirv-builder` from a build script to apply some recommended default options, such
383+ /// as [`Self::dependency_info`].
384+ pub defaults : bool ,
385+
386+ /// Print dependency information for cargo build scripts (with `cargo::rerun-if-changed={}` and such).
387+ /// Dependency information makes cargo rerun the build script is rerun when shader source files change, thus
388+ /// rebuilding the shader.
389+ ///
390+ /// Default: [`Self::defaults`]
391+ pub dependency_info : Option < bool > ,
392+
393+ /// Whether to emit an env var pointing to the shader module file (via `cargo::rustc-env={}`). The name of the env
394+ /// var is the crate name with `.spv` appended, e.g. `sky_shader.spv`.
395+ /// Not supported together with `multimodule=true` or `.watch()`.
396+ ///
397+ /// Some examples on how to include the shader module in the source code:
398+ /// * wgpu:
399+ /// ```rust,ignore
400+ /// let shader: ShaderModuleDescriptorPassthrough = include_spirv_raw!(env!("my_shader.spv"));
401+ /// ```
402+ /// * ash
403+ /// ```rust,ignore
404+ /// let bytes: &[u8] = include_bytes!(env!("my_shader.spv"))
405+ /// let words = ash::util::read_spv(&mut std::io::Cursor::new(bytes)).unwrap();
406+ /// ```
407+ ///
408+ /// Default: `false`
409+ pub env_shader_spv_path : Option < bool > ,
410+ }
411+
412+ /// these all have the prefix `get` so the doc items link to the members, not these private fns
413+ impl BuildScriptConfig {
414+ fn get_dependency_info ( & self ) -> bool {
415+ self . dependency_info . unwrap_or ( self . defaults )
416+ }
417+ fn get_env_shader_spv_path ( & self ) -> bool {
418+ self . env_shader_spv_path . unwrap_or ( false )
419+ }
420+ }
421+
391422#[ derive( Clone , Debug , serde:: Deserialize , serde:: Serialize ) ]
392423#[ cfg_attr( feature = "clap" , derive( clap:: Parser ) ) ]
393424#[ non_exhaustive]
@@ -402,10 +433,10 @@ pub struct SpirvBuilder {
402433 /// `--crate-type dylib`. Defaults to true if `cargo_cmd` is `None` or `Some("rustc")`.
403434 #[ cfg_attr( feature = "clap" , clap( skip) ) ]
404435 pub cargo_cmd_like_rustc : Option < bool > ,
405- /// Whether to print build.rs cargo metadata (e.g. cargo:rustc-env=var=val). Defaults to [`MetadataPrintout::None`].
406- /// Within build scripts, set it to [`MetadataPrintout::DependencyOnly`] or [`MetadataPrintout::Full`] to ensure the build script is rerun on code changes.
436+ /// Configuration for build scripts
407437 #[ cfg_attr( feature = "clap" , clap( skip) ) ]
408- pub print_metadata : MetadataPrintout ,
438+ #[ serde( skip) ]
439+ pub build_script : BuildScriptConfig ,
409440 /// Build in release. Defaults to true.
410441 #[ cfg_attr( feature = "clap" , clap( long = "debug" , default_value = "true" , action = clap:: ArgAction :: SetFalse ) ) ]
411442 pub release : bool ,
@@ -493,7 +524,7 @@ impl Default for SpirvBuilder {
493524 path_to_crate : None ,
494525 cargo_cmd : None ,
495526 cargo_cmd_like_rustc : None ,
496- print_metadata : MetadataPrintout :: default ( ) ,
527+ build_script : BuildScriptConfig :: default ( ) ,
497528 release : true ,
498529 target : None ,
499530 deny_warnings : false ,
@@ -523,13 +554,6 @@ impl SpirvBuilder {
523554 }
524555 }
525556
526- /// Whether to print build.rs cargo metadata (e.g. cargo:rustc-env=var=val). Defaults to [`MetadataPrintout::Full`].
527- #[ must_use]
528- pub fn print_metadata ( mut self , v : MetadataPrintout ) -> Self {
529- self . print_metadata = v;
530- self
531- }
532-
533557 #[ must_use]
534558 pub fn deny_warnings ( mut self , v : bool ) -> Self {
535559 self . deny_warnings = v;
@@ -675,19 +699,15 @@ impl SpirvBuilder {
675699 self
676700 }
677701
678- /// Builds the module. If `print_metadata` is [`MetadataPrintout::Full`], you usually don't have to inspect the path
679- /// in the result, as the environment variable for the path to the module will already be set.
702+ /// Builds the module
680703 pub fn build ( & self ) -> Result < CompileResult , SpirvBuilderError > {
681704 let metadata_file = invoke_rustc ( self ) ?;
682- match self . print_metadata {
683- MetadataPrintout :: Full | MetadataPrintout :: DependencyOnly => {
684- leaf_deps ( & metadata_file, |artifact| {
685- println ! ( "cargo:rerun-if-changed={artifact}" ) ;
686- } )
687- // Close enough
688- . map_err ( SpirvBuilderError :: MetadataFileMissing ) ?;
689- }
690- MetadataPrintout :: None => ( ) ,
705+ if self . build_script . get_dependency_info ( ) {
706+ leaf_deps ( & metadata_file, |artifact| {
707+ println ! ( "cargo:rerun-if-changed={artifact}" ) ;
708+ } )
709+ // Close enough
710+ . map_err ( SpirvBuilderError :: MetadataFileMissing ) ?;
691711 }
692712 let metadata = self . parse_metadata_file ( & metadata_file) ?;
693713
@@ -706,17 +726,17 @@ impl SpirvBuilder {
706726 match & metadata. module {
707727 ModuleResult :: SingleModule ( spirv_module) => {
708728 assert ! ( !self . multimodule) ;
709- let env_var = format ! (
710- "{}.spv" ,
711- at . file_name ( )
712- . unwrap ( )
713- . to_str ( )
714- . unwrap ( )
715- . strip_suffix ( ARTIFACT_SUFFIX )
716- . unwrap ( )
717- ) ;
718- if self . print_metadata == MetadataPrintout :: Full {
719- println ! ( "cargo:rustc-env={}={}" , env_var, spirv_module. display( ) ) ;
729+ if self . build_script . get_env_shader_spv_path ( ) {
730+ let env_var = format ! (
731+ "{}.spv" ,
732+ at . file_name ( )
733+ . unwrap ( )
734+ . to_str ( )
735+ . unwrap ( )
736+ . strip_suffix ( ARTIFACT_SUFFIX )
737+ . unwrap ( )
738+ ) ;
739+ println ! ( "cargo:: rustc-env={}={}" , env_var, spirv_module. display( ) ) ;
720740 }
721741 }
722742 ModuleResult :: MultiModule ( _) => {
@@ -792,8 +812,8 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
792812 . ok_or ( SpirvBuilderError :: MissingTarget ) ?;
793813 target = SpirvTarget :: parse ( target_str) ?;
794814
795- if ( builder. print_metadata == MetadataPrintout :: Full ) && builder. multimodule {
796- return Err ( SpirvBuilderError :: MultiModuleWithPrintMetadata ) ;
815+ if builder. build_script . get_env_shader_spv_path ( ) && builder. multimodule {
816+ return Err ( SpirvBuilderError :: MultiModuleWithEnvShaderSpvPath ) ;
797817 }
798818 if !path_to_crate. is_dir ( ) {
799819 return Err ( SpirvBuilderError :: CratePathDoesntExist (
@@ -858,7 +878,7 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
858878
859879 // Wrapper for `env::var` that appropriately informs Cargo of the dependency.
860880 let tracked_env_var_get = |name| {
861- if let MetadataPrintout :: Full | MetadataPrintout :: DependencyOnly = builder. print_metadata {
881+ if builder. build_script . get_dependency_info ( ) {
862882 println ! ( "cargo:rerun-if-env-changed={name}" ) ;
863883 }
864884 env:: var ( name)
0 commit comments