@@ -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" ) ]
@@ -126,21 +128,6 @@ pub enum SpirvBuilderError {
126128 WatchFailed ( #[ from] SpirvWatcherError ) ,
127129}
128130
129- #[ derive( Debug , PartialEq , Eq , Clone , Copy , Default , serde:: Deserialize , serde:: Serialize ) ]
130- #[ cfg_attr( feature = "clap" , derive( clap:: ValueEnum ) ) ]
131- #[ non_exhaustive]
132- pub enum MetadataPrintout {
133- /// Print no cargo metadata.
134- #[ default]
135- None ,
136- /// Print only dependency information (eg for multiple modules).
137- DependencyOnly ,
138- /// Print all cargo metadata.
139- ///
140- /// Includes dependency information and spirv environment variable.
141- Full ,
142- }
143-
144131#[ derive( Debug , PartialEq , Eq , Clone , Copy , Default , serde:: Deserialize , serde:: Serialize ) ]
145132#[ cfg_attr( feature = "clap" , derive( clap:: ValueEnum ) ) ]
146133#[ non_exhaustive]
@@ -384,6 +371,70 @@ impl Default for ShaderCrateFeatures {
384371 }
385372}
386373
374+ /// Configuration for build scripts
375+ #[ derive( Clone , Debug , Default ) ]
376+ #[ non_exhaustive]
377+ pub struct BuildScriptConfig {
378+ /// Enable this if you are using `spirv-builder` from a build script to apply some recommended default options, such
379+ /// as [`Self::dependency_info`].
380+ pub defaults : bool ,
381+
382+ /// Print dependency information for cargo build scripts (with `cargo::rerun-if-changed={}` and such).
383+ /// Dependency information makes cargo rerun the build script is rerun when shader source files change, thus
384+ /// rebuilding the shader.
385+ ///
386+ /// Default: [`Self::defaults`]
387+ pub dependency_info : Option < bool > ,
388+
389+ /// Whether to emit an env var pointing to the shader module file (via `cargo::rustc-env={}`). The name of the env
390+ /// var is the crate name with `.spv` appended, e.g. `sky_shader.spv`.
391+ /// Not supported together with `multimodule=true` or `.watch()`.
392+ ///
393+ /// Some examples on how to include the shader module in the source code:
394+ /// * wgpu:
395+ /// ```rust,ignore
396+ /// let shader: ShaderModuleDescriptorPassthrough = include_spirv_raw!(env!("my_shader.spv"));
397+ /// ```
398+ /// * ash
399+ /// ```rust,ignore
400+ /// let bytes: &[u8] = include_bytes!(env!("my_shader.spv"))
401+ /// let words = ash::util::read_spv(&mut std::io::Cursor::new(bytes)).unwrap();
402+ /// ```
403+ ///
404+ /// Default: `false`
405+ pub env_shader_spv_path : Option < bool > ,
406+
407+ /// Forwards any warnings or errors by rustc as build script warnings (via `cargo::warning=`). Not enabling this
408+ /// option may hide warnings if the build succeeds.
409+ ///
410+ /// Default: [`Self::defaults`]
411+ pub forward_rustc_warnings : Option < bool > ,
412+
413+ /// Pass `--color always` to cargo to force enable colorful error messages. Particularly in build scripts, these
414+ /// are disabled by default, even though we'll forward them to your console. Should your console not support colors,
415+ /// then the outer cargo executing the build script will filter out all ansi escape sequences anyway, so we're free
416+ /// to always emit them.
417+ ///
418+ /// Default: [`Self::defaults`]
419+ pub cargo_color_always : Option < bool > ,
420+ }
421+
422+ /// these all have the prefix `get` so the doc items link to the members, not these private fns
423+ impl BuildScriptConfig {
424+ fn get_dependency_info ( & self ) -> bool {
425+ self . dependency_info . unwrap_or ( self . defaults )
426+ }
427+ fn get_env_shader_spv_path ( & self ) -> bool {
428+ self . env_shader_spv_path . unwrap_or ( false )
429+ }
430+ fn get_forward_rustc_warnings ( & self ) -> bool {
431+ self . forward_rustc_warnings . unwrap_or ( self . defaults )
432+ }
433+ fn get_cargo_color_always ( & self ) -> bool {
434+ self . cargo_color_always . unwrap_or ( self . defaults )
435+ }
436+ }
437+
387438#[ derive( Clone , Debug , serde:: Deserialize , serde:: Serialize ) ]
388439#[ cfg_attr( feature = "clap" , derive( clap:: Parser ) ) ]
389440#[ non_exhaustive]
@@ -398,10 +449,10 @@ pub struct SpirvBuilder {
398449 /// `--crate-type dylib`. Defaults to true if `cargo_cmd` is `None` or `Some("rustc")`.
399450 #[ cfg_attr( feature = "clap" , clap( skip) ) ]
400451 pub cargo_cmd_like_rustc : Option < bool > ,
401- /// Whether to print build.rs cargo metadata (e.g. cargo:rustc-env=var=val). Defaults to [`MetadataPrintout::None`].
402- /// Within build scripts, set it to [`MetadataPrintout::DependencyOnly`] or [`MetadataPrintout::Full`] to ensure the build script is rerun on code changes.
452+ /// Configuration for build scripts
403453 #[ cfg_attr( feature = "clap" , clap( skip) ) ]
404- pub print_metadata : MetadataPrintout ,
454+ #[ serde( skip) ]
455+ pub build_script : BuildScriptConfig ,
405456 /// Build in release. Defaults to true.
406457 #[ cfg_attr( feature = "clap" , clap( long = "debug" , default_value = "true" , action = clap:: ArgAction :: SetFalse ) ) ]
407458 pub release : bool ,
@@ -489,7 +540,7 @@ impl Default for SpirvBuilder {
489540 path_to_crate : None ,
490541 cargo_cmd : None ,
491542 cargo_cmd_like_rustc : None ,
492- print_metadata : MetadataPrintout :: default ( ) ,
543+ build_script : BuildScriptConfig :: default ( ) ,
493544 release : true ,
494545 target : None ,
495546 deny_warnings : false ,
@@ -519,13 +570,6 @@ impl SpirvBuilder {
519570 }
520571 }
521572
522- /// Whether to print build.rs cargo metadata (e.g. cargo:rustc-env=var=val). Defaults to [`MetadataPrintout::Full`].
523- #[ must_use]
524- pub fn print_metadata ( mut self , v : MetadataPrintout ) -> Self {
525- self . print_metadata = v;
526- self
527- }
528-
529573 #[ must_use]
530574 pub fn deny_warnings ( mut self , v : bool ) -> Self {
531575 self . deny_warnings = v;
@@ -671,19 +715,15 @@ impl SpirvBuilder {
671715 self
672716 }
673717
674- /// Builds the module. If `print_metadata` is [`MetadataPrintout::Full`], you usually don't have to inspect the path
675- /// in the result, as the environment variable for the path to the module will already be set.
718+ /// Builds the module
676719 pub fn build ( & self ) -> Result < CompileResult , SpirvBuilderError > {
677720 let metadata_file = invoke_rustc ( self ) ?;
678- match self . print_metadata {
679- MetadataPrintout :: Full | MetadataPrintout :: DependencyOnly => {
680- leaf_deps ( & metadata_file, |artifact| {
681- println ! ( "cargo:rerun-if-changed={artifact}" ) ;
682- } )
683- // Close enough
684- . map_err ( SpirvBuilderError :: MetadataFileMissing ) ?;
685- }
686- MetadataPrintout :: None => ( ) ,
721+ if self . build_script . get_dependency_info ( ) {
722+ leaf_deps ( & metadata_file, |artifact| {
723+ println ! ( "cargo:rerun-if-changed={artifact}" ) ;
724+ } )
725+ // Close enough
726+ . map_err ( SpirvBuilderError :: MetadataFileMissing ) ?;
687727 }
688728 let metadata = self . parse_metadata_file ( & metadata_file) ?;
689729
@@ -702,17 +742,17 @@ impl SpirvBuilder {
702742 match & metadata. module {
703743 ModuleResult :: SingleModule ( spirv_module) => {
704744 assert ! ( !self . multimodule) ;
705- let env_var = format ! (
706- "{}.spv" ,
707- at . file_name ( )
708- . unwrap ( )
709- . to_str ( )
710- . unwrap ( )
711- . strip_suffix ( ARTIFACT_SUFFIX )
712- . unwrap ( )
713- ) ;
714- if self . print_metadata == MetadataPrintout :: Full {
715- println ! ( "cargo:rustc-env={}={}" , env_var, spirv_module. display( ) ) ;
745+ if self . build_script . get_env_shader_spv_path ( ) {
746+ let env_var = format ! (
747+ "{}.spv" ,
748+ at . file_name ( )
749+ . unwrap ( )
750+ . to_str ( )
751+ . unwrap ( )
752+ . strip_suffix ( ARTIFACT_SUFFIX )
753+ . unwrap ( )
754+ ) ;
755+ println ! ( "cargo:: rustc-env={}={}" , env_var, spirv_module. display( ) ) ;
716756 }
717757 }
718758 ModuleResult :: MultiModule ( _) => {
@@ -788,8 +828,8 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
788828 . ok_or ( SpirvBuilderError :: MissingTarget ) ?;
789829 target = SpirvTarget :: parse ( target_str) ?;
790830
791- if ( builder. print_metadata == MetadataPrintout :: Full ) && builder. multimodule {
792- return Err ( SpirvBuilderError :: MultiModuleWithPrintMetadata ) ;
831+ if builder. build_script . get_env_shader_spv_path ( ) && builder. multimodule {
832+ return Err ( SpirvBuilderError :: MultiModuleWithEnvShaderSpvPath ) ;
793833 }
794834 if !path_to_crate. is_dir ( ) {
795835 return Err ( SpirvBuilderError :: CratePathDoesntExist (
@@ -854,7 +894,7 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
854894
855895 // Wrapper for `env::var` that appropriately informs Cargo of the dependency.
856896 let tracked_env_var_get = |name| {
857- if let MetadataPrintout :: Full | MetadataPrintout :: DependencyOnly = builder. print_metadata {
897+ if builder. build_script . get_dependency_info ( ) {
858898 println ! ( "cargo:rerun-if-env-changed={name}" ) ;
859899 }
860900 env:: var ( name)
@@ -1000,6 +1040,16 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
10001040
10011041 cargo. arg ( "--target-dir" ) . arg ( target_dir) ;
10021042
1043+ // Args for warning and error forwarding
1044+ if builder. build_script . get_forward_rustc_warnings ( ) {
1045+ // Quiet to remove all the status messages and only emit errors and warnings
1046+ cargo. args ( [ "--quiet" ] ) ;
1047+ }
1048+ if builder. build_script . get_cargo_color_always ( ) {
1049+ // Always emit color, since the outer cargo will remove ascii escape sequences if color is turned off
1050+ cargo. args ( [ "--color" , "always" ] ) ;
1051+ }
1052+
10031053 // NOTE(eddyb) this used to be just `RUSTFLAGS` but at some point Cargo
10041054 // added a separate environment variable using `\x1f` instead of spaces,
10051055 // which allows us to have spaces within individual `rustc` flags.
@@ -1017,10 +1067,20 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
10171067 num_cgus. to_string ( ) ,
10181068 ) ;
10191069
1020- cargo. stderr ( Stdio :: inherit ( ) ) . current_dir ( path_to_crate) ;
1070+ if !builder. build_script . get_forward_rustc_warnings ( ) {
1071+ cargo. stderr ( Stdio :: inherit ( ) ) ;
1072+ }
1073+ cargo. current_dir ( path_to_crate) ;
10211074 log:: debug!( "building shaders with `{cargo:?}`" ) ;
10221075 let build = cargo. output ( ) . expect ( "failed to execute cargo build" ) ;
10231076
1077+ if builder. build_script . get_forward_rustc_warnings ( ) {
1078+ let stderr = String :: from_utf8 ( build. stderr ) . unwrap ( ) ;
1079+ for line in stderr. lines ( ) {
1080+ println ! ( "cargo::warning={line}" ) ;
1081+ }
1082+ }
1083+
10241084 // `get_last_artifact` has the side-effect of printing invalid lines, so
10251085 // we do that even in case of an error, to let through any useful messages
10261086 // that ended up on stdout instead of stderr.
0 commit comments