@@ -2,6 +2,7 @@ use crate::codegen_cx::{CodegenArgs, ModuleOutputType};
2
2
use crate :: {
3
3
linker, CompileResult , ModuleResult , SpirvCodegenBackend , SpirvModuleBuffer , SpirvThinBuffer ,
4
4
} ;
5
+ use ar:: { Archive , GnuBuilder , Header } ;
5
6
use rspirv:: binary:: Assemble ;
6
7
use rustc_codegen_ssa:: back:: lto:: { LtoModuleCodegen , SerializedModule , ThinModule , ThinShared } ;
7
8
use rustc_codegen_ssa:: back:: write:: CodegenContext ;
@@ -19,12 +20,12 @@ use rustc_session::output::{check_file_is_writeable, invalid_output_for_target,
19
20
use rustc_session:: utils:: NativeLibKind ;
20
21
use rustc_session:: Session ;
21
22
use std:: env;
22
- use std:: ffi:: { CString , OsStr } ;
23
+ use std:: ffi:: CString ;
23
24
use std:: fs:: File ;
24
25
use std:: io:: { BufWriter , Read } ;
26
+ use std:: iter;
25
27
use std:: path:: { Path , PathBuf } ;
26
28
use std:: sync:: Arc ;
27
- use tar:: { Archive , Builder , Header } ;
28
29
29
30
pub fn link < ' a > (
30
31
sess : & ' a Session ,
@@ -439,35 +440,53 @@ fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
439
440
}
440
441
441
442
fn create_archive ( files : & [ & Path ] , metadata : & [ u8 ] , out_filename : & Path ) {
442
- let file = File :: create ( out_filename) . unwrap ( ) ;
443
- let mut builder = Builder :: new ( file) ;
444
- {
445
- let mut header = Header :: new_gnu ( ) ;
446
- header. set_path ( METADATA_FILENAME ) . unwrap ( ) ;
447
- header. set_size ( metadata. len ( ) as u64 ) ;
448
- header. set_cksum ( ) ;
449
- builder. append ( & header, metadata) . unwrap ( ) ;
450
- }
443
+ let files_with_names = files. iter ( ) . map ( |file| {
444
+ (
445
+ file,
446
+ file. file_name ( )
447
+ . unwrap ( )
448
+ . to_str ( )
449
+ . expect ( "archive file names should be valid ASCII/UTF-8" ) ,
450
+ )
451
+ } ) ;
452
+ let out_file = File :: create ( out_filename) . unwrap ( ) ;
453
+ let mut builder = GnuBuilder :: new (
454
+ out_file,
455
+ iter:: once ( METADATA_FILENAME )
456
+ . chain ( files_with_names. clone ( ) . map ( |( _, name) | name) )
457
+ . map ( |name| name. as_bytes ( ) . to_vec ( ) )
458
+ . collect ( ) ,
459
+ ) ;
460
+ builder
461
+ . append (
462
+ & Header :: new ( METADATA_FILENAME . as_bytes ( ) . to_vec ( ) , metadata. len ( ) as u64 ) ,
463
+ metadata,
464
+ )
465
+ . unwrap ( ) ;
466
+
451
467
let mut filenames = FxHashSet :: default ( ) ;
452
- filenames. insert ( OsStr :: new ( METADATA_FILENAME ) ) ;
453
- for file in files {
468
+ filenames. insert ( METADATA_FILENAME ) ;
469
+ for ( file, name ) in files_with_names {
454
470
assert ! (
455
- filenames. insert( file . file_name ( ) . unwrap ( ) ) ,
471
+ filenames. insert( name ) ,
456
472
"Duplicate filename in archive: {:?}" ,
457
473
file. file_name( ) . unwrap( )
458
474
) ;
475
+ // NOTE(eddyb) this could just be `builder.append_path(file)`, but we
476
+ // have to work around https://github.com/mdsteele/rust-ar/issues/19.
459
477
builder
460
- . append_path_with_name ( file , file . file_name ( ) . unwrap ( ) )
478
+ . append_file ( name . as_bytes ( ) , & mut File :: open ( file ) . unwrap ( ) )
461
479
. unwrap ( ) ;
462
480
}
463
481
builder. into_inner ( ) . unwrap ( ) ;
464
482
}
465
483
466
484
pub fn read_metadata ( rlib : & Path ) -> Result < MetadataRef , String > {
467
485
fn read_metadata_internal ( rlib : & Path ) -> Result < Option < MetadataRef > , std:: io:: Error > {
468
- for entry in Archive :: new ( File :: open ( rlib) ?) . entries ( ) ? {
486
+ let mut archive = Archive :: new ( File :: open ( rlib) . unwrap ( ) ) ;
487
+ while let Some ( entry) = archive. next_entry ( ) {
469
488
let mut entry = entry?;
470
- if entry. path ( ) ? == Path :: new ( METADATA_FILENAME ) {
489
+ if entry. header ( ) . identifier ( ) == METADATA_FILENAME . as_bytes ( ) {
471
490
let mut bytes = Vec :: new ( ) ;
472
491
entry. read_to_end ( & mut bytes) ?;
473
492
let buf: OwningRef < Vec < u8 > , [ u8 ] > = OwningRef :: new ( bytes) ;
@@ -507,12 +526,13 @@ fn do_link(
507
526
// `rlibs` are archive files we've created in `create_archive`, usually produced by crates that are being
508
527
// referenced. We need to unpack them and add the modules inside.
509
528
for rlib in rlibs {
510
- for entry in Archive :: new ( File :: open ( rlib) . unwrap ( ) ) . entries ( ) . unwrap ( ) {
529
+ let mut archive = Archive :: new ( File :: open ( rlib) . unwrap ( ) ) ;
530
+ while let Some ( entry) = archive. next_entry ( ) {
511
531
let mut entry = entry. unwrap ( ) ;
512
- if entry. path ( ) . unwrap ( ) != Path :: new ( METADATA_FILENAME ) {
532
+ if entry. header ( ) . identifier ( ) != METADATA_FILENAME . as_bytes ( ) {
513
533
// std::fs::read adds 1 to the size, so do the same here - see comment:
514
534
// https://github.com/rust-lang/rust/blob/72868e017bdade60603a25889e253f556305f996/library/std/src/fs.rs#L200-L202
515
- let mut bytes = Vec :: with_capacity ( entry. size ( ) as usize + 1 ) ;
535
+ let mut bytes = Vec :: with_capacity ( entry. header ( ) . size ( ) as usize + 1 ) ;
516
536
entry. read_to_end ( & mut bytes) . unwrap ( ) ;
517
537
modules. push ( load ( & bytes) ) ;
518
538
}
0 commit comments