11use crate :: SpirvTarget ;
22use semver:: Version ;
3- use std:: ffi:: OsString ;
3+ use std:: ffi:: OsStr ;
44use 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 ) ]
1111pub 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,67 @@ 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-lang/rust/pull/150151
24+ Rustc_1_94_0 ,
2125}
2226
2327impl TargetSpecVersion {
2428 /// Format the `--target` arg. On newer rustc versions, will create a compatible target spec json file and return
2529 /// the absolute path to it, on older rustc versions may return the target name.
26- pub fn target_arg (
30+ pub fn append_target_arg (
2731 rustc_version : Version ,
2832 target : & SpirvTarget ,
2933 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 ( ) ) )
34+ mut push_arg : impl FnMut ( & OsStr ) ,
35+ ) -> std:: io:: Result < ( ) > {
36+ let target_spec = Self :: from_rustc_version ( rustc_version) ;
37+ if target_spec >= Self :: Rustc_1_94_0 {
38+ push_arg ( "-Zjson-target-spec" . as_ref ( ) ) ;
39+ }
40+
41+ push_arg ( "--target" . as_ref ( ) ) ;
42+ match target_spec {
43+ TargetSpecVersion :: Older => {
44+ push_arg ( target. target ( ) . as_ref ( ) ) ;
45+ }
46+ _ => {
47+ std:: fs:: create_dir_all ( target_spec_folder) ?;
48+ let spec_file = target_spec_folder. join ( format ! ( "{}.json" , target. target( ) ) ) ;
49+ std:: fs:: write ( & spec_file, target_spec. format_spec ( target) ) ?;
50+ let spec_file = std:: fs:: canonicalize ( spec_file) ?. into_os_string ( ) ;
51+ push_arg ( & spec_file) ;
52+ }
3853 }
54+ Ok ( ( ) )
3955 }
4056
4157 /// Returns the version of the target spec required for a certain rustc version. May return `None` if the version
4258 /// 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 )
59+ pub fn from_rustc_version ( rustc_version : Version ) -> Self {
60+ if rustc_version >= Version :: new ( 1 , 94 , 0 ) {
61+ Self :: Rustc_1_94_0
62+ } else if rustc_version >= Version :: new ( 1 , 93 , 0 ) {
63+ Self :: Rustc_1_93_0
4664 } else if rustc_version >= Version :: new ( 1 , 85 , 0 ) {
47- Some ( Self :: Rustc_1_85_0 )
65+ Self :: Rustc_1_85_0
4866 } else if rustc_version >= Version :: new ( 1 , 76 , 0 ) {
49- Some ( Self :: Rustc_1_76_0 )
67+ Self :: Rustc_1_76_0
5068 } else {
51- None
69+ Self :: Older
5270 }
5371 }
5472
5573 /// format the target spec json
5674 pub fn format_spec ( & self , target : & SpirvTarget ) -> String {
5775 let target_env = target. env ( ) ;
5876 let ( extra, target_pointer_width) = match self {
77+ TargetSpecVersion :: Older => panic ! ( "no target specs for older rustc versions" ) ,
5978 TargetSpecVersion :: Rustc_1_76_0 => ( r#""os": "unknown","# , "\" 32\" " ) ,
6079 TargetSpecVersion :: Rustc_1_85_0 => ( r#""crt-static-respected": true,"# , "\" 32\" " ) ,
61- TargetSpecVersion :: Rustc_1_93_0 => ( r#""crt-static-respected": true,"# , "32" ) ,
80+ TargetSpecVersion :: Rustc_1_93_0 | TargetSpecVersion :: Rustc_1_94_0 => {
81+ ( r#""crt-static-respected": true,"# , "32" )
82+ }
6283 } ;
6384 format ! (
6485 r#"{{
0 commit comments