1
- use std:: collections:: HashMap ;
2
1
use std:: fs:: File ;
3
2
use std:: path:: { Path , PathBuf } ;
4
3
@@ -24,7 +23,9 @@ enum ArchiveEntry {
24
23
pub struct ArArchiveBuilder < ' a > {
25
24
config : ArchiveConfig < ' a > ,
26
25
src_archives : Vec < ar:: Archive < File > > ,
27
- 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 ) > ,
28
29
update_symbols : bool ,
29
30
}
30
31
@@ -42,21 +43,21 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
42
43
43
44
let ( src_archives, entries) = if let Some ( src) = & config. src {
44
45
let mut archive = ar:: Archive :: new ( File :: open ( src) . unwrap ( ) ) ;
45
- let mut entries = HashMap :: new ( ) ;
46
+ let mut entries = Vec :: new ( ) ;
46
47
47
48
let mut i = 0 ;
48
49
while let Some ( entry) = archive. next_entry ( ) {
49
50
let entry = entry. unwrap ( ) ;
50
- entries. insert (
51
+ entries. push ( (
51
52
String :: from_utf8 ( entry. header ( ) . identifier ( ) . to_vec ( ) ) . unwrap ( ) ,
52
53
ArchiveEntry :: FromArchive { archive_index : 0 , entry_index : i } ,
53
- ) ;
54
+ ) ) ;
54
55
i += 1 ;
55
56
}
56
57
57
58
( vec ! [ archive] , entries)
58
59
} else {
59
- ( vec ! [ ] , HashMap :: new ( ) )
60
+ ( vec ! [ ] , Vec :: new ( ) )
60
61
} ;
61
62
62
63
ArArchiveBuilder {
@@ -68,22 +69,22 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
68
69
}
69
70
70
71
fn src_files ( & mut self ) -> Vec < String > {
71
- self . entries . keys ( ) . cloned ( ) . collect ( )
72
+ self . entries . iter ( ) . map ( | ( name , _ ) | name . clone ( ) ) . collect ( )
72
73
}
73
74
74
75
fn remove_file ( & mut self , name : & str ) {
75
- let file = self . entries . remove ( name ) ;
76
- assert ! (
77
- file . is_some ( ) ,
78
- "Tried to remove file not existing in src archive" ,
79
- ) ;
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 ) ;
80
81
}
81
82
82
83
fn add_file ( & mut self , file : & Path ) {
83
- self . entries . insert (
84
+ self . entries . push ( (
84
85
file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ,
85
86
ArchiveEntry :: File ( File :: open ( file) . unwrap ( ) ) ,
86
- ) ;
87
+ ) ) ;
87
88
}
88
89
89
90
fn add_native_library ( & mut self , name : & str ) {
@@ -132,7 +133,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
132
133
let mut builder = if self . config . use_gnu_style_archive {
133
134
BuilderKind :: Gnu ( ar:: GnuBuilder :: new (
134
135
archive_file,
135
- self . entries . keys ( ) . map ( |key| key . as_bytes ( ) . to_vec ( ) ) . collect ( ) ,
136
+ self . entries . iter ( ) . map ( |( name , _ ) | name . as_bytes ( ) . to_vec ( ) ) . collect ( ) ,
136
137
) )
137
138
} else {
138
139
BuilderKind :: Bsd ( ar:: Builder :: new ( archive_file) )
@@ -193,10 +194,10 @@ impl<'a> ArArchiveBuilder<'a> {
193
194
let entry = entry. unwrap ( ) ;
194
195
let file_name = String :: from_utf8 ( entry. header ( ) . identifier ( ) . to_vec ( ) ) . unwrap ( ) ;
195
196
if !skip ( & file_name) {
196
- self . entries . insert (
197
+ self . entries . push ( (
197
198
file_name,
198
199
ArchiveEntry :: FromArchive { archive_index, entry_index : i } ,
199
- ) ;
200
+ ) ) ;
200
201
}
201
202
i += 1 ;
202
203
}
0 commit comments