@@ -58,12 +58,9 @@ use super::command::Command;
5858use super :: linker:: { self , Linker } ;
5959use super :: metadata:: { MetadataPosition , create_wrapper_file} ;
6060use super :: rpath:: { self , RPathConfig } ;
61- use super :: { apple, versioned_llvm_target} ;
61+ use super :: { apple, rmeta_link , versioned_llvm_target} ;
6262use crate :: base:: needs_allocator_shim_for_linking;
63- use crate :: {
64- CodegenLintLevels , CompiledModule , CompiledModules , CrateInfo , NativeLib , errors,
65- looks_like_rust_object_file,
66- } ;
63+ use crate :: { CodegenLintLevels , CompiledModule , CompiledModules , CrateInfo , NativeLib , errors} ;
6764
6865pub fn ensure_removed ( dcx : DiagCtxtHandle < ' _ > , path : & Path ) {
6966 if let Err ( e) = fs:: remove_file ( path) {
@@ -307,6 +304,27 @@ fn link_rlib<'a>(
307304) -> Box < dyn ArchiveBuilder + ' a > {
308305 let mut ab = archive_builder_builder. new_archive_builder ( sess) ;
309306
307+ // Pre-compute the list of Rust object filenames and materialize the rmeta-link
308+ // wrapper file before any `add_file` calls. This lets the rmeta-link member be
309+ // placed immediately after metadata in the archive, so consumers can find
310+ // it without iterating every archive member.
311+ let rust_object_files: Vec < String > = compiled_modules
312+ . modules
313+ . iter ( )
314+ . filter_map ( |m| m. object . as_ref ( ) )
315+ . map ( |obj| obj. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_string ( ) )
316+ . collect ( ) ;
317+
318+ let metadata_link_file = if matches ! ( flavor, RlibFlavor :: Normal ) {
319+ let metadata_link = rmeta_link:: RmetaLink { rust_object_files } ;
320+ let metadata_link_data = metadata_link. encode ( ) ;
321+ let ( wrapper, _) =
322+ create_wrapper_file ( sess, rmeta_link:: SECTION . to_string ( ) , & metadata_link_data) ;
323+ Some ( emit_wrapper_file ( sess, & wrapper, tmpdir. as_ref ( ) , rmeta_link:: FILENAME ) )
324+ } else {
325+ None
326+ } ;
327+
310328 let trailing_metadata = match flavor {
311329 RlibFlavor :: Normal => {
312330 let ( metadata, metadata_position) =
@@ -320,6 +338,11 @@ fn link_rlib<'a>(
320338 // If it is possible however, placing the metadata object first improves
321339 // performance of getting metadata from rlibs.
322340 ab. add_file ( & metadata) ;
341+ // Place the rmeta-link member immediately after metadata so consumers
342+ // can find it without iterating the whole archive.
343+ if let Some ( file) = & metadata_link_file {
344+ ab. add_file ( file) ;
345+ }
323346 None
324347 }
325348 MetadataPosition :: Last => Some ( metadata) ,
@@ -383,7 +406,7 @@ fn link_rlib<'a>(
383406 packed_bundled_libs. push ( wrapper_file) ;
384407 } else {
385408 let path = find_native_static_library ( lib. name . as_str ( ) , lib. verbatim , sess) ;
386- ab. add_archive ( & path, Box :: new ( |_| false ) ) . unwrap_or_else ( |error| {
409+ ab. add_archive ( & path, None ) . unwrap_or_else ( |error| {
387410 sess. dcx ( ) . emit_fatal ( errors:: AddNativeLibrary { library_path : path, error } )
388411 } ) ;
389412 }
@@ -400,7 +423,7 @@ fn link_rlib<'a>(
400423 tmpdir. as_ref ( ) ,
401424 true ,
402425 ) {
403- ab. add_archive ( & output_path, Box :: new ( |_| false ) ) . unwrap_or_else ( |error| {
426+ ab. add_archive ( & output_path, None ) . unwrap_or_else ( |error| {
404427 sess. dcx ( )
405428 . emit_fatal ( errors:: AddNativeLibrary { library_path : output_path, error } ) ;
406429 } ) ;
@@ -434,6 +457,11 @@ fn link_rlib<'a>(
434457 // Basically, all this means is that this code should not move above the
435458 // code above.
436459 ab. add_file ( & trailing_metadata) ;
460+ // Place the rmeta-link member immediately after metadata so consumers can
461+ // find it without iterating the whole archive.
462+ if let Some ( file) = & metadata_link_file {
463+ ab. add_file ( file) ;
464+ }
437465 }
438466
439467 // Add all bundled static native library dependencies.
@@ -488,14 +516,16 @@ fn link_staticlib(
488516 let bundled_libs: FxIndexSet < _ > = native_libs. filter_map ( |lib| lib. filename ) . collect ( ) ;
489517 ab. add_archive (
490518 path,
491- Box :: new ( move |fname : & str | {
492- // Ignore metadata files, no matter the name .
493- if fname == METADATA_FILENAME {
519+ Some ( Box :: new ( move |fname : & str , metadata_link | {
520+ // Ignore metadata and rmeta-link files .
521+ if fname == METADATA_FILENAME || fname == rmeta_link :: FILENAME {
494522 return true ;
495523 }
496524
497- // Don't include Rust objects if LTO is enabled
498- if lto && looks_like_rust_object_file ( fname) {
525+ // Don't include Rust objects if LTO is enabled.
526+ if lto
527+ && metadata_link. is_some_and ( |m| m. rust_object_files . iter ( ) . any ( |f| f == fname) )
528+ {
499529 return true ;
500530 }
501531
@@ -505,7 +535,7 @@ fn link_staticlib(
505535 }
506536
507537 false
508- } ) ,
538+ } ) ) ,
509539 )
510540 . unwrap ( ) ;
511541
@@ -516,7 +546,7 @@ fn link_staticlib(
516546 for filename in relevant_libs. iter ( ) {
517547 let joined = tempdir. as_ref ( ) . join ( filename. as_str ( ) ) ;
518548 let path = joined. as_path ( ) ;
519- ab. add_archive ( path, Box :: new ( |_| false ) ) . unwrap ( ) ;
549+ ab. add_archive ( path, None ) . unwrap ( ) ;
520550 }
521551
522552 all_native_libs. extend ( crate_info. native_libraries [ & cnum] . iter ( ) . cloned ( ) ) ;
@@ -3167,23 +3197,20 @@ fn add_static_crate(
31673197 let bundled_lib_file_names = bundled_lib_file_names. clone ( ) ;
31683198
31693199 sess. prof . generic_activity_with_arg ( "link_altering_rlib" , name) . run ( || {
3170- let canonical_name = name. replace ( '-' , "_" ) ;
31713200 let upstream_rust_objects_already_included =
31723201 are_upstream_rust_objects_already_included ( sess) ;
31733202 let is_builtins = sess. target . no_builtins || !crate_info. is_no_builtins . contains ( & cnum) ;
31743203
31753204 let mut archive = archive_builder_builder. new_archive_builder ( sess) ;
31763205 if let Err ( error) = archive. add_archive (
31773206 cratepath,
3178- Box :: new ( move |f| {
3179- if f == METADATA_FILENAME {
3207+ Some ( Box :: new ( move |f, metadata_link | {
3208+ if f == METADATA_FILENAME || f == rmeta_link :: FILENAME {
31803209 return true ;
31813210 }
31823211
3183- let canonical = f. replace ( '-' , "_" ) ;
3184-
31853212 let is_rust_object =
3186- canonical . starts_with ( & canonical_name ) && looks_like_rust_object_file ( f ) ;
3213+ metadata_link . is_some_and ( |m| m . rust_object_files . iter ( ) . any ( |rf| rf == f ) ) ;
31873214
31883215 // If we're performing LTO and this is a rust-generated object
31893216 // file, then we don't need the object file as it's part of the
@@ -3203,7 +3230,7 @@ fn add_static_crate(
32033230 }
32043231
32053232 false
3206- } ) ,
3233+ } ) ) ,
32073234 ) {
32083235 sess. dcx ( )
32093236 . emit_fatal ( errors:: RlibArchiveBuildFailure { path : cratepath. clone ( ) , error } ) ;
0 commit comments