Skip to content

Commit c8078ed

Browse files
committed
spirv-builder: make required extra arg -Zjson-target-spec backwards compatible
1 parent 85cd195 commit c8078ed

File tree

3 files changed

+49
-27
lines changed

3 files changed

+49
-27
lines changed

crates/rustc_codegen_spirv-types/src/target_spec.rs

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use crate::SpirvTarget;
22
use semver::Version;
3-
use std::ffi::OsString;
3+
use std::ffi::OsStr;
44
use std::path::Path;
55

66
/// Enum for different versions of target specs, to allow changing the target spec for different rust versions.
77
/// The version listed in the enum is always the minimum version to require said target spec, with the newest version
88
/// always at the top.
99
#[allow(non_camel_case_types)]
10-
#[derive(Copy, Clone, Debug)]
10+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
1111
pub enum TargetSpecVersion {
12+
Older,
1213
/// Introduced in `489c3ee6fd63da3ca7cf2b15e1ee709d8e078aab` in the old v2 target spec way, later ported to here.
1314
/// remove `os: unknown`, add `crt-static-respected: true`
1415
Rustc_1_85_0,
@@ -18,47 +19,68 @@ pub enum TargetSpecVersion {
1819
Rustc_1_76_0,
1920
/// rustc 1.93 requires that the value of "target-pointer-width" is no longer a string but u16
2021
Rustc_1_93_0,
22+
/// rustc 1.94.0 destabilised json target specs, requiring `-Ztarget-spec-json`
23+
/// see https://github.com/Rust-GPU/rust-gpu/pull/545
24+
/// see https://github.com/rust-lang/rust/pull/150151
25+
Rustc_1_94_0,
2126
}
2227

2328
impl TargetSpecVersion {
2429
/// Format the `--target` arg. On newer rustc versions, will create a compatible target spec json file and return
2530
/// the absolute path to it, on older rustc versions may return the target name.
26-
pub fn target_arg(
31+
pub fn append_target_arg(
2732
rustc_version: Version,
2833
target: &SpirvTarget,
2934
target_spec_folder: &Path,
30-
) -> std::io::Result<OsString> {
31-
if let Some(target_spec) = Self::from_rustc_version(rustc_version) {
32-
std::fs::create_dir_all(target_spec_folder)?;
33-
let spec_file = target_spec_folder.join(format!("{}.json", target.target()));
34-
std::fs::write(&spec_file, target_spec.format_spec(target))?;
35-
Ok(std::fs::canonicalize(spec_file)?.into_os_string())
36-
} else {
37-
Ok(OsString::from(target.target()))
35+
mut push_arg: impl FnMut(&OsStr),
36+
) -> std::io::Result<()> {
37+
let target_spec = Self::from_rustc_version(rustc_version);
38+
if target_spec >= Self::Rustc_1_94_0 {
39+
push_arg("-Zjson-target-spec".as_ref());
40+
}
41+
42+
push_arg("--target".as_ref());
43+
match target_spec {
44+
TargetSpecVersion::Older => {
45+
push_arg(target.target().as_ref());
46+
}
47+
_ => {
48+
std::fs::create_dir_all(target_spec_folder)?;
49+
let spec_file = target_spec_folder.join(format!("{}.json", target.target()));
50+
std::fs::write(&spec_file, target_spec.format_spec(target))?;
51+
let spec_file = std::fs::canonicalize(spec_file)?.into_os_string();
52+
push_arg(&spec_file);
53+
}
3854
}
55+
Ok(())
3956
}
4057

4158
/// Returns the version of the target spec required for a certain rustc version. May return `None` if the version
4259
/// is old enough to not need target specs.
43-
pub fn from_rustc_version(rustc_version: Version) -> Option<Self> {
44-
if rustc_version >= Version::new(1, 93, 0) {
45-
Some(Self::Rustc_1_93_0)
60+
pub fn from_rustc_version(rustc_version: Version) -> Self {
61+
if rustc_version >= Version::new(1, 94, 0) {
62+
Self::Rustc_1_94_0
63+
} else if rustc_version >= Version::new(1, 93, 0) {
64+
Self::Rustc_1_93_0
4665
} else if rustc_version >= Version::new(1, 85, 0) {
47-
Some(Self::Rustc_1_85_0)
66+
Self::Rustc_1_85_0
4867
} else if rustc_version >= Version::new(1, 76, 0) {
49-
Some(Self::Rustc_1_76_0)
68+
Self::Rustc_1_76_0
5069
} else {
51-
None
70+
Self::Older
5271
}
5372
}
5473

5574
/// format the target spec json
5675
pub fn format_spec(&self, target: &SpirvTarget) -> String {
5776
let target_env = target.env();
5877
let (extra, target_pointer_width) = match self {
78+
TargetSpecVersion::Older => panic!("no target specs for older rustc versions"),
5979
TargetSpecVersion::Rustc_1_76_0 => (r#""os": "unknown","#, "\"32\""),
6080
TargetSpecVersion::Rustc_1_85_0 => (r#""crt-static-respected": true,"#, "\"32\""),
61-
TargetSpecVersion::Rustc_1_93_0 => (r#""crt-static-respected": true,"#, "32"),
81+
TargetSpecVersion::Rustc_1_93_0 | TargetSpecVersion::Rustc_1_94_0 => {
82+
(r#""crt-static-respected": true,"#, "32")
83+
}
6284
};
6385
format!(
6486
r#"{{

crates/spirv-builder/src/lib.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,14 +1046,14 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
10461046
}
10471047

10481048
let target_spec_dir = target_dir.join("target-specs");
1049-
let target = TargetSpecVersion::target_arg(toolchain_rustc_version, &target, &target_spec_dir)?;
1050-
if Path::new(&target)
1051-
.extension()
1052-
.is_some_and(|ext| ext == "json")
1053-
{
1054-
cargo.arg("-Zjson-target-spec");
1055-
}
1056-
cargo.arg("--target").arg(target);
1049+
TargetSpecVersion::append_target_arg(
1050+
toolchain_rustc_version,
1051+
&target,
1052+
&target_spec_dir,
1053+
|arg| {
1054+
cargo.arg(arg);
1055+
},
1056+
)?;
10571057

10581058
if !builder.shader_crate_features.default_features {
10591059
cargo.arg("--no-default-features");

tests/compiletests/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ impl Runner {
268268

269269
fn target_spec_json(&self, target: &SpirvTarget) -> OsString {
270270
let rustc_version = query_rustc_version(None).unwrap();
271-
TargetSpecVersion::target_arg(rustc_version, target, &self.deps_target_dir).unwrap()
271+
TargetSpecVersion::append_target_arg(rustc_version, target, &self.deps_target_dir).unwrap()
272272
}
273273
}
274274

0 commit comments

Comments
 (0)