fn link_rlib<'a>(sess: &'a Session,
                 trans: Option<&CrateTranslation>, // None == no metadata/bytecode
                 objects: &[PathBuf],
                 out_filename: &Path,
                 tmpdir: &Path) -> ArchiveBuilder<'a> {
    info!("preparing rlib from {:?} to {:?}", objects, out_filename);
    let mut ab = ArchiveBuilder::new(archive_config(sess, out_filename, None));
    for obj in objects {
        ab.add_file(obj);
    }

    for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
        match kind {
            cstore::NativeStatic => ab.add_native_library(&l).unwrap(),
            cstore::NativeFramework | cstore::NativeUnknown => {}
        }
    }

    // After adding all files to the archive, we need to update the
    // symbol table of the archive.
    ab.update_symbols();

    // For OSX/iOS, we must be careful to update symbols only when adding
    // object files.  We're about to start adding non-object files, so run
    // `ar` now to process the object files.
    if sess.target.target.options.is_like_osx && !ab.using_llvm() {
        ab.build();
    }

    // Note that it is important that we add all of our non-object "magical
    // files" *after* all of the object files in the archive. The reason for
    // this is as follows:
    //
    // * When performing LTO, this archive will be modified to remove
    //   objects from above. The reason for this is described below.
    //
    // * When the system linker looks at an archive, it will attempt to
    //   determine the architecture of the archive in order to see whether its
    //   linkable.
    //
    //   The algorithm for this detection is: iterate over the files in the
    //   archive. Skip magical SYMDEF names. Interpret the first file as an
    //   object file. Read architecture from the object file.
    //
    // * As one can probably see, if "metadata" and "foo.bc" were placed
    //   before all of the objects, then the architecture of this archive would
    //   not be correctly inferred once 'foo.o' is removed.
    //
    // Basically, all this means is that this code should not move above the
    // code above.
    match trans {
        Some(trans) => {
            // Instead of putting the metadata in an object file section, rlibs
            // contain the metadata in a separate file. We use a temp directory
            // here so concurrent builds in the same directory don't try to use
            // the same filename for metadata (stomping over one another)
            let metadata = tmpdir.join(METADATA_FILENAME);
            match fs::File::create(&metadata).and_then(|mut f| {
                f.write_all(&trans.metadata)
            }) {
                Ok(..) => {}
                Err(e) => {
                    sess.fatal(&format!("failed to write {}: {}",
                                        metadata.display(), e));
                }
            }
            ab.add_file(&metadata);

            // For LTO purposes, the bytecode of this library is also inserted
            // into the archive.  If codegen_units > 1, we insert each of the
            // bitcode files.
            for obj in objects {
                // Note that we make sure that the bytecode filename in the
                // archive is never exactly 16 bytes long by adding a 16 byte
                // extension to it. This is to work around a bug in LLDB that
                // would cause it to crash if the name of a file in an archive
                // was exactly 16 bytes.
                let bc_filename = obj.with_extension("bc");
                let bc_deflated_filename = tmpdir.join({
                    obj.with_extension("bytecode.deflate").file_name().unwrap()
                });

                let mut bc_data = Vec::new();
                match fs::File::open(&bc_filename).and_then(|mut f| {
                    f.read_to_end(&mut bc_data)
                }) {
                    Ok(..) => {}
                    Err(e) => sess.fatal(&format!("failed to read bytecode: {}",
                                                 e))
                }

                let bc_data_deflated = flate::deflate_bytes(&bc_data[..]);

                let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) {
                    Ok(file) => file,
                    Err(e) => {
                        sess.fatal(&format!("failed to create compressed \
                                             bytecode file: {}", e))
                    }
                };

                match write_rlib_bytecode_object_v1(&mut bc_file_deflated,
                                                    &bc_data_deflated) {
                    Ok(()) => {}
                    Err(e) => {
                        sess.fatal(&format!("failed to write compressed \
                                             bytecode: {}", e));
                    }
                };

                ab.add_file(&bc_deflated_filename);

                // See the bottom of back::write::run_passes for an explanation
                // of when we do and don't keep .0.bc files around.
                let user_wants_numbered_bitcode =
                        sess.opts.output_types.contains(&OutputTypeBitcode) &&
                        sess.opts.cg.codegen_units > 1;
                if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode {
                    remove(sess, &bc_filename);
                }
            }

            // After adding all files to the archive, we need to update the
            // symbol table of the archive. This currently dies on OSX (see
            // #11162), and isn't necessary there anyway
            if !sess.target.target.options.is_like_osx || ab.using_llvm() {
                ab.update_symbols();
            }
        }

        None => {}
    }

    ab
}
// Create an 'rlib'
//
// An rlib in its current incarnation is essentially a renamed .a file. The
// rlib primarily contains the object file of the crate, but it also contains
// all of the object files from native libraries. This is done by unzipping
// native libraries and inserting all of the contents into this archive.
Create an 'rlib'
An rlib in its current incarnation is essentially a renamed .a file. The
rlib primarily contains the object file of the crate, but it also contains
all of the object files from native libraries. This is done by unzipping
native libraries and inserting all of the contents into this archive.
Create an ' rlib ' An rlib in its current incarnation is essentially a renamed . a file . The rlib primarily contains the object file of the crate but it also contains all of the object files from native libraries . This is done by unzipping native libraries and inserting all of the contents into this archive .
fn link_rlib<'a>(sess: &'a Session,
                 trans: Option<&CrateTranslation>, // None == no metadata/bytecode
                 objects: &[PathBuf],
                 out_filename: &Path,
                 tmpdir: &Path) -> ArchiveBuilder<'a> {
    info!("preparing rlib from {:?} to {:?}", objects, out_filename);
    let mut ab = ArchiveBuilder::new(archive_config(sess, out_filename, None));
    for obj in objects {
        ab.add_file(obj);
    }
    for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
        match kind {
            cstore::NativeStatic => ab.add_native_library(&l).unwrap(),
            cstore::NativeFramework | cstore::NativeUnknown => {}
        }
    }
    // After adding all files to the archive, we need to update the
    // symbol table of the archive.
    ab.update_symbols();
    // For OSX/iOS, we must be careful to update symbols only when adding
    // object files.  We're about to start adding non-object files, so run
    // `ar` now to process the object files.
    if sess.target.target.options.is_like_osx && !ab.using_llvm() {
        ab.build();
    }
    // Note that it is important that we add all of our non-object "magical
    // files" *after* all of the object files in the archive. The reason for
    // this is as follows:
    //
    // * When performing LTO, this archive will be modified to remove
    //   objects from above. The reason for this is described below.
    //
    // * When the system linker looks at an archive, it will attempt to
    //   determine the architecture of the archive in order to see whether its
    //   linkable.
    //
    //   The algorithm for this detection is: iterate over the files in the
    //   archive. Skip magical SYMDEF names. Interpret the first file as an
    //   object file. Read architecture from the object file.
    //
    // * As one can probably see, if "metadata" and "foo.bc" were placed
    //   before all of the objects, then the architecture of this archive would
    //   not be correctly inferred once 'foo.o' is removed.
    //
    // Basically, all this means is that this code should not move above the
    // code above.
    match trans {
        Some(trans) => {
            // Instead of putting the metadata in an object file section, rlibs
            // contain the metadata in a separate file. We use a temp directory
            // here so concurrent builds in the same directory don't try to use
            // the same filename for metadata (stomping over one another)
            let metadata = tmpdir.join(METADATA_FILENAME);
            match fs::File::create(&metadata).and_then(|mut f| {
                f.write_all(&trans.metadata)
            }) {
                Ok(..) => {}
                Err(e) => {
                    sess.fatal(&format!("failed to write {}: {}",
                                        metadata.display(), e));
                }
            }
            ab.add_file(&metadata);
            // For LTO purposes, the bytecode of this library is also inserted
            // into the archive.  If codegen_units > 1, we insert each of the
            // bitcode files.
            for obj in objects {
                // Note that we make sure that the bytecode filename in the
                // archive is never exactly 16 bytes long by adding a 16 byte
                // extension to it. This is to work around a bug in LLDB that
                // would cause it to crash if the name of a file in an archive
                // was exactly 16 bytes.
                let bc_filename = obj.with_extension("bc");
                let bc_deflated_filename = tmpdir.join({
                    obj.with_extension("bytecode.deflate").file_name().unwrap()
                });
                let mut bc_data = Vec::new();
                match fs::File::open(&bc_filename).and_then(|mut f| {
                    f.read_to_end(&mut bc_data)
                }) {
                    Ok(..) => {}
                    Err(e) => sess.fatal(&format!("failed to read bytecode: {}",
                                                 e))
                }
                let bc_data_deflated = flate::deflate_bytes(&bc_data[..]);
                let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) {
                    Ok(file) => file,
                    Err(e) => {
                        sess.fatal(&format!("failed to create compressed \
                                             bytecode file: {}", e))
                    }
                };
                match write_rlib_bytecode_object_v1(&mut bc_file_deflated,
                                                    &bc_data_deflated) {
                    Ok(()) => {}
                    Err(e) => {
                        sess.fatal(&format!("failed to write compressed \
                                             bytecode: {}", e));
                    }
                };
                ab.add_file(&bc_deflated_filename);
                // See the bottom of back::write::run_passes for an explanation
                // of when we do and don't keep .0.bc files around.
                let user_wants_numbered_bitcode =
                        sess.opts.output_types.contains(&OutputTypeBitcode) &&
                        sess.opts.cg.codegen_units > 1;
                if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode {
                    remove(sess, &bc_filename);
                }
            }
            // After adding all files to the archive, we need to update the
            // symbol table of the archive. This currently dies on OSX (see
            // #11162), and isn't necessary there anyway
            if !sess.target.target.options.is_like_osx || ab.using_llvm() {
                ab.update_symbols();
            }
        }
        None => {}
    }
    ab
}
fn link_rlib < ' a > ( sess : & ' a Session , trans : Option < & CrateTranslation > , // None == no metadata/bytecode objects : & [ PathBuf ] , out_filename : & Path , tmpdir : & Path ) -> ArchiveBuilder < ' a > { info ! ( " " objects out_filename ) ; let mut ab = ArchiveBuilder :: new ( archive_config ( sess , out_filename , None ) ) ; for obj in objects { ab . add_file ( obj ) ; } for & ( ref l , kind ) in sess . cstore . get_used_libraries ( ) . borrow ( ) . iter ( ) { match kind { cstore :: NativeStatic => ab . add_native_library ( & l ) . unwrap ( ) , cstore :: NativeFramework | cstore :: NativeUnknown => { } } } // After adding all files to the archive, we need to update the // symbol table of the archive. ab . update_symbols ( ) ; // For OSX/iOS, we must be careful to update symbols only when adding // object files.  We're about to start adding non-object files, so run // `ar` now to process the object files. if sess . target . target . options . is_like_osx && ! ab . using_llvm ( ) { ab . build ( ) ; } // Note that it is important that we add all of our non-object "magical // files" *after* all of the object files in the archive. The reason for // this is as follows: // // * When performing LTO, this archive will be modified to remove //   objects from above. The reason for this is described below. // // * When the system linker looks at an archive, it will attempt to //   determine the architecture of the archive in order to see whether its //   linkable. // //   The algorithm for this detection is: iterate over the files in the //   archive. Skip magical SYMDEF names. Interpret the first file as an //   object file. Read architecture from the object file. // // * As one can probably see, if "metadata" and "foo.bc" were placed //   before all of the objects, then the architecture of this archive would //   not be correctly inferred once 'foo.o' is removed. // // Basically, all this means is that this code should not move above the // code above. match trans { Some ( trans ) => { // Instead of putting the metadata in an object file section, rlibs // contain the metadata in a separate file. We use a temp directory // here so concurrent builds in the same directory don't try to use // the same filename for metadata (stomping over one another) let metadata = tmpdir . join ( METADATA_FILENAME ) ; match fs :: File :: create ( & metadata ) . and_then ( | mut f | { f . write_all ( & trans . metadata ) } ) { Ok ( .. ) => { } Err ( e ) => { sess . fatal ( & format ! ( " " metadata display ( ) e ) ) ; } } ab . add_file ( & metadata ) ; // For LTO purposes, the bytecode of this library is also inserted // into the archive.  If codegen_units > 1, we insert each of the // bitcode files. for obj in objects { // Note that we make sure that the bytecode filename in the // archive is never exactly 16 bytes long by adding a 16 byte // extension to it. This is to work around a bug in LLDB that // would cause it to crash if the name of a file in an archive // was exactly 16 bytes. let bc_filename = obj . with_extension ( " " ) ; let bc_deflated_filename = tmpdir . join ( { obj . with_extension ( " " ) . file_name ( ) . unwrap ( ) } ) ; let mut bc_data = Vec :: new ( ) ; match fs :: File :: open ( & bc_filename ) . and_then ( | mut f | { f . read_to_end ( & mut bc_data ) } ) { Ok ( .. ) => { } Err ( e ) => sess . fatal ( & format ! ( " " e ) ) } let bc_data_deflated = flate :: deflate_bytes ( & bc_data [ .. ] ) ; let mut bc_file_deflated = match fs :: File :: create ( & bc_deflated_filename ) { Ok ( file ) => file , Err ( e ) => { sess . fatal ( & format ! ( " \
 " e ) ) } } ; match write_rlib_bytecode_object_v1 ( & mut bc_file_deflated , & bc_data_deflated ) { Ok ( ( ) ) => { } Err ( e ) => { sess . fatal ( & format ! ( " \
 " e ) ) ; } } ; ab . add_file ( & bc_deflated_filename ) ; // See the bottom of back::write::run_passes for an explanation // of when we do and don't keep .0.bc files around. let user_wants_numbered_bitcode = sess . opts . output_types . contains ( & OutputTypeBitcode ) && sess . opts . cg . codegen_units > 1 ; if ! sess . opts . cg . save_temps && ! user_wants_numbered_bitcode { remove ( sess , & bc_filename ) ; } } // After adding all files to the archive, we need to update the // symbol table of the archive. This currently dies on OSX (see // #11162), and isn't necessary there anyway if ! sess . target . target . options . is_like_osx || ab . using_llvm ( ) { ab . update_symbols ( ) ; } } None => { } } ab }
Create an 'rlib'
An rlib in its current incarnation is essentially a renamed .a file.
Create an ' rlib ' An rlib in its current incarnation is essentially a renamed . a file .
sess
&'a Session
trans
Option<&CrateTranslation>
objects
&[PathBuf]
out_filename
&Path
tmpdir
&Path
sess
&'a Session
trans
Option<&CrateTranslation>
objects
&[PathBuf]
out_filename
&Path
tmpdir
&Path