@@ -20,6 +20,7 @@ use metadata::cstore::{CStore, CrateSource, MetadataBlob};
20
20
use metadata:: decoder;
21
21
use metadata:: loader;
22
22
use metadata:: loader:: CratePaths ;
23
+ use util:: nodemap:: FnvHashMap ;
23
24
24
25
use std:: cell:: RefCell ;
25
26
use std:: path:: PathBuf ;
@@ -47,6 +48,7 @@ pub struct LocalCrateReader<'a, 'b:'a> {
47
48
pub struct CrateReader < ' a > {
48
49
sess : & ' a Session ,
49
50
next_crate_num : ast:: CrateNum ,
51
+ foreign_item_map : FnvHashMap < String , Vec < ast:: NodeId > > ,
50
52
}
51
53
52
54
impl < ' a , ' b , ' v > visit:: Visitor < ' v > for LocalCrateReader < ' a , ' b > {
@@ -157,6 +159,7 @@ impl<'a> CrateReader<'a> {
157
159
CrateReader {
158
160
sess : sess,
159
161
next_crate_num : sess. cstore . next_crate_num ( ) ,
162
+ foreign_item_map : FnvHashMap ( ) ,
160
163
}
161
164
}
162
165
@@ -490,6 +493,20 @@ impl<'a> CrateReader<'a> {
490
493
_ => None ,
491
494
}
492
495
}
496
+
497
+ fn register_statically_included_foreign_items ( & mut self ) {
498
+ let libs = self . sess . cstore . get_used_libraries ( ) ;
499
+ for ( lib, list) in self . foreign_item_map . iter ( ) {
500
+ let is_static = libs. borrow ( ) . iter ( ) . any ( |& ( ref name, kind) | {
501
+ lib == name && kind == cstore:: NativeStatic
502
+ } ) ;
503
+ if is_static {
504
+ for id in list {
505
+ self . sess . cstore . add_statically_included_foreign_item ( * id) ;
506
+ }
507
+ }
508
+ }
509
+ }
493
510
}
494
511
495
512
impl < ' a , ' b > LocalCrateReader < ' a , ' b > {
@@ -515,6 +532,7 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
515
532
for & ( ref name, kind) in & self . sess . opts . libs {
516
533
register_native_lib ( self . sess , None , name. clone ( ) , kind) ;
517
534
}
535
+ self . creader . register_statically_included_foreign_items ( ) ;
518
536
}
519
537
520
538
fn process_crate ( & self , c : & ast:: Crate ) {
@@ -541,87 +559,73 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
541
559
None ,
542
560
i. span ,
543
561
PathKind :: Crate ) ;
544
- self . ast_map . with_path ( i. id , |path|
545
- cmeta. update_local_path ( path) ) ;
562
+ self . ast_map . with_path ( i. id , |path| {
563
+ cmeta. update_local_path ( path)
564
+ } ) ;
546
565
self . sess . cstore . add_extern_mod_stmt_cnum ( info. id , cnum) ;
547
566
}
548
567
None => ( )
549
568
}
550
569
}
551
- ast:: ItemForeignMod ( ref fm) => {
552
- if fm . abi == abi :: Rust || fm . abi == abi :: RustIntrinsic {
553
- return ;
554
- }
570
+ ast:: ItemForeignMod ( ref fm) => self . process_foreign_mod ( i , fm ) ,
571
+ _ => { }
572
+ }
573
+ }
555
574
556
- // First, add all of the custom link_args attributes
557
- let link_args = i. attrs . iter ( )
558
- . filter_map ( |at| if at. name ( ) == "link_args" {
559
- Some ( at)
560
- } else {
561
- None
562
- } )
563
- . collect :: < Vec < & ast:: Attribute > > ( ) ;
564
- for m in & link_args {
565
- match m. value_str ( ) {
566
- Some ( linkarg) => self . sess . cstore . add_used_link_args ( & linkarg) ,
567
- None => { /* fallthrough */ }
568
- }
569
- }
575
+ fn process_foreign_mod ( & mut self , i : & ast:: Item , fm : & ast:: ForeignMod ) {
576
+ if fm. abi == abi:: Rust || fm. abi == abi:: RustIntrinsic {
577
+ return ;
578
+ }
570
579
571
- // Next, process all of the #[link(..)]-style arguments
572
- let link_args = i. attrs . iter ( )
573
- . filter_map ( |at| if at. name ( ) == "link" {
574
- Some ( at)
575
- } else {
576
- None
577
- } )
578
- . collect :: < Vec < & ast:: Attribute > > ( ) ;
579
- for m in & link_args {
580
- match m. meta_item_list ( ) {
581
- Some ( items) => {
582
- let kind = items. iter ( ) . find ( |k| {
583
- k. name ( ) == "kind"
584
- } ) . and_then ( |a| a. value_str ( ) ) ;
585
- let kind = match kind {
586
- Some ( k) => {
587
- if k == "static" {
588
- cstore:: NativeStatic
589
- } else if self . sess . target . target . options . is_like_osx
590
- && k == "framework" {
591
- cstore:: NativeFramework
592
- } else if k == "framework" {
593
- cstore:: NativeFramework
594
- } else if k == "dylib" {
595
- cstore:: NativeUnknown
596
- } else {
597
- self . sess . span_err ( m. span ,
598
- & format ! ( "unknown kind: `{}`" ,
599
- k) ) ;
600
- cstore:: NativeUnknown
601
- }
602
- }
603
- None => cstore:: NativeUnknown
604
- } ;
605
- let n = items. iter ( ) . find ( |n| {
606
- n. name ( ) == "name"
607
- } ) . and_then ( |a| a. value_str ( ) ) ;
608
- let n = match n {
609
- Some ( n) => n,
610
- None => {
611
- self . sess . span_err ( m. span ,
612
- "#[link(...)] specified without \
613
- `name = \" foo\" `") ;
614
- InternedString :: new ( "foo" )
615
- }
616
- } ;
617
- register_native_lib ( self . sess , Some ( m. span ) ,
618
- n. to_string ( ) , kind) ;
619
- }
620
- None => { }
621
- }
622
- }
580
+ // First, add all of the custom #[link_args] attributes
581
+ for m in i. attrs . iter ( ) . filter ( |a| a. check_name ( "link_args" ) ) {
582
+ if let Some ( linkarg) = m. value_str ( ) {
583
+ self . sess . cstore . add_used_link_args ( & linkarg) ;
623
584
}
624
- _ => { }
585
+ }
586
+
587
+ // Next, process all of the #[link(..)]-style arguments
588
+ for m in i. attrs . iter ( ) . filter ( |a| a. check_name ( "link" ) ) {
589
+ let items = match m. meta_item_list ( ) {
590
+ Some ( item) => item,
591
+ None => continue ,
592
+ } ;
593
+ let kind = items. iter ( ) . find ( |k| {
594
+ k. check_name ( "kind" )
595
+ } ) . and_then ( |a| a. value_str ( ) ) ;
596
+ let kind = match kind. as_ref ( ) . map ( |s| & s[ ..] ) {
597
+ Some ( "static" ) => cstore:: NativeStatic ,
598
+ Some ( "dylib" ) => cstore:: NativeUnknown ,
599
+ Some ( "framework" ) => cstore:: NativeFramework ,
600
+ Some ( k) => {
601
+ self . sess . span_err ( m. span , & format ! ( "unknown kind: `{}`" , k) ) ;
602
+ cstore:: NativeUnknown
603
+ }
604
+ None => cstore:: NativeUnknown
605
+ } ;
606
+ let n = items. iter ( ) . find ( |n| {
607
+ n. check_name ( "name" )
608
+ } ) . and_then ( |a| a. value_str ( ) ) ;
609
+ let n = match n {
610
+ Some ( n) => n,
611
+ None => {
612
+ self . sess . span_err ( m. span , "#[link(...)] specified without \
613
+ `name = \" foo\" `") ;
614
+ InternedString :: new ( "foo" )
615
+ }
616
+ } ;
617
+ register_native_lib ( self . sess , Some ( m. span ) , n. to_string ( ) , kind) ;
618
+ }
619
+
620
+ // Finally, process the #[linked_from = "..."] attribute
621
+ for m in i. attrs . iter ( ) . filter ( |a| a. check_name ( "linked_from" ) ) {
622
+ let lib_name = match m. value_str ( ) {
623
+ Some ( name) => name,
624
+ None => continue ,
625
+ } ;
626
+ let list = self . creader . foreign_item_map . entry ( lib_name. to_string ( ) )
627
+ . or_insert ( Vec :: new ( ) ) ;
628
+ list. extend ( fm. items . iter ( ) . map ( |it| it. id ) ) ;
625
629
}
626
630
}
627
631
}
0 commit comments