@@ -9,17 +9,34 @@ use crate::core::TargetKind;
9
9
use crate :: util:: CfgExpr ;
10
10
use crate :: util:: { CargoResult , CargoResultExt , Cfg , Config , ProcessBuilder , Rustc } ;
11
11
12
+ /// Information about the platform target gleaned from querying rustc.
13
+ ///
14
+ /// The `BuildContext` keeps two of these, one for the host and one for the
15
+ /// target. If no target is specified, it uses a clone from the host.
12
16
#[ derive( Clone ) ]
13
17
pub struct TargetInfo {
14
- crate_type_process : Option < ProcessBuilder > ,
18
+ /// A base process builder for discovering crate type information. In
19
+ /// particular, this is used to determine the output filename prefix and
20
+ /// suffix for a crate type.
21
+ crate_type_process : ProcessBuilder ,
22
+ /// Cache of output filename prefixes and suffixes.
23
+ ///
24
+ /// The key is the crate type name (like `cdylib`) and the value is
25
+ /// `Some((prefix, suffix))`, for example `libcargo.so` would be
26
+ /// `Some(("lib", ".so")). The value is `None` if the crate type is not
27
+ /// supported.
15
28
crate_types : RefCell < HashMap < String , Option < ( String , String ) > > > ,
16
- cfg : Option < Vec < Cfg > > ,
17
- pub sysroot_libdir : Option < PathBuf > ,
29
+ /// `cfg` information extracted from `rustc --print=cfg`.
30
+ cfg : Vec < Cfg > ,
31
+ /// Path to the "lib" directory in the sysroot.
32
+ pub sysroot_libdir : PathBuf ,
33
+ /// Extra flags to pass to `rustc`, see `env_args`.
18
34
pub rustflags : Vec < String > ,
35
+ /// Extra flags to pass to `rustdoc`, see `env_args`.
19
36
pub rustdocflags : Vec < String > ,
20
37
}
21
38
22
- /// Type of each file generated by a Unit.
39
+ /// Kind of each file generated by a Unit, part of `FileType` .
23
40
#[ derive( Clone , PartialEq , Eq , Debug ) ]
24
41
pub enum FileFlavor {
25
42
/// Not a special file type.
@@ -30,9 +47,13 @@ pub enum FileFlavor {
30
47
DebugInfo ,
31
48
}
32
49
50
+ /// Type of each file generated by a Unit.
33
51
pub struct FileType {
52
+ /// The kind of file.
34
53
pub flavor : FileFlavor ,
54
+ /// The suffix for the file (for example, `.rlib`).
35
55
suffix : String ,
56
+ /// The prefix for the file (for example, `lib`).
36
57
prefix : String ,
37
58
// Wasm bin target will generate two files in deps such as
38
59
// "web-stuff.js" and "web_stuff.wasm". Note the different usages of
@@ -92,60 +113,51 @@ impl TargetInfo {
92
113
process. arg ( "--crate-type" ) . arg ( crate_type) ;
93
114
}
94
115
95
- let mut with_cfg = process. clone ( ) ;
96
- with_cfg. arg ( "--print=sysroot" ) ;
97
- with_cfg. arg ( "--print=cfg" ) ;
116
+ process. arg ( "--print=sysroot" ) ;
117
+ process. arg ( "--print=cfg" ) ;
98
118
99
- let mut has_cfg_and_sysroot = true ;
100
119
let ( output, error) = rustc
101
- . cached_output ( & with_cfg)
102
- . or_else ( |_| {
103
- has_cfg_and_sysroot = false ;
104
- rustc. cached_output ( & process)
105
- } )
120
+ . cached_output ( & process)
106
121
. chain_err ( || "failed to run `rustc` to learn about target-specific information" ) ?;
107
122
108
123
let mut lines = output. lines ( ) ;
109
124
let mut map = HashMap :: new ( ) ;
110
125
for crate_type in KNOWN_CRATE_TYPES {
111
- let out = parse_crate_type ( crate_type, & error, & mut lines) ?;
126
+ let out = parse_crate_type ( crate_type, & process , & output , & error, & mut lines) ?;
112
127
map. insert ( crate_type. to_string ( ) , out) ;
113
128
}
114
129
115
- let mut sysroot_libdir = None ;
116
- if has_cfg_and_sysroot {
117
- let line = match lines . next ( ) {
118
- Some ( line ) => line ,
119
- None => failure :: bail! (
120
- " output of --print=sysroot missing when learning about \
121
- target-specific information from rustc"
122
- ) ,
123
- } ;
124
- let mut rustlib = PathBuf :: from ( line ) ;
125
- if kind == Kind :: Host {
130
+ let line = match lines . next ( ) {
131
+ Some ( line ) => line ,
132
+ None => failure :: bail! (
133
+ "output of --print=sysroot missing when learning about \
134
+ target-specific information from rustc \n {}" ,
135
+ output_err_info ( & process , & output, & error )
136
+ ) ,
137
+ } ;
138
+ let mut rustlib = PathBuf :: from ( line ) ;
139
+ let sysroot_libdir = match kind {
140
+ Kind :: Host => {
126
141
if cfg ! ( windows) {
127
142
rustlib. push ( "bin" ) ;
128
143
} else {
129
144
rustlib. push ( "lib" ) ;
130
145
}
131
- sysroot_libdir = Some ( rustlib) ;
132
- } else {
146
+ rustlib
147
+ }
148
+ Kind :: Target => {
133
149
rustlib. push ( "lib" ) ;
134
150
rustlib. push ( "rustlib" ) ;
135
151
rustlib. push ( target_triple) ;
136
152
rustlib. push ( "lib" ) ;
137
- sysroot_libdir = Some ( rustlib) ;
153
+ rustlib
138
154
}
139
- }
140
-
141
- let cfg = if has_cfg_and_sysroot {
142
- Some ( lines. map ( Cfg :: from_str) . collect :: < CargoResult < Vec < _ > > > ( ) ?)
143
- } else {
144
- None
145
155
} ;
146
156
157
+ let cfg = lines. map ( Cfg :: from_str) . collect :: < CargoResult < Vec < _ > > > ( ) ?;
158
+
147
159
Ok ( TargetInfo {
148
- crate_type_process : Some ( crate_type_process ) ,
160
+ crate_type_process,
149
161
crate_types : RefCell :: new ( map) ,
150
162
sysroot_libdir,
151
163
// recalculate `rustflags` from above now that we have `cfg`
@@ -154,24 +166,24 @@ impl TargetInfo {
154
166
config,
155
167
requested_target,
156
168
& rustc. host ,
157
- cfg . as_ref ( ) . map ( |v| v . as_ref ( ) ) ,
169
+ Some ( & cfg ) ,
158
170
kind,
159
171
"RUSTFLAGS" ,
160
172
) ?,
161
173
rustdocflags : env_args (
162
174
config,
163
175
requested_target,
164
176
& rustc. host ,
165
- cfg . as_ref ( ) . map ( |v| v . as_ref ( ) ) ,
177
+ Some ( & cfg ) ,
166
178
kind,
167
179
"RUSTDOCFLAGS" ,
168
180
) ?,
169
181
cfg,
170
182
} )
171
183
}
172
184
173
- pub fn cfg ( & self ) -> Option < & [ Cfg ] > {
174
- self . cfg . as_ref ( ) . map ( |v| v . as_ref ( ) )
185
+ pub fn cfg ( & self ) -> & [ Cfg ] {
186
+ & self . cfg
175
187
}
176
188
177
189
pub fn file_types (
@@ -255,21 +267,26 @@ impl TargetInfo {
255
267
}
256
268
257
269
fn discover_crate_type ( & self , crate_type : & str ) -> CargoResult < Option < ( String , String ) > > {
258
- let mut process = self . crate_type_process . clone ( ) . unwrap ( ) ;
270
+ let mut process = self . crate_type_process . clone ( ) ;
259
271
260
272
process. arg ( "--crate-type" ) . arg ( crate_type) ;
261
273
262
274
let output = process. exec_with_output ( ) . chain_err ( || {
263
275
format ! (
264
- "failed to run `rustc` to learn about \
265
- crate-type {} information",
276
+ "failed to run `rustc` to learn about crate-type {} information" ,
266
277
crate_type
267
278
)
268
279
} ) ?;
269
280
270
281
let error = str:: from_utf8 ( & output. stderr ) . unwrap ( ) ;
271
282
let output = str:: from_utf8 ( & output. stdout ) . unwrap ( ) ;
272
- Ok ( parse_crate_type ( crate_type, error, & mut output. lines ( ) ) ?)
283
+ Ok ( parse_crate_type (
284
+ crate_type,
285
+ & process,
286
+ output,
287
+ error,
288
+ & mut output. lines ( ) ,
289
+ ) ?)
273
290
}
274
291
}
275
292
@@ -284,6 +301,8 @@ impl TargetInfo {
284
301
// are two files for bin (`.wasm` and `.js`)).
285
302
fn parse_crate_type (
286
303
crate_type : & str ,
304
+ cmd : & ProcessBuilder ,
305
+ output : & str ,
287
306
error : & str ,
288
307
lines : & mut str:: Lines < ' _ > ,
289
308
) -> CargoResult < Option < ( String , String ) > > {
@@ -297,24 +316,41 @@ fn parse_crate_type(
297
316
let line = match lines. next ( ) {
298
317
Some ( line) => line,
299
318
None => failure:: bail!(
300
- "malformed output when learning about \
301
- crate-type {} information" ,
302
- crate_type
319
+ "malformed output when learning about crate-type {} information \n {}" ,
320
+ crate_type ,
321
+ output_err_info ( cmd , output , error )
303
322
) ,
304
323
} ;
305
324
let mut parts = line. trim ( ) . split ( "___" ) ;
306
325
let prefix = parts. next ( ) . unwrap ( ) ;
307
326
let suffix = match parts. next ( ) {
308
327
Some ( part) => part,
309
328
None => failure:: bail!(
310
- "output of --print=file-names has changed in \
311
- the compiler, cannot parse"
329
+ "output of --print=file-names has changed in the compiler, cannot parse \n {}" ,
330
+ output_err_info ( cmd , output , error )
312
331
) ,
313
332
} ;
314
333
315
334
Ok ( Some ( ( prefix. to_string ( ) , suffix. to_string ( ) ) ) )
316
335
}
317
336
337
+ /// Helper for creating an error message when parsing rustc output fails.
338
+ fn output_err_info ( cmd : & ProcessBuilder , stdout : & str , stderr : & str ) -> String {
339
+ let mut result = format ! ( "command was: {}\n " , cmd) ;
340
+ if !stdout. is_empty ( ) {
341
+ result. push_str ( "\n --- stdout\n " ) ;
342
+ result. push_str ( stdout) ;
343
+ }
344
+ if !stderr. is_empty ( ) {
345
+ result. push_str ( "\n --- stderr\n " ) ;
346
+ result. push_str ( stderr) ;
347
+ }
348
+ if stdout. is_empty ( ) && stderr. is_empty ( ) {
349
+ result. push_str ( "(no output received)" ) ;
350
+ }
351
+ result
352
+ }
353
+
318
354
/// Acquire extra flags to pass to the compiler from various locations.
319
355
///
320
356
/// The locations are:
0 commit comments