@@ -12,6 +12,7 @@ use crate::core::compiler::{
12
12
} ;
13
13
use crate :: core:: { Dependency , Package , Target , TargetKind , Workspace } ;
14
14
use crate :: util:: config:: { Config , StringList , TargetConfig } ;
15
+ use crate :: util:: interning:: InternedString ;
15
16
use crate :: util:: { CargoResult , Rustc } ;
16
17
use anyhow:: Context as _;
17
18
use cargo_platform:: { Cfg , CfgExpr } ;
@@ -43,6 +44,8 @@ pub struct TargetInfo {
43
44
crate_types : RefCell < HashMap < CrateType , Option < ( String , String ) > > > ,
44
45
/// `cfg` information extracted from `rustc --print=cfg`.
45
46
cfg : Vec < Cfg > ,
47
+ /// Supported values for `-Csplit-debuginfo=` flag, queried from rustc
48
+ support_split_debuginfo : Vec < String > ,
46
49
/// Path to the sysroot.
47
50
pub sysroot : PathBuf ,
48
51
/// Path to the "lib" or "bin" directory that rustc uses for its dynamic
@@ -55,8 +58,6 @@ pub struct TargetInfo {
55
58
pub rustflags : Vec < String > ,
56
59
/// Extra flags to pass to `rustdoc`, see [`extra_args`].
57
60
pub rustdocflags : Vec < String > ,
58
- /// Whether or not rustc supports the `-Csplit-debuginfo` flag.
59
- pub supports_split_debuginfo : bool ,
60
61
}
61
62
62
63
/// Kind of each file generated by a Unit, part of `FileType`.
@@ -170,7 +171,8 @@ impl TargetInfo {
170
171
// Query rustc for several kinds of info from each line of output:
171
172
// 0) file-names (to determine output file prefix/suffix for given crate type)
172
173
// 1) sysroot
173
- // 2) cfg
174
+ // 2) split-debuginfo
175
+ // 3) cfg
174
176
//
175
177
// Search `--print` to see what we query so far.
176
178
let mut process = rustc. workspace_process ( ) ;
@@ -199,15 +201,9 @@ impl TargetInfo {
199
201
process. arg ( "--crate-type" ) . arg ( crate_type. as_str ( ) ) ;
200
202
}
201
203
202
- // An extra `rustc` call to determine `-Csplit-debuginfo=packed` support.
203
- let supports_split_debuginfo = rustc
204
- . cached_output (
205
- process. clone ( ) . arg ( "-Csplit-debuginfo=packed" ) ,
206
- extra_fingerprint,
207
- )
208
- . is_ok ( ) ;
209
-
210
204
process. arg ( "--print=sysroot" ) ;
205
+ process. arg ( "--print=split-debuginfo" ) ;
206
+ process. arg ( "--print=crate-name" ) ; // `___` as a delimiter.
211
207
process. arg ( "--print=cfg" ) ;
212
208
213
209
let ( output, error) = rustc
@@ -223,13 +219,8 @@ impl TargetInfo {
223
219
map. insert ( crate_type. clone ( ) , out) ;
224
220
}
225
221
226
- let line = match lines. next ( ) {
227
- Some ( line) => line,
228
- None => anyhow:: bail!(
229
- "output of --print=sysroot missing when learning about \
230
- target-specific information from rustc\n {}",
231
- output_err_info( & process, & output, & error)
232
- ) ,
222
+ let Some ( line) = lines. next ( ) else {
223
+ return error_missing_print_output ( "sysroot" , & process, & output, & error) ;
233
224
} ;
234
225
let sysroot = PathBuf :: from ( line) ;
235
226
let sysroot_host_libdir = if cfg ! ( windows) {
@@ -246,6 +237,26 @@ impl TargetInfo {
246
237
} ) ;
247
238
sysroot_target_libdir. push ( "lib" ) ;
248
239
240
+ let support_split_debuginfo = {
241
+ // HACK: abuse `--print=crate-name` to use `___` as a delimiter.
242
+ let mut res = Vec :: new ( ) ;
243
+ loop {
244
+ match lines. next ( ) {
245
+ Some ( line) if line == "___" => break ,
246
+ Some ( line) => res. push ( line. into ( ) ) ,
247
+ None => {
248
+ return error_missing_print_output (
249
+ "split-debuginfo" ,
250
+ & process,
251
+ & output,
252
+ & error,
253
+ )
254
+ }
255
+ }
256
+ }
257
+ res
258
+ } ;
259
+
249
260
let cfg = lines
250
261
. map ( |line| Ok ( Cfg :: from_str ( line) ?) )
251
262
. filter ( TargetInfo :: not_user_specific_cfg)
@@ -303,7 +314,7 @@ impl TargetInfo {
303
314
Flags :: Rustdoc ,
304
315
) ?,
305
316
cfg,
306
- supports_split_debuginfo ,
317
+ support_split_debuginfo ,
307
318
} ) ;
308
319
}
309
320
}
@@ -543,6 +554,13 @@ impl TargetInfo {
543
554
}
544
555
Ok ( ( result, unsupported) )
545
556
}
557
+
558
+ /// Checks if the debuginfo-split value is supported by this target
559
+ pub fn supports_debuginfo_split ( & self , split : InternedString ) -> bool {
560
+ self . support_split_debuginfo
561
+ . iter ( )
562
+ . any ( |sup| sup. as_str ( ) == split. as_str ( ) )
563
+ }
546
564
}
547
565
548
566
/// Takes rustc output (using specialized command line args), and calculates the file prefix and
@@ -578,17 +596,27 @@ fn parse_crate_type(
578
596
} ;
579
597
let mut parts = line. trim ( ) . split ( "___" ) ;
580
598
let prefix = parts. next ( ) . unwrap ( ) ;
581
- let suffix = match parts. next ( ) {
582
- Some ( part) => part,
583
- None => anyhow:: bail!(
584
- "output of --print=file-names has changed in the compiler, cannot parse\n {}" ,
585
- output_err_info( cmd, output, error)
586
- ) ,
599
+ let Some ( suffix) = parts. next ( ) else {
600
+ return error_missing_print_output ( "file-names" , cmd, output, error) ;
587
601
} ;
588
602
589
603
Ok ( Some ( ( prefix. to_string ( ) , suffix. to_string ( ) ) ) )
590
604
}
591
605
606
+ /// Helper for creating an error message for missing output from a certain `--print` request.
607
+ fn error_missing_print_output < T > (
608
+ request : & str ,
609
+ cmd : & ProcessBuilder ,
610
+ stdout : & str ,
611
+ stderr : & str ,
612
+ ) -> CargoResult < T > {
613
+ let err_info = output_err_info ( cmd, stdout, stderr) ;
614
+ anyhow:: bail!(
615
+ "output of --print={request} missing when learning about \
616
+ target-specific information from rustc\n {err_info}",
617
+ )
618
+ }
619
+
592
620
/// Helper for creating an error message when parsing rustc output fails.
593
621
fn output_err_info ( cmd : & ProcessBuilder , stdout : & str , stderr : & str ) -> String {
594
622
let mut result = format ! ( "command was: {}\n " , cmd) ;
0 commit comments