5353//! is a platform-defined dynamic library. Each library has a metadata somewhere
5454//! inside of it.
5555//!
56+ //! A third kind of dependency is an rmeta file. These are rlibs, which contain
57+ //! metadata, but no code. To a first approximation, these are treated in the
58+ //! same way as rlibs. Where there is both an rlib and an rmeta file, the rlib
59+ //! gets priority (even if the rmeta file is newer). An rmeta file is only
60+ //! useful for checking a downstream crate, attempting to link one will cause an
61+ //! error.
62+ //!
5663//! When translating a crate name to a crate on the filesystem, we all of a
5764//! sudden need to take into account both rlibs and dylibs! Linkage later on may
5865//! use either one of these files, as each has their pros/cons. The job of crate
@@ -275,33 +282,31 @@ pub struct CratePaths {
275282 pub ident : String ,
276283 pub dylib : Option < PathBuf > ,
277284 pub rlib : Option < PathBuf > ,
285+ pub rmeta : Option < PathBuf > ,
278286}
279287
280288pub const METADATA_FILENAME : & ' static str = "rust.metadata.bin" ;
281289
282290#[ derive( Copy , Clone , PartialEq ) ]
283291enum CrateFlavor {
284292 Rlib ,
293+ Rmeta ,
285294 Dylib ,
286295}
287296
288297impl fmt:: Display for CrateFlavor {
289298 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
290299 f. write_str ( match * self {
291300 CrateFlavor :: Rlib => "rlib" ,
301+ CrateFlavor :: Rmeta => "rmeta" ,
292302 CrateFlavor :: Dylib => "dylib" ,
293303 } )
294304 }
295305}
296306
297307impl CratePaths {
298308 fn paths ( & self ) -> Vec < PathBuf > {
299- match ( & self . dylib , & self . rlib ) {
300- ( & None , & None ) => vec ! [ ] ,
301- ( & Some ( ref p) , & None ) |
302- ( & None , & Some ( ref p) ) => vec ! [ p. clone( ) ] ,
303- ( & Some ( ref p1) , & Some ( ref p2) ) => vec ! [ p1. clone( ) , p2. clone( ) ] ,
304- }
309+ self . dylib . iter ( ) . chain ( self . rlib . iter ( ) ) . chain ( self . rmeta . iter ( ) ) . cloned ( ) . collect ( )
305310 }
306311}
307312
@@ -457,11 +462,13 @@ impl<'a> Context<'a> {
457462 None => return FileDoesntMatch ,
458463 Some ( file) => file,
459464 } ;
460- let ( hash, rlib) = if file. starts_with ( & rlib_prefix[ ..] ) && file. ends_with ( ".rlib" ) {
461- ( & file[ ( rlib_prefix. len ( ) ) ..( file. len ( ) - ".rlib" . len ( ) ) ] , true )
465+ let ( hash, found_kind) = if file. starts_with ( & rlib_prefix[ ..] ) && file. ends_with ( ".rlib" ) {
466+ ( & file[ ( rlib_prefix. len ( ) ) ..( file. len ( ) - ".rlib" . len ( ) ) ] , CrateFlavor :: Rlib )
467+ } else if file. starts_with ( & rlib_prefix[ ..] ) && file. ends_with ( ".rmeta" ) {
468+ ( & file[ ( rlib_prefix. len ( ) ) ..( file. len ( ) - ".rmeta" . len ( ) ) ] , CrateFlavor :: Rmeta )
462469 } else if file. starts_with ( & dylib_prefix) &&
463470 file. ends_with ( & dypair. 1 ) {
464- ( & file[ ( dylib_prefix. len ( ) ) ..( file. len ( ) - dypair. 1 . len ( ) ) ] , false )
471+ ( & file[ ( dylib_prefix. len ( ) ) ..( file. len ( ) - dypair. 1 . len ( ) ) ] , CrateFlavor :: Dylib )
465472 } else {
466473 if file. starts_with ( & staticlib_prefix[ ..] ) && file. ends_with ( & staticpair. 1 ) {
467474 staticlibs. push ( CrateMismatch {
@@ -475,14 +482,14 @@ impl<'a> Context<'a> {
475482
476483 let hash_str = hash. to_string ( ) ;
477484 let slot = candidates. entry ( hash_str)
478- . or_insert_with ( || ( FxHashMap ( ) , FxHashMap ( ) ) ) ;
479- let ( ref mut rlibs, ref mut dylibs) = * slot;
485+ . or_insert_with ( || ( FxHashMap ( ) , FxHashMap ( ) , FxHashMap ( ) ) ) ;
486+ let ( ref mut rlibs, ref mut rmetas , ref mut dylibs) = * slot;
480487 fs:: canonicalize ( path)
481488 . map ( |p| {
482- if rlib {
483- rlibs. insert ( p, kind) ;
484- } else {
485- dylibs. insert ( p, kind) ;
489+ match found_kind {
490+ CrateFlavor :: Rlib => { rlibs. insert ( p, kind) ; }
491+ CrateFlavor :: Rmeta => { rmetas . insert ( p , kind ) ; }
492+ CrateFlavor :: Dylib => { dylibs. insert ( p, kind) ; }
486493 }
487494 FileMatches
488495 } )
@@ -499,15 +506,17 @@ impl<'a> Context<'a> {
499506 // libraries corresponds to the crate id and hash criteria that this
500507 // search is being performed for.
501508 let mut libraries = FxHashMap ( ) ;
502- for ( _hash, ( rlibs, dylibs) ) in candidates {
509+ for ( _hash, ( rlibs, rmetas , dylibs) ) in candidates {
503510 let mut slot = None ;
504511 let rlib = self . extract_one ( rlibs, CrateFlavor :: Rlib , & mut slot) ;
512+ let rmeta = self . extract_one ( rmetas, CrateFlavor :: Rmeta , & mut slot) ;
505513 let dylib = self . extract_one ( dylibs, CrateFlavor :: Dylib , & mut slot) ;
506514 if let Some ( ( h, m) ) = slot {
507515 libraries. insert ( h,
508516 Library {
509517 dylib : dylib,
510518 rlib : rlib,
519+ rmeta : rmeta,
511520 metadata : m,
512521 } ) ;
513522 }
@@ -703,6 +712,7 @@ impl<'a> Context<'a> {
703712 let sess = self . sess ;
704713 let dylibname = self . dylibname ( ) ;
705714 let mut rlibs = FxHashMap ( ) ;
715+ let mut rmetas = FxHashMap ( ) ;
706716 let mut dylibs = FxHashMap ( ) ;
707717 {
708718 let locs = locs. map ( |l| PathBuf :: from ( l) ) . filter ( |loc| {
@@ -744,6 +754,8 @@ impl<'a> Context<'a> {
744754 for loc in locs {
745755 if loc. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . ends_with ( ".rlib" ) {
746756 rlibs. insert ( fs:: canonicalize ( & loc) . unwrap ( ) , PathKind :: ExternFlag ) ;
757+ } else if loc. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . ends_with ( ".rmeta" ) {
758+ rmetas. insert ( fs:: canonicalize ( & loc) . unwrap ( ) , PathKind :: ExternFlag ) ;
747759 } else {
748760 dylibs. insert ( fs:: canonicalize ( & loc) . unwrap ( ) , PathKind :: ExternFlag ) ;
749761 }
@@ -753,16 +765,18 @@ impl<'a> Context<'a> {
753765 // Extract the rlib/dylib pair.
754766 let mut slot = None ;
755767 let rlib = self . extract_one ( rlibs, CrateFlavor :: Rlib , & mut slot) ;
768+ let rmeta = self . extract_one ( rmetas, CrateFlavor :: Rmeta , & mut slot) ;
756769 let dylib = self . extract_one ( dylibs, CrateFlavor :: Dylib , & mut slot) ;
757770
758- if rlib. is_none ( ) && dylib. is_none ( ) {
771+ if rlib. is_none ( ) && rmeta . is_none ( ) && dylib. is_none ( ) {
759772 return None ;
760773 }
761774 match slot {
762775 Some ( ( _, metadata) ) => {
763776 Some ( Library {
764777 dylib : dylib,
765778 rlib : rlib,
779+ rmeta : rmeta,
766780 metadata : metadata,
767781 } )
768782 }
@@ -832,7 +846,7 @@ fn get_metadata_section_imp(target: &Target,
832846 if !filename. exists ( ) {
833847 return Err ( format ! ( "no such file: '{}'" , filename. display( ) ) ) ;
834848 }
835- if flavor == CrateFlavor :: Rlib {
849+ if flavor == CrateFlavor :: Rlib || flavor == CrateFlavor :: Rmeta {
836850 // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
837851 // internally to read the file. We also avoid even using a memcpy by
838852 // just keeping the archive along while the metadata is in use.
@@ -933,6 +947,8 @@ pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) ->
933947 let filename = path. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
934948 let flavor = if filename. ends_with ( ".rlib" ) {
935949 CrateFlavor :: Rlib
950+ } else if filename. ends_with ( ".rmeta" ) {
951+ CrateFlavor :: Rmeta
936952 } else {
937953 CrateFlavor :: Dylib
938954 } ;
0 commit comments