@@ -2,6 +2,7 @@ use crate::codegen_cx::{CodegenArgs, ModuleOutputType};
22use crate :: {
33 linker, CompileResult , ModuleResult , SpirvCodegenBackend , SpirvModuleBuffer , SpirvThinBuffer ,
44} ;
5+ use ar:: { Archive , GnuBuilder , Header } ;
56use rspirv:: binary:: Assemble ;
67use rustc_codegen_ssa:: back:: lto:: { LtoModuleCodegen , SerializedModule , ThinModule , ThinShared } ;
78use rustc_codegen_ssa:: back:: write:: CodegenContext ;
@@ -19,12 +20,12 @@ use rustc_session::output::{check_file_is_writeable, invalid_output_for_target,
1920use rustc_session:: utils:: NativeLibKind ;
2021use rustc_session:: Session ;
2122use std:: env;
22- use std:: ffi:: { CString , OsStr } ;
23+ use std:: ffi:: CString ;
2324use std:: fs:: File ;
2425use std:: io:: { BufWriter , Read } ;
26+ use std:: iter;
2527use std:: path:: { Path , PathBuf } ;
2628use std:: sync:: Arc ;
27- use tar:: { Archive , Builder , Header } ;
2829
2930pub fn link < ' a > (
3031 sess : & ' a Session ,
@@ -439,35 +440,53 @@ fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
439440}
440441
441442fn 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+
451467 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 {
454470 assert ! (
455- filenames. insert( file . file_name ( ) . unwrap ( ) ) ,
471+ filenames. insert( name ) ,
456472 "Duplicate filename in archive: {:?}" ,
457473 file. file_name( ) . unwrap( )
458474 ) ;
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.
459477 builder
460- . append_path_with_name ( file , file . file_name ( ) . unwrap ( ) )
478+ . append_file ( name . as_bytes ( ) , & mut File :: open ( file ) . unwrap ( ) )
461479 . unwrap ( ) ;
462480 }
463481 builder. into_inner ( ) . unwrap ( ) ;
464482}
465483
466484pub fn read_metadata ( rlib : & Path ) -> Result < MetadataRef , String > {
467485 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 ( ) {
469488 let mut entry = entry?;
470- if entry. path ( ) ? == Path :: new ( METADATA_FILENAME ) {
489+ if entry. header ( ) . identifier ( ) == METADATA_FILENAME . as_bytes ( ) {
471490 let mut bytes = Vec :: new ( ) ;
472491 entry. read_to_end ( & mut bytes) ?;
473492 let buf: OwningRef < Vec < u8 > , [ u8 ] > = OwningRef :: new ( bytes) ;
@@ -507,12 +526,13 @@ fn do_link(
507526 // `rlibs` are archive files we've created in `create_archive`, usually produced by crates that are being
508527 // referenced. We need to unpack them and add the modules inside.
509528 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 ( ) {
511531 let mut entry = entry. unwrap ( ) ;
512- if entry. path ( ) . unwrap ( ) != Path :: new ( METADATA_FILENAME ) {
532+ if entry. header ( ) . identifier ( ) != METADATA_FILENAME . as_bytes ( ) {
513533 // std::fs::read adds 1 to the size, so do the same here - see comment:
514534 // 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 ) ;
516536 entry. read_to_end ( & mut bytes) . unwrap ( ) ;
517537 modules. push ( load ( & bytes) ) ;
518538 }
0 commit comments