@@ -15,13 +15,50 @@ use std::io::prelude::*;
1515use std:: path:: { Path , PathBuf } ;
1616use std:: process:: Command ;
1717
18+ use context:: SharedCrateContext ;
19+ use monomorphize:: Instance ;
20+
1821use back:: archive;
1922use middle:: dependency_format:: Linkage ;
2023use session:: Session ;
2124use session:: config:: CrateType ;
2225use session:: config;
2326use syntax:: ast;
24- use CrateTranslation ;
27+
28+ /// For all the linkers we support, and information they might
29+ /// need out of the shared crate context before we get rid of it.
30+ pub struct LinkerInfo {
31+ dylib_exports : Vec < String > ,
32+ cdylib_exports : Vec < String >
33+ }
34+
35+ impl < ' a , ' tcx > LinkerInfo {
36+ pub fn new ( scx : & SharedCrateContext < ' a , ' tcx > ,
37+ reachable : & [ String ] ) -> LinkerInfo {
38+ LinkerInfo {
39+ dylib_exports : exported_symbols ( scx, reachable, CrateType :: CrateTypeDylib ) ,
40+ cdylib_exports : exported_symbols ( scx, reachable, CrateType :: CrateTypeCdylib )
41+ }
42+ }
43+
44+ pub fn to_linker ( & ' a self ,
45+ cmd : & ' a mut Command ,
46+ sess : & ' a Session ) -> Box < Linker +' a > {
47+ if sess. target . target . options . is_like_msvc {
48+ Box :: new ( MsvcLinker {
49+ cmd : cmd,
50+ sess : sess,
51+ info : self
52+ } ) as Box < Linker >
53+ } else {
54+ Box :: new ( GnuLinker {
55+ cmd : cmd,
56+ sess : sess,
57+ info : self
58+ } ) as Box < Linker >
59+ }
60+ }
61+ }
2562
2663/// Linker abstraction used by back::link to build up the command to invoke a
2764/// linker.
@@ -53,16 +90,13 @@ pub trait Linker {
5390 fn hint_dynamic ( & mut self ) ;
5491 fn whole_archives ( & mut self ) ;
5592 fn no_whole_archives ( & mut self ) ;
56- fn export_symbols ( & mut self ,
57- sess : & Session ,
58- trans : & CrateTranslation ,
59- tmpdir : & Path ,
60- crate_type : CrateType ) ;
93+ fn export_symbols ( & mut self , tmpdir : & Path , crate_type : CrateType ) ;
6194}
6295
6396pub struct GnuLinker < ' a > {
64- pub cmd : & ' a mut Command ,
65- pub sess : & ' a Session ,
97+ cmd : & ' a mut Command ,
98+ sess : & ' a Session ,
99+ info : & ' a LinkerInfo
66100}
67101
68102impl < ' a > GnuLinker < ' a > {
@@ -201,11 +235,7 @@ impl<'a> Linker for GnuLinker<'a> {
201235 self . cmd . arg ( "-Wl,-Bdynamic" ) ;
202236 }
203237
204- fn export_symbols ( & mut self ,
205- sess : & Session ,
206- trans : & CrateTranslation ,
207- tmpdir : & Path ,
208- crate_type : CrateType ) {
238+ fn export_symbols ( & mut self , tmpdir : & Path , crate_type : CrateType ) {
209239 // If we're compiling a dylib, then we let symbol visibility in object
210240 // files to take care of whether they're exported or not.
211241 //
@@ -225,13 +255,13 @@ impl<'a> Linker for GnuLinker<'a> {
225255 } ;
226256 let res = ( || -> io:: Result < ( ) > {
227257 let mut f = BufWriter :: new ( File :: create ( & path) ?) ;
228- for sym in exported_symbols ( sess , trans , crate_type ) {
258+ for sym in & self . info . cdylib_exports {
229259 writeln ! ( f, "{}{}" , prefix, sym) ?;
230260 }
231261 Ok ( ( ) )
232262 } ) ( ) ;
233263 if let Err ( e) = res {
234- sess. fatal ( & format ! ( "failed to write lib.def file: {}" , e) ) ;
264+ self . sess . fatal ( & format ! ( "failed to write lib.def file: {}" , e) ) ;
235265 }
236266 let mut arg = OsString :: new ( ) ;
237267 if self . sess . target . target . options . is_like_osx {
@@ -245,8 +275,9 @@ impl<'a> Linker for GnuLinker<'a> {
245275}
246276
247277pub struct MsvcLinker < ' a > {
248- pub cmd : & ' a mut Command ,
249- pub sess : & ' a Session ,
278+ cmd : & ' a mut Command ,
279+ sess : & ' a Session ,
280+ info : & ' a LinkerInfo
250281}
251282
252283impl < ' a > Linker for MsvcLinker < ' a > {
@@ -366,8 +397,6 @@ impl<'a> Linker for MsvcLinker<'a> {
366397 // in which case they may continue to transitively be used and hence need
367398 // their symbols exported.
368399 fn export_symbols ( & mut self ,
369- sess : & Session ,
370- trans : & CrateTranslation ,
371400 tmpdir : & Path ,
372401 crate_type : CrateType ) {
373402 let path = tmpdir. join ( "lib.def" ) ;
@@ -378,26 +407,42 @@ impl<'a> Linker for MsvcLinker<'a> {
378407 // straight to exports.
379408 writeln ! ( f, "LIBRARY" ) ?;
380409 writeln ! ( f, "EXPORTS" ) ?;
381-
382- for sym in exported_symbols ( sess, trans, crate_type) {
383- writeln ! ( f, " {}" , sym) ?;
410+ let symbols = if crate_type == CrateType :: CrateTypeCdylib {
411+ & self . info . cdylib_exports
412+ } else {
413+ & self . info . dylib_exports
414+ } ;
415+ for symbol in symbols {
416+ writeln ! ( f, " {}" , symbol) ?;
384417 }
385-
386418 Ok ( ( ) )
387419 } ) ( ) ;
388420 if let Err ( e) = res {
389- sess. fatal ( & format ! ( "failed to write lib.def file: {}" , e) ) ;
421+ self . sess . fatal ( & format ! ( "failed to write lib.def file: {}" , e) ) ;
390422 }
391423 let mut arg = OsString :: from ( "/DEF:" ) ;
392424 arg. push ( path) ;
393425 self . cmd . arg ( & arg) ;
394426 }
395427}
396428
397- fn exported_symbols ( sess : & Session ,
398- trans : & CrateTranslation ,
399- crate_type : CrateType ) -> Vec < String > {
400- let mut symbols = trans. reachable . iter ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) ;
429+ fn exported_symbols ( scx : & SharedCrateContext ,
430+ reachable : & [ String ] ,
431+ crate_type : CrateType )
432+ -> Vec < String > {
433+ if !scx. sess ( ) . crate_types . borrow ( ) . contains ( & crate_type) {
434+ return vec ! [ ] ;
435+ }
436+
437+ // See explanation in GnuLinker::export_symbols, for
438+ // why we don't ever need dylib symbols on non-MSVC.
439+ if crate_type == CrateType :: CrateTypeDylib {
440+ if !scx. sess ( ) . target . target . options . is_like_msvc {
441+ return vec ! [ ] ;
442+ }
443+ }
444+
445+ let mut symbols = reachable. to_vec ( ) ;
401446
402447 // If we're producing anything other than a dylib then the `reachable` array
403448 // above is the exhaustive set of symbols we should be exporting.
@@ -409,20 +454,19 @@ fn exported_symbols(sess: &Session,
409454 return symbols
410455 }
411456
412- let cstore = & sess. cstore ;
413- let formats = sess. dependency_formats . borrow ( ) ;
414- let upstream_symbols = formats[ & crate_type] . iter ( ) ;
415- symbols. extend ( upstream_symbols . enumerate ( ) . filter_map ( |( i, f) | {
457+ let cstore = & scx . sess ( ) . cstore ;
458+ let formats = scx . sess ( ) . dependency_formats . borrow ( ) ;
459+ let deps = formats[ & crate_type] . iter ( ) ;
460+ symbols. extend ( deps . enumerate ( ) . filter_map ( |( i, f) | {
416461 if * f == Linkage :: Static {
417462 Some ( ( i + 1 ) as ast:: CrateNum )
418463 } else {
419464 None
420465 }
421466 } ) . flat_map ( |cnum| {
422467 cstore. reachable_ids ( cnum)
423- } ) . map ( |did| {
424- cstore . item_symbol ( did)
468+ } ) . map ( |did| -> String {
469+ Instance :: mono ( scx , did) . symbol_name ( scx )
425470 } ) ) ;
426-
427- return symbols
471+ symbols
428472}
0 commit comments