@@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library;
1111use rustc_metadata:: fs:: { emit_wrapper_file, METADATA_FILENAME } ;
1212use rustc_middle:: middle:: dependency_format:: Linkage ;
1313use rustc_middle:: middle:: exported_symbols:: SymbolExportKind ;
14- use rustc_session:: config:: { self , CFGuard , CrateType , DebugInfo , LdImpl , Lto , Strip } ;
14+ use rustc_session:: config:: { self , CFGuard , CrateType , DebugInfo , LdImpl , Strip } ;
1515use rustc_session:: config:: { OutputFilenames , OutputType , PrintRequest , SplitDwarfKind } ;
1616use rustc_session:: cstore:: DllImport ;
1717use rustc_session:: output:: { check_file_is_writeable, invalid_output_for_target, out_filename} ;
@@ -208,16 +208,16 @@ pub fn link_binary<'a>(
208208 Ok ( ( ) )
209209}
210210
211+ // Crate type is not passed when calculating the dylibs to include for LTO. In that case all
212+ // crate types must use the same dependency formats.
211213pub fn each_linked_rlib (
212- sess : & Session ,
213214 info : & CrateInfo ,
215+ crate_type : Option < CrateType > ,
214216 f : & mut dyn FnMut ( CrateNum , & Path ) ,
215217) -> Result < ( ) , errors:: LinkRlibError > {
216218 let crates = info. used_crates . iter ( ) ;
217- let mut fmts = None ;
218219
219- let lto_active = matches ! ( sess. lto( ) , Lto :: Fat | Lto :: Thin ) ;
220- if lto_active {
220+ let fmts = if crate_type. is_none ( ) {
221221 for combination in info. dependency_formats . iter ( ) . combinations ( 2 ) {
222222 let ( ty1, list1) = & combination[ 0 ] ;
223223 let ( ty2, list2) = & combination[ 1 ] ;
@@ -230,27 +230,20 @@ pub fn each_linked_rlib(
230230 } ) ;
231231 }
232232 }
233- }
233+ & info. dependency_formats [ 0 ] . 1
234+ } else {
235+ let fmts = info
236+ . dependency_formats
237+ . iter ( )
238+ . find_map ( |& ( ty, ref list) | if Some ( ty) == crate_type { Some ( list) } else { None } ) ;
234239
235- for ( ty, list) in info. dependency_formats . iter ( ) {
236- match ty {
237- CrateType :: Executable
238- | CrateType :: Staticlib
239- | CrateType :: Cdylib
240- | CrateType :: ProcMacro => {
241- fmts = Some ( list) ;
242- break ;
243- }
244- CrateType :: Dylib if lto_active => {
245- fmts = Some ( list) ;
246- break ;
247- }
248- _ => { }
249- }
250- }
251- let Some ( fmts) = fmts else {
252- return Err ( errors:: LinkRlibError :: MissingFormat ) ;
240+ let Some ( fmts) = fmts else {
241+ return Err ( errors:: LinkRlibError :: MissingFormat ) ;
242+ } ;
243+
244+ fmts
253245 } ;
246+
254247 for & cnum in crates {
255248 match fmts. get ( cnum. as_usize ( ) - 1 ) {
256249 Some ( & Linkage :: NotLinked | & Linkage :: Dynamic | & Linkage :: IncludedFromDylib ) => continue ,
@@ -516,64 +509,71 @@ fn link_staticlib<'a>(
516509 ) ?;
517510 let mut all_native_libs = vec ! [ ] ;
518511
519- let res = each_linked_rlib ( sess, & codegen_results. crate_info , & mut |cnum, path| {
520- let name = codegen_results. crate_info . crate_name [ & cnum] ;
521- let native_libs = & codegen_results. crate_info . native_libraries [ & cnum] ;
522-
523- // Here when we include the rlib into our staticlib we need to make a
524- // decision whether to include the extra object files along the way.
525- // These extra object files come from statically included native
526- // libraries, but they may be cfg'd away with #[link(cfg(..))].
527- //
528- // This unstable feature, though, only needs liblibc to work. The only
529- // use case there is where musl is statically included in liblibc.rlib,
530- // so if we don't want the included version we just need to skip it. As
531- // a result the logic here is that if *any* linked library is cfg'd away
532- // we just skip all object files.
533- //
534- // Clearly this is not sufficient for a general purpose feature, and
535- // we'd want to read from the library's metadata to determine which
536- // object files come from where and selectively skip them.
537- let skip_object_files = native_libs. iter ( ) . any ( |lib| {
538- matches ! ( lib. kind, NativeLibKind :: Static { bundle: None | Some ( true ) , .. } )
539- && !relevant_lib ( sess, lib)
540- } ) ;
512+ let res = each_linked_rlib (
513+ & codegen_results. crate_info ,
514+ Some ( CrateType :: Staticlib ) ,
515+ & mut |cnum, path| {
516+ let name = codegen_results. crate_info . crate_name [ & cnum] ;
517+ let native_libs = & codegen_results. crate_info . native_libraries [ & cnum] ;
518+
519+ // Here when we include the rlib into our staticlib we need to make a
520+ // decision whether to include the extra object files along the way.
521+ // These extra object files come from statically included native
522+ // libraries, but they may be cfg'd away with #[link(cfg(..))].
523+ //
524+ // This unstable feature, though, only needs liblibc to work. The only
525+ // use case there is where musl is statically included in liblibc.rlib,
526+ // so if we don't want the included version we just need to skip it. As
527+ // a result the logic here is that if *any* linked library is cfg'd away
528+ // we just skip all object files.
529+ //
530+ // Clearly this is not sufficient for a general purpose feature, and
531+ // we'd want to read from the library's metadata to determine which
532+ // object files come from where and selectively skip them.
533+ let skip_object_files = native_libs. iter ( ) . any ( |lib| {
534+ matches ! ( lib. kind, NativeLibKind :: Static { bundle: None | Some ( true ) , .. } )
535+ && !relevant_lib ( sess, lib)
536+ } ) ;
541537
542- let lto = are_upstream_rust_objects_already_included ( sess)
543- && !ignored_for_lto ( sess, & codegen_results. crate_info , cnum) ;
538+ let lto = are_upstream_rust_objects_already_included ( sess)
539+ && !ignored_for_lto ( sess, & codegen_results. crate_info , cnum) ;
544540
545- // Ignoring obj file starting with the crate name
546- // as simple comparison is not enough - there
547- // might be also an extra name suffix
548- let obj_start = name. as_str ( ) . to_owned ( ) ;
541+ // Ignoring obj file starting with the crate name
542+ // as simple comparison is not enough - there
543+ // might be also an extra name suffix
544+ let obj_start = name. as_str ( ) . to_owned ( ) ;
549545
550- ab. add_archive (
551- path,
552- Box :: new ( move |fname : & str | {
553- // Ignore metadata files, no matter the name.
554- if fname == METADATA_FILENAME {
555- return true ;
556- }
546+ ab. add_archive (
547+ path,
548+ Box :: new ( move |fname : & str | {
549+ // Ignore metadata files, no matter the name.
550+ if fname == METADATA_FILENAME {
551+ return true ;
552+ }
557553
558- // Don't include Rust objects if LTO is enabled
559- if lto && looks_like_rust_object_file ( fname) {
560- return true ;
561- }
554+ // Don't include Rust objects if LTO is enabled
555+ if lto && looks_like_rust_object_file ( fname) {
556+ return true ;
557+ }
562558
563- // Otherwise if this is *not* a rust object and we're skipping
564- // objects then skip this file
565- if skip_object_files && ( !fname. starts_with ( & obj_start) || !fname. ends_with ( ".o" ) ) {
566- return true ;
567- }
559+ // Otherwise if this is *not* a rust object and we're skipping
560+ // objects then skip this file
561+ if skip_object_files
562+ && ( !fname. starts_with ( & obj_start) || !fname. ends_with ( ".o" ) )
563+ {
564+ return true ;
565+ }
568566
569- // ok, don't skip this
570- false
571- } ) ,
572- )
573- . unwrap ( ) ;
567+ // ok, don't skip this
568+ false
569+ } ) ,
570+ )
571+ . unwrap ( ) ;
574572
575- all_native_libs. extend ( codegen_results. crate_info . native_libraries [ & cnum] . iter ( ) . cloned ( ) ) ;
576- } ) ;
573+ all_native_libs
574+ . extend ( codegen_results. crate_info . native_libraries [ & cnum] . iter ( ) . cloned ( ) ) ;
575+ } ,
576+ ) ;
577577 if let Err ( e) = res {
578578 sess. emit_fatal ( e) ;
579579 }
0 commit comments