@@ -23,7 +23,7 @@ use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Ta
2323use super :: archive:: { find_library, ArchiveBuilder } ;
2424use super :: command:: Command ;
2525use super :: linker:: { self , Linker } ;
26- use super :: metadata:: create_rmeta_file;
26+ use super :: metadata:: { create_rmeta_file, MetadataPosition } ;
2727use super :: rpath:: { self , RPathConfig } ;
2828use crate :: {
2929 looks_like_rust_object_file, CodegenResults , CompiledModule , CrateInfo , NativeLib ,
@@ -267,6 +267,28 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
267267
268268 let mut ab = <B as ArchiveBuilder >:: new ( sess, out_filename, None ) ;
269269
270+ let trailing_metadata = match flavor {
271+ RlibFlavor :: Normal => {
272+ let ( metadata, metadata_position) =
273+ create_rmeta_file ( sess, codegen_results. metadata . raw_data ( ) ) ;
274+ let metadata = emit_metadata ( sess, & metadata, tmpdir) ;
275+ match metadata_position {
276+ MetadataPosition :: First => {
277+ // Most of the time metadata in rlib files is wrapped in a "dummy" object
278+ // file for the target platform so the rlib can be processed entirely by
279+ // normal linkers for the platform. Sometimes this is not possible however.
280+ // If it is possible however, placing the metadata object first improves
281+ // performance of getting metadata from rlibs.
282+ ab. add_file ( & metadata) ;
283+ None
284+ }
285+ MetadataPosition :: Last => Some ( metadata) ,
286+ }
287+ }
288+
289+ RlibFlavor :: StaticlibBase => None ,
290+ } ;
291+
270292 for m in & codegen_results. modules {
271293 if let Some ( obj) = m. object . as_ref ( ) {
272294 ab. add_file ( obj) ;
@@ -277,6 +299,16 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
277299 }
278300 }
279301
302+ match flavor {
303+ RlibFlavor :: Normal => { }
304+ RlibFlavor :: StaticlibBase => {
305+ let obj = codegen_results. allocator_module . as_ref ( ) . and_then ( |m| m. object . as_ref ( ) ) ;
306+ if let Some ( obj) = obj {
307+ ab. add_file ( obj) ;
308+ }
309+ }
310+ }
311+
280312 // Note that in this loop we are ignoring the value of `lib.cfg`. That is,
281313 // we may not be configured to actually include a static library if we're
282314 // adding it here. That's because later when we consume this rlib we'll
@@ -334,42 +366,33 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
334366 ab. inject_dll_import_lib ( & raw_dylib_name, & raw_dylib_imports, tmpdir) ;
335367 }
336368
337- // Note that it is important that we add all of our non-object "magical
338- // files" *after* all of the object files in the archive. The reason for
339- // this is as follows:
340- //
341- // * When performing LTO, this archive will be modified to remove
342- // objects from above. The reason for this is described below.
343- //
344- // * When the system linker looks at an archive, it will attempt to
345- // determine the architecture of the archive in order to see whether its
346- // linkable.
347- //
348- // The algorithm for this detection is: iterate over the files in the
349- // archive. Skip magical SYMDEF names. Interpret the first file as an
350- // object file. Read architecture from the object file.
351- //
352- // * As one can probably see, if "metadata" and "foo.bc" were placed
353- // before all of the objects, then the architecture of this archive would
354- // not be correctly inferred once 'foo.o' is removed.
355- //
356- // Basically, all this means is that this code should not move above the
357- // code above.
358- match flavor {
359- RlibFlavor :: Normal => {
360- // metadata in rlib files is wrapped in a "dummy" object file for
361- // the target platform so the rlib can be processed entirely by
362- // normal linkers for the platform.
363- let metadata = create_rmeta_file ( sess, codegen_results. metadata . raw_data ( ) ) ;
364- ab. add_file ( & emit_metadata ( sess, & metadata, tmpdir) ) ;
365- }
366-
367- RlibFlavor :: StaticlibBase => {
368- let obj = codegen_results. allocator_module . as_ref ( ) . and_then ( |m| m. object . as_ref ( ) ) ;
369- if let Some ( obj) = obj {
370- ab. add_file ( obj) ;
371- }
372- }
369+ if let Some ( trailing_metadata) = trailing_metadata {
370+ // Note that it is important that we add all of our non-object "magical
371+ // files" *after* all of the object files in the archive. The reason for
372+ // this is as follows:
373+ //
374+ // * When performing LTO, this archive will be modified to remove
375+ // objects from above. The reason for this is described below.
376+ //
377+ // * When the system linker looks at an archive, it will attempt to
378+ // determine the architecture of the archive in order to see whether its
379+ // linkable.
380+ //
381+ // The algorithm for this detection is: iterate over the files in the
382+ // archive. Skip magical SYMDEF names. Interpret the first file as an
383+ // object file. Read architecture from the object file.
384+ //
385+ // * As one can probably see, if "metadata" and "foo.bc" were placed
386+ // before all of the objects, then the architecture of this archive would
387+ // not be correctly inferred once 'foo.o' is removed.
388+ //
389+ // * Most of the time metadata in rlib files is wrapped in a "dummy" object
390+ // file for the target platform so the rlib can be processed entirely by
391+ // normal linkers for the platform. Sometimes this is not possible however.
392+ //
393+ // Basically, all this means is that this code should not move above the
394+ // code above.
395+ ab. add_file ( & trailing_metadata) ;
373396 }
374397
375398 return Ok ( ab) ;
0 commit comments