@@ -20,6 +20,8 @@ use std::str;
20
20
use extra:: tempfile:: TempDir ;
21
21
use syntax:: abi;
22
22
23
+ pub static METADATA_FILENAME : & ' static str = "metadata" ;
24
+
23
25
pub struct Archive {
24
26
priv sess : Session ,
25
27
priv dst: Path ,
@@ -40,7 +42,8 @@ fn run_ar(sess: Session, args: &str, cwd: Option<&Path>,
40
42
}
41
43
let o = Process :: new ( ar, args. as_slice ( ) , opts) . finish_with_output ( ) ;
42
44
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) ) ;
44
47
sess. note ( format ! ( "stdout ---\n {}" , str :: from_utf8( o. output) ) ) ;
45
48
sess. note ( format ! ( "stderr ---\n {}" , str :: from_utf8( o. error) ) ) ;
46
49
sess. abort_if_errors ( ) ;
@@ -81,17 +84,40 @@ impl Archive {
81
84
/// search in the relevant locations for a library named `name`.
82
85
pub fn add_native_library ( & mut self , name : & str ) {
83
86
let location = self . find_library ( name) ;
84
- self . add_archive ( & location, name) ;
87
+ self . add_archive ( & location, name, [ ] ) ;
85
88
}
86
89
87
90
/// Adds all of the contents of the rlib at the specified path to this
88
91
/// 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) ;
92
103
}
93
104
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 ] ) {
95
121
let loc = TempDir :: new ( "rsar" ) . unwrap ( ) ;
96
122
97
123
// First, extract the contents of the archive to a temporary directory
@@ -102,10 +128,17 @@ impl Archive {
102
128
// The reason for this is that archives are keyed off the name of the
103
129
// files, so if two files have the same name they will override one
104
130
// 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.
105
135
let files = fs:: readdir ( loc. path ( ) ) ;
106
136
let mut inputs = ~[ ] ;
107
137
for file in files. iter ( ) {
108
138
let filename = file. filename_str ( ) . unwrap ( ) ;
139
+ if skip. iter ( ) . any ( |s| * s == filename) { continue }
140
+ if filename. contains ( ".SYMDEF" ) { continue }
141
+
109
142
let filename = format ! ( "r-{}-{}" , name, filename) ;
110
143
let new_filename = file. with_filename ( filename) ;
111
144
fs:: rename ( file, & new_filename) ;
0 commit comments