Skip to content

Commit b8f659b

Browse files
committed
compile_codegen: SpirvBuilder: only use target_spec json when compiler is new enough
1 parent e040ab9 commit b8f659b

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

Cargo.lock

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/spirv-builder/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ raw-string = "0.3.5"
4343
serde = { version = "1.0", features = ["derive"] }
4444
serde_json = "1.0"
4545
thiserror = "2.0.12"
46+
semver = { version = "1.0.24", features = ["serde"] }
4647

4748
notify = { version = "7.0", optional = true }
4849
# Pinning clap, as newer versions have raised min rustc version without being marked a breaking change

crates/spirv-builder/src/lib.rs

+44-7
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ mod target_specs;
7878
mod watch;
7979

8080
use raw_string::{RawStr, RawString};
81+
use semver::Version;
8182
use serde::Deserialize;
8283
use std::borrow::Borrow;
8384
use std::collections::HashMap;
@@ -403,6 +404,9 @@ pub struct SpirvBuilder {
403404
// Overwrite the toolchain like `cargo +nightly`
404405
#[cfg_attr(feature = "clap", clap(skip))]
405406
pub toolchain_overwrite: Option<String>,
407+
// Set the rustc version of the toolchain, used to adjust params to support older toolchains
408+
#[cfg_attr(feature = "clap", clap(skip))]
409+
pub toolchain_rustc_version: Option<Version>,
406410

407411
/// The path of the "target specification" file.
408412
///
@@ -460,6 +464,7 @@ impl Default for SpirvBuilder {
460464
path_to_target_spec: None,
461465
target_dir_path: None,
462466
toolchain_overwrite: None,
467+
toolchain_rustc_version: None,
463468
shader_panic_strategy: ShaderPanicStrategy::default(),
464469
validator: ValidatorOptions::default(),
465470
optimizer: OptimizerOptions::default(),
@@ -781,6 +786,13 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
781786
}
782787
}
783788

789+
let toolchain_rustc_version =
790+
if let Some(toolchain_rustc_version) = &builder.toolchain_rustc_version {
791+
toolchain_rustc_version.clone()
792+
} else {
793+
query_rustc_version(builder.toolchain_overwrite.as_deref())?
794+
};
795+
784796
// Okay, this is a little bonkers: in a normal world, we'd have the user clone
785797
// rustc_codegen_spirv and pass in the path to it, and then we'd invoke cargo to build it, grab
786798
// the resulting .so, and pass it into -Z codegen-backend. But that's really gross: the user
@@ -958,13 +970,21 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
958970

959971
// FIXME(eddyb) consider moving `target-specs` into `rustc_codegen_spirv_types`.
960972
// FIXME(eddyb) consider the `RUST_TARGET_PATH` env var alternative.
961-
cargo
962-
.arg("--target")
963-
.arg(builder.path_to_target_spec.clone().unwrap_or_else(|| {
964-
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
965-
.join("target-specs")
966-
.join(format!("{}.json", target))
967-
}));
973+
974+
// NOTE(firestar99) rustc 1.76 has been tested to correctly parse modern
975+
// target_spec jsons, some later version requires them, some earlier
976+
// version fails with them (notably our 0.9.0 release)
977+
if toolchain_rustc_version >= Version::new(1, 76, 0) {
978+
cargo
979+
.arg("--target")
980+
.arg(builder.path_to_target_spec.clone().unwrap_or_else(|| {
981+
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
982+
.join("target-specs")
983+
.join(format!("{}.json", target))
984+
}));
985+
} else {
986+
cargo.arg("--target").arg(target);
987+
}
968988

969989
if !builder.shader_crate_features.default_features {
970990
cargo.arg("--no-default-features");
@@ -1108,3 +1128,20 @@ fn leaf_deps(artifact: &Path, mut handle: impl FnMut(&RawStr)) -> std::io::Resul
11081128
recurse(&deps_map, artifact.to_str().unwrap().into(), &mut handle);
11091129
Ok(())
11101130
}
1131+
1132+
pub fn query_rustc_version(toolchain: Option<&str>) -> std::io::Result<Version> {
1133+
let mut cmd = Command::new("rustc");
1134+
if let Some(toolchain) = toolchain {
1135+
cmd.arg(format!("+{}", toolchain));
1136+
}
1137+
cmd.arg("--version");
1138+
1139+
let parse = |stdout| {
1140+
let output = String::from_utf8(stdout).ok()?;
1141+
let output = output.strip_prefix("rustc ")?;
1142+
let version = &output[..output.find("-")?];
1143+
Some(Version::parse(version).expect("invalid version"))
1144+
};
1145+
1146+
Ok(parse(cmd.output()?.stdout).expect("rustc --version parsing failed"))
1147+
}

0 commit comments

Comments
 (0)