@@ -20,6 +20,8 @@ use std::str;
2020use extra:: tempfile:: TempDir ;
2121use syntax:: abi;
2222
23+ pub static METADATA_FILENAME : & ' static str = "metadata" ;
24+
2325pub struct Archive {
2426 priv sess : Session ,
2527 priv dst: Path ,
@@ -40,7 +42,8 @@ fn run_ar(sess: Session, args: &str, cwd: Option<&Path>,
4042 }
4143 let o = Process :: new ( ar, args. as_slice ( ) , opts) . finish_with_output ( ) ;
4244 if !o. status . success ( ) {
43- sess. err ( format ! ( "{} failed with: {}" , ar, o. status) ) ;
45+ sess. err ( format ! ( "{} {} failed with: {}" , ar, args. connect( " " ) ,
46+ o. status) ) ;
4447 sess. note ( format ! ( "stdout ---\n {}" , str :: from_utf8( o. output) ) ) ;
4548 sess. note ( format ! ( "stderr ---\n {}" , str :: from_utf8( o. error) ) ) ;
4649 sess. abort_if_errors ( ) ;
@@ -81,17 +84,40 @@ impl Archive {
8184 /// search in the relevant locations for a library named `name`.
8285 pub fn add_native_library ( & mut self , name : & str ) {
8386 let location = self . find_library ( name) ;
84- self . add_archive ( & location, name) ;
87+ self . add_archive ( & location, name, [ ] ) ;
8588 }
8689
8790 /// Adds all of the contents of the rlib at the specified path to this
8891 /// archive.
89- pub fn add_rlib ( & mut self , rlib : & Path ) {
90- let name = rlib. filename_str ( ) . unwrap ( ) . split ( '-' ) . next ( ) . unwrap ( ) ;
91- self . add_archive ( rlib, name) ;
92+ ///
93+ /// This ignores adding the bytecode from the rlib, and if LTO is enabled
94+ /// then the object file also isn't added.
95+ pub fn add_rlib ( & mut self , rlib : & Path , name : & str , lto : bool ) {
96+ let object = format ! ( "{}.o" , name) ;
97+ let bytecode = format ! ( "{}.bc" , name) ;
98+ let mut ignore = ~[ METADATA_FILENAME , bytecode. as_slice ( ) ] ;
99+ if lto {
100+ ignore. push ( object. as_slice ( ) ) ;
101+ }
102+ self . add_archive ( rlib, name, ignore) ;
92103 }
93104
94- fn add_archive ( & mut self , archive : & Path , name : & str ) {
105+ /// Adds an arbitrary file to this archive
106+ pub fn add_file ( & mut self , file : & Path ) {
107+ run_ar ( self . sess , "r" , None , [ & self . dst , file] ) ;
108+ }
109+
110+ /// Removes a file from this archive
111+ pub fn remove_file ( & mut self , file : & str ) {
112+ run_ar ( self . sess , "d" , None , [ & self . dst , & Path :: new ( file) ] ) ;
113+ }
114+
115+ pub fn files ( & self ) -> ~[ ~str ] {
116+ let output = run_ar ( self . sess , "t" , None , [ & self . dst ] ) ;
117+ str:: from_utf8 ( output. output ) . lines ( ) . map ( |s| s. to_owned ( ) ) . collect ( )
118+ }
119+
120+ fn add_archive ( & mut self , archive : & Path , name : & str , skip : & [ & str ] ) {
95121 let loc = TempDir :: new ( "rsar" ) . unwrap ( ) ;
96122
97123 // First, extract the contents of the archive to a temporary directory
@@ -102,10 +128,17 @@ impl Archive {
102128 // The reason for this is that archives are keyed off the name of the
103129 // files, so if two files have the same name they will override one
104130 // another in the archive (bad).
131+ //
132+ // We skip any files explicitly desired for skipping, and we also skip
133+ // all SYMDEF files as these are just magical placeholders which get
134+ // re-created when we make a new archive anyway.
105135 let files = fs:: readdir ( loc. path ( ) ) ;
106136 let mut inputs = ~[ ] ;
107137 for file in files. iter ( ) {
108138 let filename = file. filename_str ( ) . unwrap ( ) ;
139+ if skip. iter ( ) . any ( |s| * s == filename) { continue }
140+ if filename. contains ( ".SYMDEF" ) { continue }
141+
109142 let filename = format ! ( "r-{}-{}" , name, filename) ;
110143 let new_filename = file. with_filename ( filename) ;
111144 fs:: rename ( file, & new_filename) ;
0 commit comments