1
- //! Creation of ar archives like for the lib and staticlib crate type
2
-
3
- use std:: collections:: BTreeMap ;
4
- use std:: fs:: File ;
5
- use std:: io:: { self , Read , Seek } ;
6
1
use std:: path:: { Path , PathBuf } ;
7
2
8
- use rustc_codegen_ssa:: back:: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
3
+ use rustc_codegen_ssa:: back:: archive:: {
4
+ get_native_object_symbols, ArArchiveBuilder , ArchiveBuilder , ArchiveBuilderBuilder ,
5
+ } ;
9
6
use rustc_session:: Session ;
10
7
11
- use object:: read:: archive:: ArchiveFile ;
12
- use object:: { Object , ObjectSymbol , ReadCache } ;
13
-
14
- #[ derive( Debug ) ]
15
- enum ArchiveEntry {
16
- FromArchive { archive_index : usize , file_range : ( u64 , u64 ) } ,
17
- File ( PathBuf ) ,
18
- }
19
-
20
8
pub ( crate ) struct ArArchiveBuilderBuilder ;
21
9
22
10
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
23
11
fn new_archive_builder < ' a > ( & self , sess : & ' a Session ) -> Box < dyn ArchiveBuilder < ' a > + ' a > {
24
- Box :: new ( ArArchiveBuilder {
25
- sess,
26
- use_gnu_style_archive : sess. target . archive_format == "gnu" ,
27
- // FIXME fix builtin ranlib on macOS
28
- no_builtin_ranlib : sess. target . is_like_osx ,
29
-
30
- src_archives : vec ! [ ] ,
31
- entries : vec ! [ ] ,
32
- } )
12
+ Box :: new ( ArArchiveBuilder :: new ( sess, get_native_object_symbols) )
33
13
}
34
14
35
15
fn create_dll_import_lib (
@@ -40,200 +20,6 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
40
20
_tmpdir : & Path ,
41
21
_is_direct_dependency : bool ,
42
22
) -> PathBuf {
43
- bug ! ( "creating dll imports is not supported" ) ;
44
- }
45
- }
46
-
47
- pub ( crate ) struct ArArchiveBuilder < ' a > {
48
- sess : & ' a Session ,
49
- use_gnu_style_archive : bool ,
50
- no_builtin_ranlib : bool ,
51
-
52
- src_archives : Vec < File > ,
53
- // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
54
- // the end of an archive for linkers to not get confused.
55
- entries : Vec < ( Vec < u8 > , ArchiveEntry ) > ,
56
- }
57
-
58
- impl < ' a > ArchiveBuilder < ' a > for ArArchiveBuilder < ' a > {
59
- fn add_file ( & mut self , file : & Path ) {
60
- self . entries . push ( (
61
- file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_string ( ) . into_bytes ( ) ,
62
- ArchiveEntry :: File ( file. to_owned ( ) ) ,
63
- ) ) ;
64
- }
65
-
66
- fn add_archive (
67
- & mut self ,
68
- archive_path : & Path ,
69
- mut skip : Box < dyn FnMut ( & str ) -> bool + ' static > ,
70
- ) -> std:: io:: Result < ( ) > {
71
- let read_cache = ReadCache :: new ( std:: fs:: File :: open ( & archive_path) ?) ;
72
- let archive = ArchiveFile :: parse ( & read_cache) . unwrap ( ) ;
73
- let archive_index = self . src_archives . len ( ) ;
74
-
75
- for entry in archive. members ( ) {
76
- let entry = entry. map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
77
- let file_name = String :: from_utf8 ( entry. name ( ) . to_vec ( ) )
78
- . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
79
- if !skip ( & file_name) {
80
- self . entries . push ( (
81
- file_name. into_bytes ( ) ,
82
- ArchiveEntry :: FromArchive { archive_index, file_range : entry. file_range ( ) } ,
83
- ) ) ;
84
- }
85
- }
86
-
87
- self . src_archives . push ( read_cache. into_inner ( ) ) ;
88
- Ok ( ( ) )
89
- }
90
-
91
- fn build ( mut self : Box < Self > , output : & Path ) -> bool {
92
- enum BuilderKind {
93
- Bsd ( ar:: Builder < File > ) ,
94
- Gnu ( ar:: GnuBuilder < File > ) ,
95
- }
96
-
97
- let sess = self . sess ;
98
-
99
- let mut symbol_table = BTreeMap :: new ( ) ;
100
-
101
- let mut entries = Vec :: new ( ) ;
102
-
103
- for ( mut entry_name, entry) in self . entries {
104
- // FIXME only read the symbol table of the object files to avoid having to keep all
105
- // object files in memory at once, or read them twice.
106
- let data = match entry {
107
- ArchiveEntry :: FromArchive { archive_index, file_range } => {
108
- // FIXME read symbols from symtab
109
- let src_read_cache = & mut self . src_archives [ archive_index] ;
110
-
111
- src_read_cache. seek ( io:: SeekFrom :: Start ( file_range. 0 ) ) . unwrap ( ) ;
112
- let mut data = std:: vec:: from_elem ( 0 , usize:: try_from ( file_range. 1 ) . unwrap ( ) ) ;
113
- src_read_cache. read_exact ( & mut data) . unwrap ( ) ;
114
-
115
- data
116
- }
117
- ArchiveEntry :: File ( file) => std:: fs:: read ( file) . unwrap_or_else ( |err| {
118
- sess. fatal ( & format ! (
119
- "error while reading object file during archive building: {}" ,
120
- err
121
- ) ) ;
122
- } ) ,
123
- } ;
124
-
125
- if !self . no_builtin_ranlib {
126
- if symbol_table. contains_key ( & entry_name) {
127
- // The ar crate can't handle creating a symbol table in case of multiple archive
128
- // members with the same name. Work around this by prepending a number until we
129
- // get a unique name.
130
- for i in 1 .. {
131
- let new_name = format ! ( "{}_" , i)
132
- . into_bytes ( )
133
- . into_iter ( )
134
- . chain ( entry_name. iter ( ) . copied ( ) )
135
- . collect :: < Vec < _ > > ( ) ;
136
- if !symbol_table. contains_key ( & new_name) {
137
- entry_name = new_name;
138
- break ;
139
- }
140
- }
141
- }
142
-
143
- match object:: File :: parse ( & * data) {
144
- Ok ( object) => {
145
- symbol_table. insert (
146
- entry_name. to_vec ( ) ,
147
- object
148
- . symbols ( )
149
- . filter_map ( |symbol| {
150
- if symbol. is_undefined ( ) || symbol. is_local ( ) {
151
- None
152
- } else {
153
- symbol. name ( ) . map ( |name| name. as_bytes ( ) . to_vec ( ) ) . ok ( )
154
- }
155
- } )
156
- . collect :: < Vec < _ > > ( ) ,
157
- ) ;
158
- }
159
- Err ( err) => {
160
- let err = err. to_string ( ) ;
161
- if err == "Unknown file magic" {
162
- // Not an object file; skip it.
163
- } else if object:: read:: archive:: ArchiveFile :: parse ( & * data) . is_ok ( ) {
164
- // Nested archive file; skip it.
165
- } else {
166
- sess. fatal ( & format ! (
167
- "error parsing `{}` during archive creation: {}" ,
168
- String :: from_utf8_lossy( & entry_name) ,
169
- err
170
- ) ) ;
171
- }
172
- }
173
- }
174
- }
175
-
176
- entries. push ( ( entry_name, data) ) ;
177
- }
178
-
179
- let mut builder = if self . use_gnu_style_archive {
180
- BuilderKind :: Gnu (
181
- ar:: GnuBuilder :: new (
182
- File :: create ( output) . unwrap_or_else ( |err| {
183
- sess. fatal ( & format ! (
184
- "error opening destination during archive building: {}" ,
185
- err
186
- ) ) ;
187
- } ) ,
188
- entries. iter ( ) . map ( |( name, _) | name. clone ( ) ) . collect ( ) ,
189
- ar:: GnuSymbolTableFormat :: Size32 ,
190
- symbol_table,
191
- )
192
- . unwrap ( ) ,
193
- )
194
- } else {
195
- BuilderKind :: Bsd (
196
- ar:: Builder :: new (
197
- File :: create ( output) . unwrap_or_else ( |err| {
198
- sess. fatal ( & format ! (
199
- "error opening destination during archive building: {}" ,
200
- err
201
- ) ) ;
202
- } ) ,
203
- symbol_table,
204
- )
205
- . unwrap ( ) ,
206
- )
207
- } ;
208
-
209
- let any_members = !entries. is_empty ( ) ;
210
-
211
- // Add all files
212
- for ( entry_name, data) in entries. into_iter ( ) {
213
- let header = ar:: Header :: new ( entry_name, data. len ( ) as u64 ) ;
214
- match builder {
215
- BuilderKind :: Bsd ( ref mut builder) => builder. append ( & header, & mut & * data) . unwrap ( ) ,
216
- BuilderKind :: Gnu ( ref mut builder) => builder. append ( & header, & mut & * data) . unwrap ( ) ,
217
- }
218
- }
219
-
220
- // Finalize archive
221
- std:: mem:: drop ( builder) ;
222
-
223
- if self . no_builtin_ranlib {
224
- let ranlib = crate :: toolchain:: get_toolchain_binary ( self . sess , "ranlib" ) ;
225
-
226
- // Run ranlib to be able to link the archive
227
- let status = std:: process:: Command :: new ( ranlib)
228
- . arg ( output)
229
- . status ( )
230
- . expect ( "Couldn't run ranlib" ) ;
231
-
232
- if !status. success ( ) {
233
- self . sess . fatal ( & format ! ( "Ranlib exited with code {:?}" , status. code( ) ) ) ;
234
- }
235
- }
236
-
237
- any_members
23
+ unimplemented ! ( "creating dll imports is not yet supported" ) ;
238
24
}
239
25
}
0 commit comments