2
2
//!
3
3
//! See the `target-lexicon` crate for a more principled approach to this.
4
4
5
- use std:: str:: FromStr ;
6
-
7
- use crate :: { Error , ErrorKind } ;
8
-
9
5
mod apple;
10
- mod generated;
11
6
mod llvm;
12
7
mod parser;
13
8
@@ -43,47 +38,11 @@ pub(crate) struct TargetInfo<'a> {
43
38
///
44
39
/// This is the same as the value of `cfg!(target_abi)`.
45
40
pub 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
- }
82
41
}
83
42
84
43
#[ cfg( test) ]
85
44
mod tests {
86
- use std:: str :: FromStr ;
45
+ use std:: process :: Command ;
87
46
88
47
use super :: TargetInfo ;
89
48
@@ -104,13 +63,92 @@ mod tests {
104
63
105
64
for target in targets {
106
65
// 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" ) ;
108
146
}
109
147
}
110
148
111
149
// Various custom target triples not (or no longer) known by `rustc`
112
150
#[ test]
113
- fn cannot_parse_extra ( ) {
151
+ fn parse_extra ( ) {
114
152
let targets = [
115
153
"aarch64-unknown-none-gnu" ,
116
154
"aarch64-uwp-windows-gnu" ,
@@ -120,13 +158,20 @@ mod tests {
120
158
"armv7neon-unknown-linux-musleabihf" ,
121
159
"thumbv7-unknown-linux-gnueabihf" ,
122
160
"thumbv7-unknown-linux-musleabihf" ,
161
+ "armv7-apple-ios" ,
162
+ "wasm32-wasi" ,
123
163
"x86_64-rumprun-netbsd" ,
124
164
"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" ,
125
170
] ;
126
171
127
172
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 ( ) ;
130
175
}
131
176
}
132
177
}
0 commit comments