1
- // Extracting metadata from crate files
1
+ #[ doc = "
2
+
3
+ Validates all used crates and native libraries and loads their metadata
4
+
5
+ " ] ;
2
6
3
7
import driver:: session;
4
8
import session:: session;
5
9
import syntax:: { ast, ast_util} ;
6
- import lib:: llvm:: { False , llvm, mk_object_file, mk_section_iter} ;
7
10
import syntax:: attr;
8
11
import syntax:: visit;
9
12
import syntax:: codemap:: span;
10
- import util :: { filesearch} ;
11
- import io:: writer_util;
12
13
import std:: map:: { hashmap, int_hash} ;
13
14
import syntax:: print:: pprust;
14
15
import common:: * ;
15
16
16
17
export read_crates;
17
- export list_file_metadata;
18
18
19
19
// Traverses an AST, reading all the information about use'd crates and native
20
20
// libraries necessary for later resolving, typechecking, linking, etc.
@@ -59,10 +59,10 @@ fn warn_if_multiple_versions(sess: session::session,
59
59
import either:: * ;
60
60
61
61
if crate_cache. is_not_empty( ) {
62
- let name = crate_name_from_metas( * crate_cache. last( ) . metas) ;
62
+ let name = loader :: crate_name_from_metas( * crate_cache. last( ) . metas) ;
63
63
let { lefts: matches, rights: non_matches} =
64
64
partition( crate_cache. map { |entry|
65
- let othername = crate_name_from_metas( * entry. metas) ;
65
+ let othername = loader :: crate_name_from_metas( * entry. metas) ;
66
66
if name == othername {
67
67
left( entry)
68
68
} else {
@@ -79,7 +79,7 @@ fn warn_if_multiple_versions(sess: session::session,
79
79
let attrs = [
80
80
attr:: mk_attr( attr:: mk_list_item( "link" , * match . metas) )
81
81
] ;
82
- note_linkage_attrs( sess, attrs) ;
82
+ loader :: note_linkage_attrs( sess, attrs) ;
83
83
}
84
84
}
85
85
@@ -148,195 +148,6 @@ fn visit_item(e: env, i: @ast::item) {
148
148
}
149
149
}
150
150
151
- // A diagnostic function for dumping crate metadata to an output stream
152
- fn list_file_metadata( sess: session:: session, path: str , out: io:: writer) {
153
- alt get_metadata_section( sess, path) {
154
- option:: some( bytes) { decoder:: list_crate_metadata( bytes, out) ; }
155
- option:: none {
156
- out. write_str( "could not find metadata in " + path + " . \n ") ;
157
- }
158
- }
159
- }
160
-
161
- fn crate_matches ( crate_data: @[ u8] , metas: [ @ast:: meta_item] , hash: str ) ->
162
- bool {
163
- let attrs = decoder:: get_crate_attributes ( crate_data) ;
164
- let linkage_metas = attr:: find_linkage_metas ( attrs) ;
165
- if hash. is_not_empty ( ) {
166
- let chash = decoder:: get_crate_hash ( crate_data) ;
167
- if chash != hash { ret false ; }
168
- }
169
- metadata_matches ( linkage_metas, metas)
170
- }
171
-
172
- fn metadata_matches ( extern_metas : [ @ast:: meta_item ] ,
173
- local_metas : [ @ast:: meta_item ] ) -> bool {
174
-
175
- #debug ( "matching %u metadata requirements against %u items" ,
176
- vec:: len ( local_metas) , vec:: len ( extern_metas) ) ;
177
-
178
- #debug ( "crate metadata:" ) ;
179
- for extern_metas. each { |have|
180
- #debug( " %s" , pprust:: meta_item_to_str( * have) ) ;
181
- }
182
-
183
- for local_metas. each { |needed|
184
- #debug( "looking for %s" , pprust:: meta_item_to_str( * needed) ) ;
185
- if !attr:: contains ( extern_metas, needed) {
186
- #debug ( "missing %s" , pprust:: meta_item_to_str ( * needed) ) ;
187
- ret false ;
188
- }
189
- }
190
- ret true;
191
- }
192
-
193
- fn default_native_lib_naming ( sess : session:: session , static : bool ) ->
194
- { prefix : str , suffix : str } {
195
- if static { ret { prefix : "lib" , suffix : ".rlib" } ; }
196
- alt sess. targ_cfg . os {
197
- session:: os_win32 { ret { prefix : "" , suffix : ".dll" } ; }
198
- session:: os_macos { ret { prefix : "lib" , suffix : ".dylib" } ; }
199
- session:: os_linux { ret { prefix : "lib" , suffix : ".so" } ; }
200
- session:: os_freebsd { ret { prefix : "lib" , suffix : ".so" } ; }
201
- }
202
- }
203
-
204
- fn crate_name_from_metas( metas: [ @ast:: meta_item] ) -> str {
205
- let name_items = attr:: find_meta_items_by_name ( metas, "name" ) ;
206
- alt vec:: last_opt ( name_items) {
207
- some ( i) {
208
- alt attr:: get_meta_item_value_str ( i) {
209
- some ( n) { n }
210
- // FIXME: Probably want a warning here since the user
211
- // is using the wrong type of meta item
212
- _ { fail }
213
- }
214
- }
215
- none { fail "expected to find the crate name" }
216
- }
217
- }
218
-
219
- fn find_library_crate ( sess : session:: session , span : span ,
220
- metas : [ @ast:: meta_item ] , hash : str )
221
- -> option < { ident: str , data : @[ u8 ] } > {
222
-
223
- attr:: require_unique_names ( sess. diagnostic ( ) , metas) ;
224
- let metas = metas;
225
-
226
- let nn = default_native_lib_naming ( sess, sess. opts . static ) ;
227
- let x =
228
- find_library_crate_aux ( sess, span, nn,
229
- metas, hash, sess. filesearch ) ;
230
- if x != none || sess. opts . static { ret x; }
231
- let nn2 = default_native_lib_naming ( sess, true ) ;
232
- ret find_library_crate_aux ( sess, span, nn2, metas, hash,
233
- sess. filesearch ) ;
234
- }
235
-
236
- fn find_library_crate_aux ( sess : session:: session ,
237
- span : span ,
238
- nn : { prefix : str , suffix : str } ,
239
- metas : [ @ast:: meta_item ] ,
240
- hash : str ,
241
- filesearch : filesearch:: filesearch ) ->
242
- option < { ident: str , data : @[ u8 ] } > {
243
- let crate_name = crate_name_from_metas ( metas) ;
244
- let prefix: str = nn. prefix + crate_name + "-" ;
245
- let suffix: str = nn. suffix ;
246
-
247
- let mut matches = [ ] ;
248
- filesearch:: search ( filesearch, { |path|
249
- #debug ( "inspecting file %s" , path) ;
250
- let f: str = path:: basename ( path) ;
251
- if !( str:: starts_with ( f, prefix) && str:: ends_with ( f, suffix) ) {
252
- #debug ( "skipping %s, doesn't look like %s*%s" , path, prefix,
253
- suffix) ;
254
- option:: none :: < ( ) >
255
- } else {
256
- #debug ( "%s is a candidate" , path) ;
257
- alt get_metadata_section ( sess, path) {
258
- option:: some ( cvec) {
259
- if !crate_matches ( cvec, metas, hash) {
260
- #debug ( "skipping %s, metadata doesn't match" , path) ;
261
- option:: none :: < ( ) >
262
- } else {
263
- #debug ( "found %s with matching metadata" , path) ;
264
- matches += [ { ident: path, data: cvec} ] ;
265
- option:: none :: < ( ) >
266
- }
267
- }
268
- _ {
269
- #debug( "could not load metadata for %s" , path) ;
270
- option:: none :: < ( ) >
271
- }
272
- }
273
- }
274
- } ) ;
275
-
276
- if matches. is_empty ( ) {
277
- none
278
- } else if matches. len ( ) == 1 u {
279
- some ( matches[ 0 ] )
280
- } else {
281
- sess. span_err (
282
- span, #fmt ( "multiple matching crates for `%s`" , crate_name) ) ;
283
- sess. note ( "candidates:" ) ;
284
- for matches. each { |match|
285
- sess. note( #fmt( "path: %s" , match. ident) ) ;
286
- let attrs = decoder:: get_crate_attributes( match . data) ;
287
- note_linkage_attrs ( sess, attrs) ;
288
- }
289
- sess. abort_if_errors ( ) ;
290
- none
291
- }
292
- }
293
-
294
- fn note_linkage_attrs ( sess : session:: session , attrs : [ ast:: attribute ] ) {
295
- for attr:: find_linkage_attrs( attrs) . each { |attr|
296
- sess. note( #fmt( "meta: %s" , pprust:: attr_to_str( attr) ) ) ;
297
- }
298
- }
299
-
300
- fn get_metadata_section ( sess : session:: session ,
301
- filename : str ) -> option < @[ u8 ] > unsafe {
302
- let mb = str:: as_c_str ( filename, { |buf|
303
- llvm:: LLVMRustCreateMemoryBufferWithContentsOfFile ( buf)
304
- } ) ;
305
- if mb as int == 0 { ret option:: none :: < @[ u8 ] > ; }
306
- let of = alt mk_object_file ( mb) {
307
- option:: some ( of) { of }
308
- _ { ret option:: none :: < @[ u8 ] > ; }
309
- } ;
310
- let si = mk_section_iter ( of. llof ) ;
311
- while llvm:: LLVMIsSectionIteratorAtEnd ( of. llof , si. llsi ) == False {
312
- let name_buf = llvm:: LLVMGetSectionName ( si. llsi ) ;
313
- let name = unsafe { str:: unsafe:: from_c_str ( name_buf) } ;
314
- if str:: eq ( name, sess. targ_cfg . target_strs . meta_sect_name ) {
315
- let cbuf = llvm:: LLVMGetSectionContents ( si. llsi ) ;
316
- let csz = llvm:: LLVMGetSectionSize ( si. llsi ) as uint ;
317
- unsafe {
318
- let cvbuf: * u8 = unsafe :: reinterpret_cast ( cbuf) ;
319
- ret some( @vec:: unsafe:: from_buf ( cvbuf, csz) ) ;
320
- }
321
- }
322
- llvm:: LLVMMoveToNextSection ( si. llsi ) ;
323
- }
324
- ret option:: none :: < @[ u8 ] > ;
325
- }
326
-
327
- fn load_library_crate ( sess : session:: session , ident : ast:: ident , span : span ,
328
- metas : [ @ast:: meta_item ] , hash : str )
329
- -> { ident: str , data: @[ u8] } {
330
-
331
-
332
- alt find_library_crate ( sess, span, metas, hash) {
333
- some ( t) { ret t; }
334
- none {
335
- sess. span_fatal ( span, #fmt[ "can't find crate for '%s'" , ident] ) ;
336
- }
337
- }
338
- }
339
-
340
151
fn metas_with( ident: ast:: ident, key: str ,
341
152
metas: [ @ast:: meta_item] ) -> [ @ast:: meta_item] {
342
153
let name_items = attr:: find_meta_items_by_name( metas, key) ;
@@ -355,7 +166,7 @@ fn metas_with_ident(ident: ast::ident,
355
166
fn existing_match( e: env, metas: [ @ast:: meta_item] , hash: str ) ->
356
167
option<int> {
357
168
let maybe_entry = e. crate_cache. find { |c|
358
- metadata_matches ( * c. metas , metas) &&
169
+ loader :: metadata_matches( * c. metas, metas) &&
359
170
( hash. is_empty( ) || c. hash == hash)
360
171
} ;
361
172
@@ -369,7 +180,7 @@ fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
369
180
alt existing_match( e, metas, hash) {
370
181
none {
371
182
let cinfo =
372
- load_library_crate ( e. sess , ident, span, metas, hash) ;
183
+ loader :: load_library_crate( e. sess, ident, span, metas, hash) ;
373
184
374
185
let cfilename = cinfo. ident;
375
186
let cdata = cinfo. data;
0 commit comments