@@ -270,10 +270,9 @@ pub fn each_linked_rlib(
270270
271271/// Create an 'rlib'.
272272///
273- /// An rlib in its current incarnation is essentially a renamed .a file. The rlib primarily contains
274- /// the object file of the crate, but it also contains all of the object files from native
275- /// libraries. This is done by unzipping native libraries and inserting all of the contents into
276- /// this archive.
273+ /// An rlib in its current incarnation is essentially a renamed .a file (with "dummy" object files).
274+ /// The rlib primarily contains the object file of the crate, but it also some of the object files
275+ /// from native libraries.
277276fn link_rlib < ' a > (
278277 sess : & ' a Session ,
279278 archive_builder_builder : & dyn ArchiveBuilderBuilder ,
@@ -347,44 +346,23 @@ fn link_rlib<'a>(
347346 // loaded from the libraries found here and then encode that into the
348347 // metadata of the rlib we're generating somehow.
349348 for lib in codegen_results. crate_info . used_libraries . iter ( ) {
350- match lib. kind {
351- NativeLibKind :: Static { bundle : None | Some ( true ) , whole_archive : Some ( true ) }
352- if flavor == RlibFlavor :: Normal && sess. opts . unstable_opts . packed_bundled_libs => { }
353- NativeLibKind :: Static { bundle : None | Some ( true ) , whole_archive : Some ( true ) }
354- if flavor == RlibFlavor :: Normal =>
355- {
356- // Don't allow mixing +bundle with +whole_archive since an rlib may contain
357- // multiple native libs, some of which are +whole-archive and some of which are
358- // -whole-archive and it isn't clear how we can currently handle such a
359- // situation correctly.
360- // See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897
361- sess. emit_err ( errors:: IncompatibleLinkingModifiers ) ;
362- }
363- NativeLibKind :: Static { bundle : None | Some ( true ) , .. } => { }
364- NativeLibKind :: Static { bundle : Some ( false ) , .. }
365- | NativeLibKind :: Dylib { .. }
366- | NativeLibKind :: Framework { .. }
367- | NativeLibKind :: RawDylib
368- | NativeLibKind :: LinkArg
369- | NativeLibKind :: Unspecified => continue ,
370- }
371- if let Some ( name) = lib. name {
372- let location =
349+ let NativeLibKind :: Static { bundle : None | Some ( true ) , whole_archive } = lib. kind else {
350+ continue ;
351+ } ;
352+ if whole_archive == Some ( true ) && !codegen_results. crate_info . feature_packed_bundled_libs {
353+ sess. emit_err ( errors:: IncompatibleLinkingModifiers ) ;
354+ }
355+ if flavor == RlibFlavor :: Normal && let Some ( filename) = lib. filename {
356+ let path = find_native_static_library ( filename. as_str ( ) , true , & lib_search_paths, sess) ;
357+ let src = read ( path) . map_err ( |e| sess. emit_fatal ( errors:: ReadFileError { message : e } ) ) ?;
358+ let ( data, _) = create_wrapper_file ( sess, b".bundled_lib" . to_vec ( ) , & src) ;
359+ let wrapper_file = emit_wrapper_file ( sess, & data, tmpdir, filename. as_str ( ) ) ;
360+ packed_bundled_libs. push ( wrapper_file) ;
361+ } else if let Some ( name) = lib. name {
362+ let path =
373363 find_native_static_library ( name. as_str ( ) , lib. verbatim , & lib_search_paths, sess) ;
374- if sess. opts . unstable_opts . packed_bundled_libs && flavor == RlibFlavor :: Normal {
375- let filename = lib. filename . unwrap ( ) ;
376- let lib_path =
377- find_native_static_library ( filename. as_str ( ) , true , & lib_search_paths, sess) ;
378- let src = read ( lib_path)
379- . map_err ( |e| sess. emit_fatal ( errors:: ReadFileError { message : e } ) ) ?;
380- let ( data, _) = create_wrapper_file ( sess, b".bundled_lib" . to_vec ( ) , & src) ;
381- let wrapper_file = emit_wrapper_file ( sess, & data, tmpdir, filename. as_str ( ) ) ;
382- packed_bundled_libs. push ( wrapper_file) ;
383- continue ;
384- }
385- ab. add_archive ( & location, Box :: new ( |_| false ) ) . unwrap_or_else ( |error| {
386- sess. emit_fatal ( errors:: AddNativeLibrary { library_path : location, error } ) ;
387- } ) ;
364+ ab. add_archive ( & path, Box :: new ( |_| false ) ) . unwrap_or_else ( |error| {
365+ sess. emit_fatal ( errors:: AddNativeLibrary { library_path : path, error } ) } ) ;
388366 }
389367 }
390368
@@ -516,36 +494,14 @@ fn link_staticlib<'a>(
516494 & codegen_results. crate_info ,
517495 Some ( CrateType :: Staticlib ) ,
518496 & mut |cnum, path| {
519- let name = codegen_results. crate_info . crate_name [ & cnum] ;
520- let native_libs = & codegen_results. crate_info . native_libraries [ & cnum] ;
521-
522- // Here when we include the rlib into our staticlib we need to make a
523- // decision whether to include the extra object files along the way.
524- // These extra object files come from statically included native
525- // libraries, but they may be cfg'd away with #[link(cfg(..))].
526- //
527- // This unstable feature, though, only needs liblibc to work. The only
528- // use case there is where musl is statically included in liblibc.rlib,
529- // so if we don't want the included version we just need to skip it. As
530- // a result the logic here is that if *any* linked library is cfg'd away
531- // we just skip all object files.
532- //
533- // Clearly this is not sufficient for a general purpose feature, and
534- // we'd want to read from the library's metadata to determine which
535- // object files come from where and selectively skip them.
536- let skip_object_files = native_libs. iter ( ) . any ( |lib| {
537- matches ! ( lib. kind, NativeLibKind :: Static { bundle: None | Some ( true ) , .. } )
538- && !relevant_lib ( sess, lib)
539- } ) ;
540-
541497 let lto = are_upstream_rust_objects_already_included ( sess)
542498 && !ignored_for_lto ( sess, & codegen_results. crate_info , cnum) ;
543499
544- // Ignoring obj file starting with the crate name
545- // as simple comparison is not enough - there
546- // might be also an extra name suffix
547- let obj_start = name. as_str ( ) . to_owned ( ) ;
500+ let native_libs = codegen_results. crate_info . native_libraries [ & cnum] . iter ( ) ;
501+ let relevant = native_libs. clone ( ) . filter ( |lib| relevant_lib ( sess, & lib) ) ;
502+ let relevant_libs: FxHashSet < _ > = relevant. filter_map ( |lib| lib. filename ) . collect ( ) ;
548503
504+ let bundled_libs: FxHashSet < _ > = native_libs. filter_map ( |lib| lib. filename ) . collect ( ) ;
549505 ab. add_archive (
550506 path,
551507 Box :: new ( move |fname : & str | {
@@ -559,20 +515,25 @@ fn link_staticlib<'a>(
559515 return true ;
560516 }
561517
562- // Otherwise if this is *not* a rust object and we're skipping
563- // objects then skip this file
564- if skip_object_files
565- && ( !fname. starts_with ( & obj_start) || !fname. ends_with ( ".o" ) )
566- {
518+ // Skip objects for bundled libs.
519+ if bundled_libs. contains ( & Symbol :: intern ( fname) ) {
567520 return true ;
568521 }
569522
570- // ok, don't skip this
571523 false
572524 } ) ,
573525 )
574526 . unwrap ( ) ;
575527
528+ archive_builder_builder
529+ . extract_bundled_libs ( path, tempdir. as_ref ( ) , & relevant_libs)
530+ . unwrap_or_else ( |e| sess. emit_fatal ( e) ) ;
531+ for filename in relevant_libs {
532+ let joined = tempdir. as_ref ( ) . join ( filename. as_str ( ) ) ;
533+ let path = joined. as_path ( ) ;
534+ ab. add_archive ( path, Box :: new ( |_| false ) ) . unwrap ( ) ;
535+ }
536+
576537 all_native_libs
577538 . extend ( codegen_results. crate_info . native_libraries [ & cnum] . iter ( ) . cloned ( ) ) ;
578539 } ,
@@ -2590,18 +2551,8 @@ fn add_static_crate<'a>(
25902551 cmd. link_rlib ( & fix_windows_verbatim_for_gcc ( path) ) ;
25912552 } ;
25922553
2593- // See the comment above in `link_staticlib` and `link_rlib` for why if
2594- // there's a static library that's not relevant we skip all object
2595- // files.
2596- let native_libs = & codegen_results. crate_info . native_libraries [ & cnum] ;
2597- let skip_native = native_libs. iter ( ) . any ( |lib| {
2598- matches ! ( lib. kind, NativeLibKind :: Static { bundle: None | Some ( true ) , .. } )
2599- && !relevant_lib ( sess, lib)
2600- } ) ;
2601-
2602- if ( !are_upstream_rust_objects_already_included ( sess)
2603- || ignored_for_lto ( sess, & codegen_results. crate_info , cnum) )
2604- && !skip_native
2554+ if !are_upstream_rust_objects_already_included ( sess)
2555+ || ignored_for_lto ( sess, & codegen_results. crate_info , cnum)
26052556 {
26062557 link_upstream ( cratepath) ;
26072558 return ;
@@ -2632,17 +2583,13 @@ fn add_static_crate<'a>(
26322583 let is_rust_object =
26332584 canonical. starts_with ( & canonical_name) && looks_like_rust_object_file ( & f) ;
26342585
2635- // If we've been requested to skip all native object files
2636- // (those not generated by the rust compiler) then we can skip
2637- // this file. See above for why we may want to do this.
2638- let skip_because_cfg_say_so = skip_native && !is_rust_object;
2639-
26402586 // If we're performing LTO and this is a rust-generated object
26412587 // file, then we don't need the object file as it's part of the
26422588 // LTO module. Note that `#![no_builtins]` is excluded from LTO,
26432589 // though, so we let that object file slide.
2644- let skip_because_lto =
2645- upstream_rust_objects_already_included && is_rust_object && is_builtins;
2590+ if upstream_rust_objects_already_included && is_rust_object && is_builtins {
2591+ return true ;
2592+ }
26462593
26472594 // We skip native libraries because:
26482595 // 1. This native libraries won't be used from the generated rlib,
@@ -2653,10 +2600,6 @@ fn add_static_crate<'a>(
26532600 return true ;
26542601 }
26552602
2656- if skip_because_cfg_say_so || skip_because_lto {
2657- return true ;
2658- }
2659-
26602603 false
26612604 } ) ,
26622605 ) {
0 commit comments