@@ -12,6 +12,7 @@ use crate::core::compiler::{
1212} ;
1313use crate :: core:: { Dependency , Package , Target , TargetKind , Workspace } ;
1414use crate :: util:: config:: { Config , StringList , TargetConfig } ;
15+ use crate :: util:: interning:: InternedString ;
1516use crate :: util:: { CargoResult , Rustc } ;
1617use anyhow:: Context as _;
1718use cargo_platform:: { Cfg , CfgExpr } ;
@@ -43,6 +44,8 @@ pub struct TargetInfo {
4344 crate_types : RefCell < HashMap < CrateType , Option < ( String , String ) > > > ,
4445 /// `cfg` information extracted from `rustc --print=cfg`.
4546 cfg : Vec < Cfg > ,
47+ /// Supported values for `-Csplit-debuginfo=` flag, queried from rustc
48+ support_split_debuginfo : Vec < String > ,
4649 /// Path to the sysroot.
4750 pub sysroot : PathBuf ,
4851 /// Path to the "lib" or "bin" directory that rustc uses for its dynamic
@@ -55,8 +58,6 @@ pub struct TargetInfo {
5558 pub rustflags : Vec < String > ,
5659 /// Extra flags to pass to `rustdoc`, see [`extra_args`].
5760 pub rustdocflags : Vec < String > ,
58- /// Whether or not rustc supports the `-Csplit-debuginfo` flag.
59- pub supports_split_debuginfo : bool ,
6061}
6162
6263/// Kind of each file generated by a Unit, part of `FileType`.
@@ -170,7 +171,8 @@ impl TargetInfo {
170171 // Query rustc for several kinds of info from each line of output:
171172 // 0) file-names (to determine output file prefix/suffix for given crate type)
172173 // 1) sysroot
173- // 2) cfg
174+ // 2) split-debuginfo
175+ // 3) cfg
174176 //
175177 // Search `--print` to see what we query so far.
176178 let mut process = rustc. workspace_process ( ) ;
@@ -199,15 +201,9 @@ impl TargetInfo {
199201 process. arg ( "--crate-type" ) . arg ( crate_type. as_str ( ) ) ;
200202 }
201203
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-
210204 process. arg ( "--print=sysroot" ) ;
205+ process. arg ( "--print=split-debuginfo" ) ;
206+ process. arg ( "--print=crate-name" ) ; // `___` as a delimiter.
211207 process. arg ( "--print=cfg" ) ;
212208
213209 let ( output, error) = rustc
@@ -223,13 +219,8 @@ impl TargetInfo {
223219 map. insert ( crate_type. clone ( ) , out) ;
224220 }
225221
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) ;
233224 } ;
234225 let sysroot = PathBuf :: from ( line) ;
235226 let sysroot_host_libdir = if cfg ! ( windows) {
@@ -246,6 +237,26 @@ impl TargetInfo {
246237 } ) ;
247238 sysroot_target_libdir. push ( "lib" ) ;
248239
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+
249260 let cfg = lines
250261 . map ( |line| Ok ( Cfg :: from_str ( line) ?) )
251262 . filter ( TargetInfo :: not_user_specific_cfg)
@@ -303,7 +314,7 @@ impl TargetInfo {
303314 Flags :: Rustdoc ,
304315 ) ?,
305316 cfg,
306- supports_split_debuginfo ,
317+ support_split_debuginfo ,
307318 } ) ;
308319 }
309320 }
@@ -543,6 +554,13 @@ impl TargetInfo {
543554 }
544555 Ok ( ( result, unsupported) )
545556 }
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+ }
546564}
547565
548566/// Takes rustc output (using specialized command line args), and calculates the file prefix and
@@ -578,17 +596,27 @@ fn parse_crate_type(
578596 } ;
579597 let mut parts = line. trim ( ) . split ( "___" ) ;
580598 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) ;
587601 } ;
588602
589603 Ok ( Some ( ( prefix. to_string ( ) , suffix. to_string ( ) ) ) )
590604}
591605
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+
592620/// Helper for creating an error message when parsing rustc output fails.
593621fn output_err_info ( cmd : & ProcessBuilder , stdout : & str , stderr : & str ) -> String {
594622 let mut result = format ! ( "command was: {}\n " , cmd) ;
0 commit comments