@@ -9,17 +9,34 @@ use crate::core::TargetKind;
99use crate :: util:: CfgExpr ;
1010use crate :: util:: { CargoResult , CargoResultExt , Cfg , Config , ProcessBuilder , Rustc } ;
1111
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.
1216#[ derive( Clone ) ]
1317pub 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.
1528 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`.
1834 pub rustflags : Vec < String > ,
35+ /// Extra flags to pass to `rustdoc`, see `env_args`.
1936 pub rustdocflags : Vec < String > ,
2037}
2138
22- /// Type of each file generated by a Unit.
39+ /// Kind of each file generated by a Unit, part of `FileType` .
2340#[ derive( Clone , PartialEq , Eq , Debug ) ]
2441pub enum FileFlavor {
2542 /// Not a special file type.
@@ -30,9 +47,13 @@ pub enum FileFlavor {
3047 DebugInfo ,
3148}
3249
50+ /// Type of each file generated by a Unit.
3351pub struct FileType {
52+ /// The kind of file.
3453 pub flavor : FileFlavor ,
54+ /// The suffix for the file (for example, `.rlib`).
3555 suffix : String ,
56+ /// The prefix for the file (for example, `lib`).
3657 prefix : String ,
3758 // Wasm bin target will generate two files in deps such as
3859 // "web-stuff.js" and "web_stuff.wasm". Note the different usages of
@@ -92,60 +113,51 @@ impl TargetInfo {
92113 process. arg ( "--crate-type" ) . arg ( crate_type) ;
93114 }
94115
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" ) ;
98118
99- let mut has_cfg_and_sysroot = true ;
100119 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)
106121 . chain_err ( || "failed to run `rustc` to learn about target-specific information" ) ?;
107122
108123 let mut lines = output. lines ( ) ;
109124 let mut map = HashMap :: new ( ) ;
110125 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) ?;
112127 map. insert ( crate_type. to_string ( ) , out) ;
113128 }
114129
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 => {
126141 if cfg ! ( windows) {
127142 rustlib. push ( "bin" ) ;
128143 } else {
129144 rustlib. push ( "lib" ) ;
130145 }
131- sysroot_libdir = Some ( rustlib) ;
132- } else {
146+ rustlib
147+ }
148+ Kind :: Target => {
133149 rustlib. push ( "lib" ) ;
134150 rustlib. push ( "rustlib" ) ;
135151 rustlib. push ( target_triple) ;
136152 rustlib. push ( "lib" ) ;
137- sysroot_libdir = Some ( rustlib) ;
153+ rustlib
138154 }
139- }
140-
141- let cfg = if has_cfg_and_sysroot {
142- Some ( lines. map ( Cfg :: from_str) . collect :: < CargoResult < Vec < _ > > > ( ) ?)
143- } else {
144- None
145155 } ;
146156
157+ let cfg = lines. map ( Cfg :: from_str) . collect :: < CargoResult < Vec < _ > > > ( ) ?;
158+
147159 Ok ( TargetInfo {
148- crate_type_process : Some ( crate_type_process ) ,
160+ crate_type_process,
149161 crate_types : RefCell :: new ( map) ,
150162 sysroot_libdir,
151163 // recalculate `rustflags` from above now that we have `cfg`
@@ -154,24 +166,24 @@ impl TargetInfo {
154166 config,
155167 requested_target,
156168 & rustc. host ,
157- cfg . as_ref ( ) . map ( |v| v . as_ref ( ) ) ,
169+ Some ( & cfg ) ,
158170 kind,
159171 "RUSTFLAGS" ,
160172 ) ?,
161173 rustdocflags : env_args (
162174 config,
163175 requested_target,
164176 & rustc. host ,
165- cfg . as_ref ( ) . map ( |v| v . as_ref ( ) ) ,
177+ Some ( & cfg ) ,
166178 kind,
167179 "RUSTDOCFLAGS" ,
168180 ) ?,
169181 cfg,
170182 } )
171183 }
172184
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
175187 }
176188
177189 pub fn file_types (
@@ -255,21 +267,26 @@ impl TargetInfo {
255267 }
256268
257269 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 ( ) ;
259271
260272 process. arg ( "--crate-type" ) . arg ( crate_type) ;
261273
262274 let output = process. exec_with_output ( ) . chain_err ( || {
263275 format ! (
264- "failed to run `rustc` to learn about \
265- crate-type {} information",
276+ "failed to run `rustc` to learn about crate-type {} information" ,
266277 crate_type
267278 )
268279 } ) ?;
269280
270281 let error = str:: from_utf8 ( & output. stderr ) . unwrap ( ) ;
271282 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+ ) ?)
273290 }
274291}
275292
@@ -284,6 +301,8 @@ impl TargetInfo {
284301// are two files for bin (`.wasm` and `.js`)).
285302fn parse_crate_type (
286303 crate_type : & str ,
304+ cmd : & ProcessBuilder ,
305+ output : & str ,
287306 error : & str ,
288307 lines : & mut str:: Lines < ' _ > ,
289308) -> CargoResult < Option < ( String , String ) > > {
@@ -297,24 +316,41 @@ fn parse_crate_type(
297316 let line = match lines. next ( ) {
298317 Some ( line) => line,
299318 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 )
303322 ) ,
304323 } ;
305324 let mut parts = line. trim ( ) . split ( "___" ) ;
306325 let prefix = parts. next ( ) . unwrap ( ) ;
307326 let suffix = match parts. next ( ) {
308327 Some ( part) => part,
309328 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 )
312331 ) ,
313332 } ;
314333
315334 Ok ( Some ( ( prefix. to_string ( ) , suffix. to_string ( ) ) ) )
316335}
317336
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+
318354/// Acquire extra flags to pass to the compiler from various locations.
319355///
320356/// The locations are:
0 commit comments