@@ -30,16 +30,11 @@ pub struct ArchiveConfig<'a> {
30
30
pub lib_search_paths : Vec < PathBuf > ,
31
31
pub slib_prefix : String ,
32
32
pub slib_suffix : String ,
33
- pub maybe_ar_prog : Option < String >
33
+ pub ar_prog : String
34
34
}
35
35
36
36
pub struct Archive < ' a > {
37
- handler : & ' a ErrorHandler ,
38
- dst : PathBuf ,
39
- lib_search_paths : Vec < PathBuf > ,
40
- slib_prefix : String ,
41
- slib_suffix : String ,
42
- maybe_ar_prog : Option < String >
37
+ config : ArchiveConfig < ' a > ,
43
38
}
44
39
45
40
/// Helper for adding many files to an archive with a single invocation of
@@ -53,47 +48,10 @@ pub struct ArchiveBuilder<'a> {
53
48
should_update_symbols : bool ,
54
49
}
55
50
56
- fn run_ar ( handler : & ErrorHandler , maybe_ar_prog : & Option < String > ,
57
- args : & str , cwd : Option < & Path > ,
58
- paths : & [ & Path ] ) -> Output {
59
- let ar = match * maybe_ar_prog {
60
- Some ( ref ar) => & ar[ ..] ,
61
- None => "ar"
62
- } ;
63
- let mut cmd = Command :: new ( ar) ;
64
-
65
- cmd. arg ( args) . args ( paths) . stdout ( Stdio :: piped ( ) ) . stderr ( Stdio :: piped ( ) ) ;
66
- debug ! ( "{:?}" , cmd) ;
67
-
68
- match cwd {
69
- Some ( p) => {
70
- cmd. current_dir ( p) ;
71
- debug ! ( "inside {:?}" , p. display( ) ) ;
72
- }
73
- None => { }
74
- }
75
-
76
- match cmd. spawn ( ) {
77
- Ok ( prog) => {
78
- let o = prog. wait_with_output ( ) . unwrap ( ) ;
79
- if !o. status . success ( ) {
80
- handler. err ( & format ! ( "{:?} failed with: {}" , cmd, o. status) ) ;
81
- handler. note ( & format ! ( "stdout ---\n {}" ,
82
- str :: from_utf8( & o. stdout) . unwrap( ) ) ) ;
83
- handler. note ( & format ! ( "stderr ---\n {}" ,
84
- str :: from_utf8( & o. stderr) . unwrap( ) )
85
- ) ;
86
- handler. abort_if_errors ( ) ;
87
- }
88
- o
89
- } ,
90
- Err ( e) => {
91
- handler. err ( & format ! ( "could not exec `{}`: {}" , & ar[ ..] ,
92
- e) ) ;
93
- handler. abort_if_errors ( ) ;
94
- panic ! ( "rustc::back::archive::run_ar() should not reach this point" ) ;
95
- }
96
- }
51
+ enum Action < ' a > {
52
+ Remove ( & ' a Path ) ,
53
+ AddObjects ( & ' a [ & ' a PathBuf ] , bool ) ,
54
+ UpdateSymbols ,
97
55
}
98
56
99
57
pub fn find_library ( name : & str , osprefix : & str , ossuffix : & str ,
@@ -120,43 +78,89 @@ pub fn find_library(name: &str, osprefix: &str, ossuffix: &str,
120
78
121
79
impl < ' a > Archive < ' a > {
122
80
fn new ( config : ArchiveConfig < ' a > ) -> Archive < ' a > {
123
- let ArchiveConfig { handler, dst, lib_search_paths, slib_prefix, slib_suffix,
124
- maybe_ar_prog } = config;
125
- Archive {
126
- handler : handler,
127
- dst : dst,
128
- lib_search_paths : lib_search_paths,
129
- slib_prefix : slib_prefix,
130
- slib_suffix : slib_suffix,
131
- maybe_ar_prog : maybe_ar_prog
132
- }
81
+ Archive { config : config }
133
82
}
134
83
135
84
/// Opens an existing static archive
136
85
pub fn open ( config : ArchiveConfig < ' a > ) -> Archive < ' a > {
137
86
let archive = Archive :: new ( config) ;
138
- assert ! ( archive. dst. exists( ) ) ;
87
+ assert ! ( archive. config . dst. exists( ) ) ;
139
88
archive
140
89
}
141
90
142
91
/// Removes a file from this archive
143
92
pub fn remove_file ( & mut self , file : & str ) {
144
- run_ar ( self . handler , & self . maybe_ar_prog , "d" , None , & [ & self . dst , & Path :: new ( file) ] ) ;
93
+ self . run ( None , Action :: Remove ( Path :: new ( file) ) ) ;
145
94
}
146
95
147
96
/// Lists all files in an archive
148
97
pub fn files ( & self ) -> Vec < String > {
149
- let output = run_ar ( self . handler , & self . maybe_ar_prog , "t" , None , & [ & self . dst ] ) ;
150
- let output = str:: from_utf8 ( & output. stdout ) . unwrap ( ) ;
151
- // use lines_any because windows delimits output with `\r\n` instead of
152
- // just `\n`
153
- output. lines_any ( ) . map ( |s| s. to_string ( ) ) . collect ( )
98
+ let archive = match ArchiveRO :: open ( & self . config . dst ) {
99
+ Some ( ar) => ar,
100
+ None => return Vec :: new ( ) ,
101
+ } ;
102
+ let ret = archive. iter ( ) . filter_map ( |child| child. name ( ) )
103
+ . map ( |name| name. to_string ( ) )
104
+ . collect ( ) ;
105
+ return ret;
154
106
}
155
107
156
108
/// Creates an `ArchiveBuilder` for adding files to this archive.
157
109
pub fn extend ( self ) -> ArchiveBuilder < ' a > {
158
110
ArchiveBuilder :: new ( self )
159
111
}
112
+
113
+ fn run ( & self , cwd : Option < & Path > , action : Action ) -> Output {
114
+ let abs_dst = env:: current_dir ( ) . unwrap ( ) . join ( & self . config . dst ) ;
115
+ let ar = & self . config . ar_prog ;
116
+ let mut cmd = Command :: new ( ar) ;
117
+ cmd. stdout ( Stdio :: piped ( ) ) . stderr ( Stdio :: piped ( ) ) ;
118
+ self . prepare_ar_action ( & mut cmd, & abs_dst, action) ;
119
+ info ! ( "{:?}" , cmd) ;
120
+
121
+ if let Some ( p) = cwd {
122
+ cmd. current_dir ( p) ;
123
+ info ! ( "inside {:?}" , p. display( ) ) ;
124
+ }
125
+
126
+ let handler = & self . config . handler ;
127
+ match cmd. spawn ( ) {
128
+ Ok ( prog) => {
129
+ let o = prog. wait_with_output ( ) . unwrap ( ) ;
130
+ if !o. status . success ( ) {
131
+ handler. err ( & format ! ( "{:?} failed with: {}" , cmd, o. status) ) ;
132
+ handler. note ( & format ! ( "stdout ---\n {}" ,
133
+ str :: from_utf8( & o. stdout) . unwrap( ) ) ) ;
134
+ handler. note ( & format ! ( "stderr ---\n {}" ,
135
+ str :: from_utf8( & o. stderr) . unwrap( ) ) ) ;
136
+ handler. abort_if_errors ( ) ;
137
+ }
138
+ o
139
+ } ,
140
+ Err ( e) => {
141
+ handler. err ( & format ! ( "could not exec `{}`: {}" ,
142
+ self . config. ar_prog, e) ) ;
143
+ handler. abort_if_errors ( ) ;
144
+ panic ! ( "rustc::back::archive::run() should not reach this point" ) ;
145
+ }
146
+ }
147
+ }
148
+
149
+ fn prepare_ar_action ( & self , cmd : & mut Command , dst : & Path , action : Action ) {
150
+ match action {
151
+ Action :: Remove ( file) => {
152
+ cmd. arg ( "d" ) . arg ( dst) . arg ( file) ;
153
+ }
154
+ Action :: AddObjects ( objs, update_symbols) => {
155
+ cmd. arg ( if update_symbols { "crus" } else { "cruS" } )
156
+ . arg ( dst)
157
+ . args ( objs) ;
158
+ }
159
+ Action :: UpdateSymbols => {
160
+ cmd. arg ( "s" ) . arg ( dst) ;
161
+ }
162
+ }
163
+ }
160
164
}
161
165
162
166
impl < ' a > ArchiveBuilder < ' a > {
@@ -179,10 +183,10 @@ impl<'a> ArchiveBuilder<'a> {
179
183
/// search in the relevant locations for a library named `name`.
180
184
pub fn add_native_library ( & mut self , name : & str ) -> io:: Result < ( ) > {
181
185
let location = find_library ( name,
182
- & self . archive . slib_prefix ,
183
- & self . archive . slib_suffix ,
184
- & self . archive . lib_search_paths ,
185
- self . archive . handler ) ;
186
+ & self . archive . config . slib_prefix ,
187
+ & self . archive . config . slib_suffix ,
188
+ & self . archive . config . lib_search_paths ,
189
+ self . archive . config . handler ) ;
186
190
self . add_archive ( & location, name, |_| false )
187
191
}
188
192
@@ -229,17 +233,13 @@ impl<'a> ArchiveBuilder<'a> {
229
233
pub fn build ( self ) -> Archive < ' a > {
230
234
// Get an absolute path to the destination, so `ar` will work even
231
235
// though we run it from `self.work_dir`.
232
- let abs_dst = env:: current_dir ( ) . unwrap ( ) . join ( & self . archive . dst ) ;
233
- assert ! ( !abs_dst. is_relative( ) ) ;
234
- let mut args = vec ! [ & * abs_dst] ;
235
- let mut total_len = abs_dst. to_string_lossy ( ) . len ( ) ;
236
+ let mut objects = Vec :: new ( ) ;
237
+ let mut total_len = self . archive . config . dst . to_string_lossy ( ) . len ( ) ;
236
238
237
239
if self . members . is_empty ( ) {
238
- // OSX `ar` does not allow using `r` with no members, but it does
239
- // allow running `ar s file.a` to update symbols only.
240
240
if self . should_update_symbols {
241
- run_ar ( self . archive . handler , & self . archive . maybe_ar_prog ,
242
- "s" , Some ( self . work_dir . path ( ) ) , & args [ .. ] ) ;
241
+ self . archive . run ( Some ( self . work_dir . path ( ) ) ,
242
+ Action :: UpdateSymbols ) ;
243
243
}
244
244
return self . archive ;
245
245
}
@@ -257,24 +257,22 @@ impl<'a> ArchiveBuilder<'a> {
257
257
// string, not an array of strings.)
258
258
if total_len + len + 1 > ARG_LENGTH_LIMIT {
259
259
// Add the archive members seen so far, without updating the
260
- // symbol table (`S`) .
261
- run_ar ( self . archive . handler , & self . archive . maybe_ar_prog ,
262
- "cruS" , Some ( self . work_dir . path ( ) ) , & args [ .. ] ) ;
260
+ // symbol table.
261
+ self . archive . run ( Some ( self . work_dir . path ( ) ) ,
262
+ Action :: AddObjects ( & objects , false ) ) ;
263
263
264
- args. clear ( ) ;
265
- args. push ( & abs_dst) ;
266
- total_len = abs_dst. to_string_lossy ( ) . len ( ) ;
264
+ objects. clear ( ) ;
265
+ total_len = self . archive . config . dst . to_string_lossy ( ) . len ( ) ;
267
266
}
268
267
269
- args . push ( member_name) ;
268
+ objects . push ( member_name) ;
270
269
total_len += len + 1 ;
271
270
}
272
271
273
272
// Add the remaining archive members, and update the symbol table if
274
273
// necessary.
275
- let flags = if self . should_update_symbols { "crus" } else { "cruS" } ;
276
- run_ar ( self . archive . handler , & self . archive . maybe_ar_prog ,
277
- flags, Some ( self . work_dir . path ( ) ) , & args[ ..] ) ;
274
+ self . archive . run ( Some ( self . work_dir . path ( ) ) ,
275
+ Action :: AddObjects ( & objects, self . should_update_symbols ) ) ;
278
276
279
277
self . archive
280
278
}
@@ -305,6 +303,8 @@ impl<'a> ArchiveBuilder<'a> {
305
303
} ;
306
304
if filename. contains ( ".SYMDEF" ) { continue }
307
305
if skip ( filename) { continue }
306
+ let filename = Path :: new ( filename) . file_name ( ) . unwrap ( )
307
+ . to_str ( ) . unwrap ( ) ;
308
308
309
309
// An archive can contain files of the same name multiple times, so
310
310
// we need to be sure to not have them overwrite one another when we
0 commit comments