@@ -17,11 +17,11 @@ use std::path::{Path, PathBuf};
1717use std:: process:: Command ;
1818
1919use context:: SharedCrateContext ;
20- use monomorphize:: Instance ;
2120
2221use back:: archive;
22+ use back:: symbol_export:: { self , ExportedSymbols } ;
2323use middle:: dependency_format:: Linkage ;
24- use rustc:: hir:: def_id:: CrateNum ;
24+ use rustc:: hir:: def_id:: { LOCAL_CRATE , CrateNum } ;
2525use session:: Session ;
2626use session:: config:: CrateType ;
2727use session:: config;
@@ -34,10 +34,10 @@ pub struct LinkerInfo {
3434
3535impl < ' a , ' tcx > LinkerInfo {
3636 pub fn new ( scx : & SharedCrateContext < ' a , ' tcx > ,
37- reachable : & [ String ] ) -> LinkerInfo {
37+ exports : & ExportedSymbols ) -> LinkerInfo {
3838 LinkerInfo {
3939 exports : scx. sess ( ) . crate_types . borrow ( ) . iter ( ) . map ( |& c| {
40- ( c, exported_symbols ( scx, reachable , c) )
40+ ( c, exported_symbols ( scx, exports , c) )
4141 } ) . collect ( ) ,
4242 }
4343 }
@@ -253,46 +253,47 @@ impl<'a> Linker for GnuLinker<'a> {
253253 let mut arg = OsString :: new ( ) ;
254254 let path = tmpdir. join ( "list" ) ;
255255
256- if self . sess . target . target . options . is_like_solaris {
256+ debug ! ( "EXPORTED SYMBOLS:" ) ;
257+
258+ if self . sess . target . target . options . is_like_osx {
259+ // Write a plain, newline-separated list of symbols
257260 let res = ( || -> io:: Result < ( ) > {
258261 let mut f = BufWriter :: new ( File :: create ( & path) ?) ;
259- writeln ! ( f, "{{\n global:" ) ?;
260262 for sym in self . info . exports [ & crate_type] . iter ( ) {
261- writeln ! ( f, " {};" , sym) ?;
263+ debug ! ( " _{}" , sym) ;
264+ writeln ! ( f, "_{}" , sym) ?;
262265 }
263- writeln ! ( f, "\n local:\n *;\n }};" ) ?;
264266 Ok ( ( ) )
265267 } ) ( ) ;
266268 if let Err ( e) = res {
267- self . sess . fatal ( & format ! ( "failed to write version script : {}" , e) ) ;
269+ self . sess . fatal ( & format ! ( "failed to write lib.def file : {}" , e) ) ;
268270 }
269-
270- arg. push ( "-Wl,-M," ) ;
271- arg. push ( & path) ;
272271 } else {
273- let prefix = if self . sess . target . target . options . is_like_osx {
274- "_"
275- } else {
276- ""
277- } ;
272+ // Write an LD version script
278273 let res = ( || -> io:: Result < ( ) > {
279274 let mut f = BufWriter :: new ( File :: create ( & path) ?) ;
275+ writeln ! ( f, "{{\n global:" ) ?;
280276 for sym in self . info . exports [ & crate_type] . iter ( ) {
281- writeln ! ( f, "{}{}" , prefix, sym) ?;
277+ debug ! ( " {};" , sym) ;
278+ writeln ! ( f, " {};" , sym) ?;
282279 }
280+ writeln ! ( f, "\n local:\n *;\n }};" ) ?;
283281 Ok ( ( ) )
284282 } ) ( ) ;
285283 if let Err ( e) = res {
286- self . sess . fatal ( & format ! ( "failed to write lib.def file: {}" , e) ) ;
287- }
288- if self . sess . target . target . options . is_like_osx {
289- arg. push ( "-Wl,-exported_symbols_list," ) ;
290- } else {
291- arg. push ( "-Wl,--retain-symbols-file=" ) ;
284+ self . sess . fatal ( & format ! ( "failed to write version script: {}" , e) ) ;
292285 }
293- arg. push ( & path) ;
294286 }
295287
288+ if self . sess . target . target . options . is_like_osx {
289+ arg. push ( "-Wl,-exported_symbols_list," ) ;
290+ } else if self . sess . target . target . options . is_like_solaris {
291+ arg. push ( "-Wl,-M," ) ;
292+ } else {
293+ arg. push ( "-Wl,--version-script=" ) ;
294+ }
295+
296+ arg. push ( & path) ;
296297 self . cmd . arg ( arg) ;
297298 }
298299
@@ -473,43 +474,29 @@ impl<'a> Linker for MsvcLinker<'a> {
473474}
474475
475476fn exported_symbols ( scx : & SharedCrateContext ,
476- reachable : & [ String ] ,
477+ exported_symbols : & ExportedSymbols ,
477478 crate_type : CrateType )
478479 -> Vec < String > {
479- // See explanation in GnuLinker::export_symbols, for
480- // why we don't ever need dylib symbols on non-MSVC.
481- if crate_type == CrateType :: CrateTypeDylib ||
482- crate_type == CrateType :: CrateTypeProcMacro {
483- if !scx. sess ( ) . target . target . options . is_like_msvc {
484- return vec ! [ ] ;
485- }
486- }
480+ let export_threshold = symbol_export:: crate_export_threshold ( crate_type) ;
487481
488- let mut symbols = reachable. to_vec ( ) ;
482+ let mut symbols = Vec :: new ( ) ;
483+ exported_symbols. for_each_exported_symbol ( LOCAL_CRATE , export_threshold, |name, _| {
484+ symbols. push ( name. to_owned ( ) ) ;
485+ } ) ;
489486
490- // If we're producing anything other than a dylib then the `reachable` array
491- // above is the exhaustive set of symbols we should be exporting.
492- //
493- // For dylibs, however, we need to take a look at how all upstream crates
494- // are linked into this dynamic library. For all statically linked
495- // libraries we take all their reachable symbols and emit them as well.
496- if crate_type != CrateType :: CrateTypeDylib {
497- return symbols
498- }
499-
500- let cstore = & scx. sess ( ) . cstore ;
501487 let formats = scx. sess ( ) . dependency_formats . borrow ( ) ;
502488 let deps = formats[ & crate_type] . iter ( ) ;
503- symbols. extend ( deps. enumerate ( ) . filter_map ( |( i, f) | {
504- if * f == Linkage :: Static {
505- Some ( CrateNum :: new ( i + 1 ) )
506- } else {
507- None
489+
490+ for ( index, dep_format) in deps. enumerate ( ) {
491+ let cnum = CrateNum :: new ( index + 1 ) ;
492+ // For each dependency that we are linking to statically ...
493+ if * dep_format == Linkage :: Static {
494+ // ... we add its symbol list to our export list.
495+ exported_symbols. for_each_exported_symbol ( cnum, export_threshold, |name, _| {
496+ symbols. push ( name. to_owned ( ) ) ;
497+ } )
508498 }
509- } ) . flat_map ( |cnum| {
510- cstore. reachable_ids ( cnum)
511- } ) . map ( |did| -> String {
512- Instance :: mono ( scx, did) . symbol_name ( scx)
513- } ) ) ;
499+ }
500+
514501 symbols
515502}
0 commit comments