@@ -23,7 +23,7 @@ use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Ta
23
23
use super :: archive:: { find_library, ArchiveBuilder } ;
24
24
use super :: command:: Command ;
25
25
use super :: linker:: { self , Linker } ;
26
- use super :: metadata:: create_rmeta_file;
26
+ use super :: metadata:: { create_rmeta_file, MetadataPosition } ;
27
27
use super :: rpath:: { self , RPathConfig } ;
28
28
use crate :: {
29
29
looks_like_rust_object_file, CodegenResults , CompiledModule , CrateInfo , NativeLib ,
@@ -267,6 +267,28 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
267
267
268
268
let mut ab = <B as ArchiveBuilder >:: new ( sess, out_filename, None ) ;
269
269
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
+
270
292
for m in & codegen_results. modules {
271
293
if let Some ( obj) = m. object . as_ref ( ) {
272
294
ab. add_file ( obj) ;
@@ -277,6 +299,16 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
277
299
}
278
300
}
279
301
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
+
280
312
// Note that in this loop we are ignoring the value of `lib.cfg`. That is,
281
313
// we may not be configured to actually include a static library if we're
282
314
// 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>>(
334
366
ab. inject_dll_import_lib ( & raw_dylib_name, & raw_dylib_imports, tmpdir) ;
335
367
}
336
368
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) ;
373
396
}
374
397
375
398
return Ok ( ab) ;
0 commit comments