@@ -15,13 +15,50 @@ use std::io::prelude::*;
15
15
use std:: path:: { Path , PathBuf } ;
16
16
use std:: process:: Command ;
17
17
18
+ use context:: SharedCrateContext ;
19
+ use monomorphize:: Instance ;
20
+
18
21
use back:: archive;
19
22
use middle:: dependency_format:: Linkage ;
20
23
use session:: Session ;
21
24
use session:: config:: CrateType ;
22
25
use session:: config;
23
26
use 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
+ }
25
62
26
63
/// Linker abstraction used by back::link to build up the command to invoke a
27
64
/// linker.
@@ -53,16 +90,13 @@ pub trait Linker {
53
90
fn hint_dynamic ( & mut self ) ;
54
91
fn whole_archives ( & mut self ) ;
55
92
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 ) ;
61
94
}
62
95
63
96
pub 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
66
100
}
67
101
68
102
impl < ' a > GnuLinker < ' a > {
@@ -201,11 +235,7 @@ impl<'a> Linker for GnuLinker<'a> {
201
235
self . cmd . arg ( "-Wl,-Bdynamic" ) ;
202
236
}
203
237
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 ) {
209
239
// If we're compiling a dylib, then we let symbol visibility in object
210
240
// files to take care of whether they're exported or not.
211
241
//
@@ -225,13 +255,13 @@ impl<'a> Linker for GnuLinker<'a> {
225
255
} ;
226
256
let res = ( || -> io:: Result < ( ) > {
227
257
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 {
229
259
writeln ! ( f, "{}{}" , prefix, sym) ?;
230
260
}
231
261
Ok ( ( ) )
232
262
} ) ( ) ;
233
263
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) ) ;
235
265
}
236
266
let mut arg = OsString :: new ( ) ;
237
267
if self . sess . target . target . options . is_like_osx {
@@ -245,8 +275,9 @@ impl<'a> Linker for GnuLinker<'a> {
245
275
}
246
276
247
277
pub 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
250
281
}
251
282
252
283
impl < ' a > Linker for MsvcLinker < ' a > {
@@ -366,8 +397,6 @@ impl<'a> Linker for MsvcLinker<'a> {
366
397
// in which case they may continue to transitively be used and hence need
367
398
// their symbols exported.
368
399
fn export_symbols ( & mut self ,
369
- sess : & Session ,
370
- trans : & CrateTranslation ,
371
400
tmpdir : & Path ,
372
401
crate_type : CrateType ) {
373
402
let path = tmpdir. join ( "lib.def" ) ;
@@ -378,26 +407,42 @@ impl<'a> Linker for MsvcLinker<'a> {
378
407
// straight to exports.
379
408
writeln ! ( f, "LIBRARY" ) ?;
380
409
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) ?;
384
417
}
385
-
386
418
Ok ( ( ) )
387
419
} ) ( ) ;
388
420
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) ) ;
390
422
}
391
423
let mut arg = OsString :: from ( "/DEF:" ) ;
392
424
arg. push ( path) ;
393
425
self . cmd . arg ( & arg) ;
394
426
}
395
427
}
396
428
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 ( ) ;
401
446
402
447
// If we're producing anything other than a dylib then the `reachable` array
403
448
// above is the exhaustive set of symbols we should be exporting.
@@ -409,20 +454,19 @@ fn exported_symbols(sess: &Session,
409
454
return symbols
410
455
}
411
456
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) | {
416
461
if * f == Linkage :: Static {
417
462
Some ( ( i + 1 ) as ast:: CrateNum )
418
463
} else {
419
464
None
420
465
}
421
466
} ) . flat_map ( |cnum| {
422
467
cstore. reachable_ids ( cnum)
423
- } ) . map ( |did| {
424
- cstore . item_symbol ( did)
468
+ } ) . map ( |did| -> String {
469
+ Instance :: mono ( scx , did) . symbol_name ( scx )
425
470
} ) ) ;
426
-
427
- return symbols
471
+ symbols
428
472
}
0 commit comments