22//! 
33//! See the `target-lexicon` crate for a more principled approach to this. 
44
5- use  std:: str:: FromStr ; 
6- 
7- use  crate :: { Error ,  ErrorKind } ; 
8- 
95mod  apple; 
10- mod  generated; 
116mod  llvm; 
127mod  parser; 
138
@@ -43,47 +38,11 @@ pub(crate) struct TargetInfo<'a> {
4338/// 
4439/// This is the same as the value of `cfg!(target_abi)`. 
4540pub  abi :  & ' a  str , 
46-     /// The unversioned LLVM/Clang target triple. 
47- /// 
48- /// NOTE: You should never need to match on this explicitly, use the other 
49- /// fields on [`TargetInfo`] instead. 
50- pub  llvm_target :  & ' a  str , 
51- } 
52- 
53- impl  FromStr  for  TargetInfo < ' _ >  { 
54-     type  Err  = Error ; 
55- 
56-     /// This will fail when using a custom target triple unknown to `rustc`. 
57- fn  from_str ( target_triple :  & str )  -> Result < Self ,  Error >  { 
58-         if  let  Ok ( index)  =
59-             generated:: LIST . binary_search_by_key ( & target_triple,  |( target_triple,  _) | target_triple) 
60-         { 
61-             let  ( _,  info)  = & generated:: LIST [ index] ; 
62-             Ok ( info. clone ( ) ) 
63-         }  else  { 
64-             Err ( Error :: new ( 
65-                 ErrorKind :: UnknownTarget , 
66-                 format ! ( 
67-                     "unknown target `{target_triple}`. 
68- 
69- NOTE: `cc-rs` only supports a fixed set of targets when not in a build script. 
70- - If adding a new target, you will need to fork of `cc-rs` until the target 
71-   has landed on nightly and the auto-generated list has been updated. See also 
72-   the `rustc` dev guide on adding a new target: 
73-   https://rustc-dev-guide.rust-lang.org/building/new-target.html 
74- - If using a custom target, prefer to upstream it to `rustc` if possible, 
75-   otherwise open an issue with `cc-rs`: 
76-   https://github.com/rust-lang/cc-rs/issues/new 
77- " 
78-                 ) , 
79-             ) ) 
80-         } 
81-     } 
8241} 
8342
8443#[ cfg( test) ]  
8544mod  tests { 
86-     use  std:: str :: FromStr ; 
45+     use  std:: process :: Command ; 
8746
8847    use  super :: TargetInfo ; 
8948
@@ -104,13 +63,92 @@ mod tests {
10463
10564        for  target in  targets { 
10665            // Check that it parses 
107-             let  _ = TargetInfo :: from_str ( target) . unwrap ( ) ; 
66+             let  _ = TargetInfo :: from_rustc_target ( target) . unwrap ( ) ; 
67+         } 
68+     } 
69+ 
70+     fn  target_from_rustc_cfgs < ' a > ( target :  & ' a  str ,  cfgs :  & ' a  str )  -> TargetInfo < ' a >  { 
71+         // Cannot determine full architecture from cfgs. 
72+         let  ( full_arch,  _rest)  = target. split_once ( '-' ) . expect ( "target to have arch" ) ; 
73+ 
74+         let  mut  target = TargetInfo  { 
75+             full_arch :  full_arch. into ( ) , 
76+             arch :  "invalid-none-set" . into ( ) , 
77+             vendor :  "invalid-none-set" . into ( ) , 
78+             os :  "invalid-none-set" . into ( ) , 
79+             env :  "invalid-none-set" . into ( ) , 
80+             // Not set in older Rust versions 
81+             abi :  "" . into ( ) , 
82+         } ; 
83+ 
84+         for  cfg in  cfgs. lines ( )  { 
85+             if  let  Some ( ( name,  value) )  = cfg. split_once ( '=' )  { 
86+                 // Remove whitespace, if `rustc` decided to insert any 
87+                 let  name = name. trim ( ) ; 
88+                 let  value = value. trim ( ) ; 
89+ 
90+                 // Remove quotes around value 
91+                 let  value = value. strip_prefix ( '"' ) . unwrap_or ( value) ; 
92+                 let  value = value. strip_suffix ( '"' ) . unwrap_or ( value) ; 
93+ 
94+                 match  name { 
95+                     "target_arch"  => target. arch  = value, 
96+                     "target_vendor"  => target. vendor  = value, 
97+                     "target_os"  => target. os  = value, 
98+                     "target_env"  => target. env  = value, 
99+                     "target_abi"  => target. abi  = value, 
100+                     _ => { } 
101+                 } 
102+             }  else  { 
103+                 // Skip cfgs like `debug_assertions` and `unix`. 
104+             } 
105+         } 
106+ 
107+         target
108+     } 
109+ 
110+     #[ test]  
111+     fn  parse_rustc_targets ( )  { 
112+         let  rustc = std:: env:: var ( "RUSTC" ) . unwrap_or_else ( |_| "rustc" . to_string ( ) ) ; 
113+ 
114+         let  target_list = Command :: new ( & rustc) 
115+             . arg ( "--print=target-list" ) 
116+             . output ( ) 
117+             . unwrap ( ) 
118+             . stdout ; 
119+         let  target_list = String :: from_utf8 ( target_list) . unwrap ( ) ; 
120+ 
121+         let  mut  has_failure = false ; 
122+         for  target in  target_list. lines ( )  { 
123+             let  cfgs = Command :: new ( & rustc) 
124+                 . arg ( "--target" ) 
125+                 . arg ( target) 
126+                 . arg ( "--print=cfg" ) 
127+                 . output ( ) 
128+                 . unwrap ( ) 
129+                 . stdout ; 
130+             let  cfgs = String :: from_utf8 ( cfgs) . unwrap ( ) ; 
131+ 
132+             let  expected = target_from_rustc_cfgs ( target,  & cfgs) ; 
133+             let  actual = TargetInfo :: from_rustc_target ( target) ; 
134+ 
135+             if  Some ( & expected)  != actual. as_ref ( ) . ok ( )  { 
136+                 eprintln ! ( "failed comparing {target}:" ) ; 
137+                 eprintln ! ( "  expected: Ok({expected:?})" ) ; 
138+                 eprintln ! ( "    actual: {actual:?}" ) ; 
139+                 eprintln ! ( ) ; 
140+                 has_failure = true ; 
141+             } 
142+         } 
143+ 
144+         if  has_failure { 
145+             panic ! ( "failed comparing targets" ) ; 
108146        } 
109147    } 
110148
111149    // Various custom target triples not (or no longer) known by `rustc` 
112150    #[ test]  
113-     fn  cannot_parse_extra ( )  { 
151+     fn  parse_extra ( )  { 
114152        let  targets = [ 
115153            "aarch64-unknown-none-gnu" , 
116154            "aarch64-uwp-windows-gnu" , 
@@ -120,13 +158,20 @@ mod tests {
120158            "armv7neon-unknown-linux-musleabihf" , 
121159            "thumbv7-unknown-linux-gnueabihf" , 
122160            "thumbv7-unknown-linux-musleabihf" , 
161+             "armv7-apple-ios" , 
162+             "wasm32-wasi" , 
123163            "x86_64-rumprun-netbsd" , 
124164            "x86_64-unknown-linux" , 
165+             "x86_64-alpine-linux-musl" , 
166+             "x86_64-chimera-linux-musl" , 
167+             "x86_64-foxkit-linux-musl" , 
168+             "arm-poky-linux-gnueabi" , 
169+             "x86_64-unknown-moturus" , 
125170        ] ; 
126171
127172        for  target in  targets { 
128-             // Check that it does not parse  
129-             let  _ = TargetInfo :: from_str ( target) . unwrap_err ( ) ; 
173+             // Check that it parses  
174+             let  _ = TargetInfo :: from_rustc_target ( target) . unwrap ( ) ; 
130175        } 
131176    } 
132177} 
0 commit comments