@@ -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
139141const 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,50 @@ 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 an env var pointing to the shader module file (via `cargo::rustc-env={}`). The name of the env
402+ /// var is the crate name with `.spv` appended, e.g. `sky_shader.spv`.
403+ /// Not supported together with `multimodule=true` or `.watch()`.
404+ ///
405+ /// Some examples on how to include the shader module in the source code:
406+ /// * wgpu:
407+ /// ```rust,ignore
408+ /// let shader: ShaderModuleDescriptorPassthrough = include_spirv_raw!(env!("my_shader.spv"));
409+ /// ```
410+ /// * ash
411+ /// ```rust,ignore
412+ /// let bytes: &[u8] = include_bytes!(env!("my_shader.spv"))
413+ /// let words = ash::util::read_spv(&mut std::io::Cursor::new(bytes)).unwrap();
414+ /// ```
415+ ///
416+ /// Default: `false`
417+ pub env_shader_spv_path : Option < bool > ,
418+ }
419+
420+ /// these all have the prefix `get` so the doc items link to the members, not these private fns
421+ impl BuildScriptConfig {
422+ fn get_dependency_info ( & self ) -> bool {
423+ self . dependency_info . unwrap_or ( self . defaults )
424+ }
425+ fn get_env_shader_spv_path ( & self ) -> bool {
426+ self . env_shader_spv_path . unwrap_or ( false )
427+ }
428+ }
429+
399430#[ derive( Clone , Debug , serde:: Deserialize , serde:: Serialize ) ]
400431#[ cfg_attr( feature = "clap" , derive( clap:: Parser ) ) ]
401432#[ non_exhaustive]
@@ -410,10 +441,10 @@ pub struct SpirvBuilder {
410441 /// `--crate-type dylib`. Defaults to true if `cargo_cmd` is `None` or `Some("rustc")`.
411442 #[ cfg_attr( feature = "clap" , clap( skip) ) ]
412443 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.
444+ /// Configuration for build scripts
415445 #[ cfg_attr( feature = "clap" , clap( skip) ) ]
416- pub print_metadata : MetadataPrintout ,
446+ #[ serde( skip) ]
447+ pub build_script : BuildScriptConfig ,
417448 /// Build in release. Defaults to true.
418449 #[ cfg_attr( feature = "clap" , clap( long = "debug" , default_value = "true" , action = clap:: ArgAction :: SetFalse ) ) ]
419450 pub release : bool ,
@@ -507,7 +538,7 @@ impl Default for SpirvBuilder {
507538 path_to_crate : None ,
508539 cargo_cmd : None ,
509540 cargo_cmd_like_rustc : None ,
510- print_metadata : MetadataPrintout :: default ( ) ,
541+ build_script : BuildScriptConfig :: default ( ) ,
511542 release : true ,
512543 target : None ,
513544 deny_warnings : false ,
@@ -548,13 +579,6 @@ impl SpirvBuilder {
548579 self
549580 }
550581
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-
558582 #[ must_use]
559583 pub fn deny_warnings ( mut self , v : bool ) -> Self {
560584 self . deny_warnings = v;
@@ -700,19 +724,15 @@ impl SpirvBuilder {
700724 self
701725 }
702726
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.
727+ /// Builds the module
705728 pub fn build ( & self ) -> Result < CompileResult , SpirvBuilderError > {
706729 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 => ( ) ,
730+ if self . build_script . get_dependency_info ( ) {
731+ leaf_deps ( & metadata_file, |artifact| {
732+ println ! ( "cargo:rerun-if-changed={artifact}" ) ;
733+ } )
734+ // Close enough
735+ . map_err ( SpirvBuilderError :: MetadataFileMissing ) ?;
716736 }
717737 let metadata = self . parse_metadata_file ( & metadata_file) ?;
718738
@@ -731,17 +751,17 @@ impl SpirvBuilder {
731751 match & metadata. module {
732752 ModuleResult :: SingleModule ( spirv_module) => {
733753 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( ) ) ;
754+ if self . build_script . get_env_shader_spv_path ( ) {
755+ let env_var = format ! (
756+ "{}.spv" ,
757+ at . file_name ( )
758+ . unwrap ( )
759+ . to_str ( )
760+ . unwrap ( )
761+ . strip_suffix ( ARTIFACT_SUFFIX )
762+ . unwrap ( )
763+ ) ;
764+ println ! ( "cargo:: rustc-env={}={}" , env_var, spirv_module. display( ) ) ;
745765 }
746766 }
747767 ModuleResult :: MultiModule ( _) => {
@@ -839,8 +859,8 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
839859 }
840860 }
841861
842- if ( builder. print_metadata == MetadataPrintout :: Full ) && builder. multimodule {
843- return Err ( SpirvBuilderError :: MultiModuleWithPrintMetadata ) ;
862+ if builder. build_script . get_env_shader_spv_path ( ) && builder. multimodule {
863+ return Err ( SpirvBuilderError :: MultiModuleWithEnvShaderSpvPath ) ;
844864 }
845865 if !path_to_crate. is_dir ( ) {
846866 return Err ( SpirvBuilderError :: CratePathDoesntExist (
@@ -905,7 +925,7 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
905925
906926 // Wrapper for `env::var` that appropriately informs Cargo of the dependency.
907927 let tracked_env_var_get = |name| {
908- if let MetadataPrintout :: Full | MetadataPrintout :: DependencyOnly = builder. print_metadata {
928+ if builder. build_script . get_dependency_info ( ) {
909929 println ! ( "cargo:rerun-if-env-changed={name}" ) ;
910930 }
911931 env:: var ( name)
0 commit comments