1
- use std:: collections:: HashMap ;
2
1
use std:: fs:: File ;
3
2
use std:: path:: { Path , PathBuf } ;
4
3
@@ -8,12 +7,14 @@ use rustc_codegen_ssa::{METADATA_FILENAME, RLIB_BYTECODE_EXTENSION};
8
7
use rustc_codegen_ssa:: back:: archive:: { ArchiveBuilder , find_library} ;
9
8
10
9
struct ArchiveConfig < ' a > {
11
- pub sess : & ' a Session ,
12
- pub dst : PathBuf ,
13
- pub src : Option < PathBuf > ,
14
- pub lib_search_paths : Vec < PathBuf > ,
10
+ sess : & ' a Session ,
11
+ dst : PathBuf ,
12
+ src : Option < PathBuf > ,
13
+ lib_search_paths : Vec < PathBuf > ,
14
+ use_gnu_style_archive : bool ,
15
15
}
16
16
17
+ #[ derive( Debug ) ]
17
18
enum ArchiveEntry {
18
19
FromArchive { archive_index : usize , entry_index : usize } ,
19
20
File ( File ) ,
@@ -22,7 +23,9 @@ enum ArchiveEntry {
22
23
pub struct ArArchiveBuilder < ' a > {
23
24
config : ArchiveConfig < ' a > ,
24
25
src_archives : Vec < ar:: Archive < File > > ,
25
- entries : HashMap < String , ArchiveEntry > ,
26
+ // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
27
+ // the end of an archive for linkers to not get confused.
28
+ entries : Vec < ( String , ArchiveEntry ) > ,
26
29
update_symbols : bool ,
27
30
}
28
31
@@ -34,25 +37,27 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
34
37
dst : output. to_path_buf ( ) ,
35
38
src : input. map ( |p| p. to_path_buf ( ) ) ,
36
39
lib_search_paths : archive_search_paths ( sess) ,
40
+ // FIXME test for linux and System V derivatives instead
41
+ use_gnu_style_archive : !sess. target . target . options . is_like_osx ,
37
42
} ;
38
43
39
44
let ( src_archives, entries) = if let Some ( src) = & config. src {
40
45
let mut archive = ar:: Archive :: new ( File :: open ( src) . unwrap ( ) ) ;
41
- let mut entries = HashMap :: new ( ) ;
46
+ let mut entries = Vec :: new ( ) ;
42
47
43
48
let mut i = 0 ;
44
49
while let Some ( entry) = archive. next_entry ( ) {
45
50
let entry = entry. unwrap ( ) ;
46
- entries. insert (
51
+ entries. push ( (
47
52
String :: from_utf8 ( entry. header ( ) . identifier ( ) . to_vec ( ) ) . unwrap ( ) ,
48
53
ArchiveEntry :: FromArchive { archive_index : 0 , entry_index : i } ,
49
- ) ;
54
+ ) ) ;
50
55
i += 1 ;
51
56
}
52
57
53
58
( vec ! [ archive] , entries)
54
59
} else {
55
- ( vec ! [ ] , HashMap :: new ( ) )
60
+ ( vec ! [ ] , Vec :: new ( ) )
56
61
} ;
57
62
58
63
ArArchiveBuilder {
@@ -64,22 +69,22 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
64
69
}
65
70
66
71
fn src_files ( & mut self ) -> Vec < String > {
67
- self . entries . keys ( ) . cloned ( ) . collect ( )
72
+ self . entries . iter ( ) . map ( | ( name , _ ) | name . clone ( ) ) . collect ( )
68
73
}
69
74
70
75
fn remove_file ( & mut self , name : & str ) {
71
- let file = self . entries . remove ( name ) ;
72
- assert ! (
73
- file . is_some ( ) ,
74
- "Tried to remove file not existing in src archive" ,
75
- ) ;
76
+ let index = self . entries
77
+ . iter ( )
78
+ . position ( | ( entry_name , _ ) | entry_name == name )
79
+ . expect ( "Tried to remove file not existing in src archive" ) ;
80
+ self . entries . remove ( index ) ;
76
81
}
77
82
78
83
fn add_file ( & mut self , file : & Path ) {
79
- self . entries . insert (
84
+ self . entries . push ( (
80
85
file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ,
81
86
ArchiveEntry :: File ( File :: open ( file) . unwrap ( ) ) ,
82
- ) ;
87
+ ) ) ;
83
88
}
84
89
85
90
fn add_native_library ( & mut self , name : & str ) {
@@ -119,24 +124,44 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
119
124
}
120
125
121
126
fn build ( mut self ) {
122
- let mut builder = ar:: Builder :: new ( File :: create ( & self . config . dst ) . unwrap ( ) ) ;
127
+ enum BuilderKind {
128
+ Bsd ( ar:: Builder < File > ) ,
129
+ Gnu ( ar:: GnuBuilder < File > ) ,
130
+ }
131
+
132
+ let archive_file = File :: create ( & self . config . dst ) . unwrap ( ) ;
133
+ let mut builder = if self . config . use_gnu_style_archive {
134
+ BuilderKind :: Gnu ( ar:: GnuBuilder :: new (
135
+ archive_file,
136
+ self . entries . iter ( ) . map ( |( name, _) | name. as_bytes ( ) . to_vec ( ) ) . collect ( ) ,
137
+ ) )
138
+ } else {
139
+ BuilderKind :: Bsd ( ar:: Builder :: new ( archive_file) )
140
+ } ;
123
141
124
142
// Add all files
125
143
for ( entry_name, entry) in self . entries . into_iter ( ) {
126
144
match entry {
127
145
ArchiveEntry :: FromArchive { archive_index, entry_index } => {
128
146
let entry = self . src_archives [ archive_index] . jump_to_entry ( entry_index) . unwrap ( ) ;
129
147
let orig_header = entry. header ( ) ;
148
+
130
149
let mut header =
131
150
ar:: Header :: new ( orig_header. identifier ( ) . to_vec ( ) , orig_header. size ( ) ) ;
132
151
header. set_mtime ( orig_header. mtime ( ) ) ;
133
152
header. set_uid ( orig_header. uid ( ) ) ;
134
153
header. set_gid ( orig_header. gid ( ) ) ;
135
154
header. set_mode ( orig_header. mode ( ) ) ;
136
- builder. append ( & header, entry) . unwrap ( ) ;
155
+ match builder {
156
+ BuilderKind :: Bsd ( ref mut builder) => builder. append ( & header, entry) . unwrap ( ) ,
157
+ BuilderKind :: Gnu ( ref mut builder) => builder. append ( & header, entry) . unwrap ( ) ,
158
+ }
137
159
}
138
160
ArchiveEntry :: File ( mut file) => {
139
- builder. append_file ( entry_name. as_bytes ( ) , & mut file) . unwrap ( ) ;
161
+ match builder {
162
+ BuilderKind :: Bsd ( ref mut builder) => builder. append_file ( entry_name. as_bytes ( ) , & mut file) . unwrap ( ) ,
163
+ BuilderKind :: Gnu ( ref mut builder) => builder. append_file ( entry_name. as_bytes ( ) , & mut file) . unwrap ( ) ,
164
+ }
140
165
}
141
166
}
142
167
}
@@ -169,10 +194,10 @@ impl<'a> ArArchiveBuilder<'a> {
169
194
let entry = entry. unwrap ( ) ;
170
195
let file_name = String :: from_utf8 ( entry. header ( ) . identifier ( ) . to_vec ( ) ) . unwrap ( ) ;
171
196
if !skip ( & file_name) {
172
- self . entries . insert (
197
+ self . entries . push ( (
173
198
file_name,
174
199
ArchiveEntry :: FromArchive { archive_index, entry_index : i } ,
175
- ) ;
200
+ ) ) ;
176
201
}
177
202
i += 1 ;
178
203
}
0 commit comments