Skip to content

Commit b55dcab

Browse files
committed
Merge branch 'fwd_warnings' into no_artifacts
# Conflicts: # crates/spirv-builder/src/lib.rs
2 parents a64583d + 8b83d58 commit b55dcab

8 files changed

Lines changed: 138 additions & 82 deletions

File tree

crates/spirv-builder/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ It takes care of pulling in the `SPIR-V` backend for Rust, `rustc_codegen_spirv`
1111
## Example
1212

1313
```rust,no_run
14-
use spirv_builder::{MetadataPrintout, SpirvBuilder};
15-
14+
# use spirv_builder::SpirvBuilder;
15+
#
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 = Some(true);
20+
builder.build()?;
2021
Ok(())
2122
}
2223
```

crates/spirv-builder/src/lib.rs

Lines changed: 114 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -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.

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: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
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+
builder.build_script.env_shader_spv_path = Some(true);
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+
builder.target_dir_path = Some(PathBuf::from("example-runner-wgpu-builder"));
15+
let result = builder.build()?;
1616
if codegen_names {
1717
let out_dir = env::var_os("OUT_DIR").unwrap();
1818
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)