9
9
// except according to those terms.
10
10
11
11
use std:: ffi:: OsString ;
12
+ use std:: fmt:: Write as FmtWrite ;
12
13
use std:: fs:: { self , File } ;
13
14
use std:: io:: { self , BufWriter } ;
14
15
use std:: io:: prelude:: * ;
15
16
use std:: path:: { Path , PathBuf } ;
16
17
use std:: process:: Command ;
17
18
19
+ use context:: SharedCrateContext ;
20
+ use monomorphize:: Instance ;
21
+
18
22
use back:: archive;
19
23
use middle:: dependency_format:: Linkage ;
20
24
use session:: Session ;
21
25
use session:: config:: CrateTypeDylib ;
22
26
use session:: config;
23
27
use syntax:: ast;
24
- use CrateTranslation ;
28
+
29
+ /// For all the linkers we support, and information they might
30
+ /// need out of the shared crate context before we get rid of it.
31
+ pub enum LinkerInfo {
32
+ Gnu ,
33
+ Msvc {
34
+ dylib_exports : String
35
+ }
36
+ }
37
+
38
+ impl < ' a , ' tcx > LinkerInfo {
39
+ pub fn new ( scx : & SharedCrateContext < ' a , ' tcx > ,
40
+ reachable : & [ String ] ) -> LinkerInfo {
41
+ if scx. sess ( ) . target . target . options . is_like_msvc {
42
+ let mut exports = String :: new ( ) ;
43
+ if scx. sess ( ) . crate_types . borrow ( ) . contains ( & CrateTypeDylib ) {
44
+ for sym in reachable {
45
+ writeln ! ( exports, " {}" , sym) . unwrap ( ) ;
46
+ }
47
+
48
+ // Take a look at how all upstream crates are linked into this
49
+ // dynamic library. For all statically linked libraries we take all
50
+ // their reachable symbols and emit them as well.
51
+ let cstore = & scx. sess ( ) . cstore ;
52
+ let formats = scx. sess ( ) . dependency_formats . borrow ( ) ;
53
+ let symbols = formats[ & CrateTypeDylib ] . iter ( ) ;
54
+ let symbols = symbols. enumerate ( ) . filter_map ( |( i, f) | {
55
+ if * f == Linkage :: Static {
56
+ Some ( ( i + 1 ) as ast:: CrateNum )
57
+ } else {
58
+ None
59
+ }
60
+ } ) . flat_map ( |cnum| {
61
+ cstore. reachable_ids ( cnum)
62
+ } ) . map ( |did| -> String {
63
+ Instance :: mono ( scx. tcx ( ) , did) . symbol_name ( scx)
64
+ } ) ;
65
+ for symbol in symbols {
66
+ writeln ! ( exports, " {}" , symbol) . unwrap ( ) ;
67
+ }
68
+ }
69
+ LinkerInfo :: Msvc {
70
+ dylib_exports : exports
71
+ }
72
+ } else {
73
+ LinkerInfo :: Gnu
74
+ }
75
+ }
76
+
77
+ pub fn to_linker ( & ' a self ,
78
+ cmd : & ' a mut Command ,
79
+ sess : & ' a Session ) -> Box < Linker +' a > {
80
+ match * self {
81
+ LinkerInfo :: Gnu => {
82
+ Box :: new ( GnuLinker {
83
+ cmd : cmd,
84
+ sess : sess
85
+ } ) as Box < Linker >
86
+ }
87
+ LinkerInfo :: Msvc { ref dylib_exports } => {
88
+ Box :: new ( MsvcLinker {
89
+ cmd : cmd,
90
+ sess : sess,
91
+ dylib_exports : dylib_exports
92
+ } ) as Box < Linker >
93
+ }
94
+ }
95
+ }
96
+ }
25
97
26
98
/// Linker abstraction used by back::link to build up the command to invoke a
27
99
/// linker.
@@ -53,13 +125,12 @@ pub trait Linker {
53
125
fn hint_dynamic ( & mut self ) ;
54
126
fn whole_archives ( & mut self ) ;
55
127
fn no_whole_archives ( & mut self ) ;
56
- fn export_symbols ( & mut self , sess : & Session , trans : & CrateTranslation ,
57
- tmpdir : & Path ) ;
128
+ fn export_symbols ( & mut self , tmpdir : & Path ) ;
58
129
}
59
130
60
131
pub struct GnuLinker < ' a > {
61
- pub cmd : & ' a mut Command ,
62
- pub sess : & ' a Session ,
132
+ cmd : & ' a mut Command ,
133
+ sess : & ' a Session ,
63
134
}
64
135
65
136
impl < ' a > GnuLinker < ' a > {
@@ -198,14 +269,15 @@ impl<'a> Linker for GnuLinker<'a> {
198
269
self . cmd . arg ( "-Wl,-Bdynamic" ) ;
199
270
}
200
271
201
- fn export_symbols ( & mut self , _: & Session , _ : & CrateTranslation , _ : & Path ) {
272
+ fn export_symbols ( & mut self , _: & Path ) {
202
273
// noop, visibility in object files takes care of this
203
274
}
204
275
}
205
276
206
277
pub struct MsvcLinker < ' a > {
207
- pub cmd : & ' a mut Command ,
208
- pub sess : & ' a Session ,
278
+ cmd : & ' a mut Command ,
279
+ sess : & ' a Session ,
280
+ dylib_exports : & ' a str
209
281
}
210
282
211
283
impl < ' a > Linker for MsvcLinker < ' a > {
@@ -322,8 +394,7 @@ impl<'a> Linker for MsvcLinker<'a> {
322
394
// crates. Upstream rlibs may be linked statically to this dynamic library,
323
395
// in which case they may continue to transitively be used and hence need
324
396
// their symbols exported.
325
- fn export_symbols ( & mut self , sess : & Session , trans : & CrateTranslation ,
326
- tmpdir : & Path ) {
397
+ fn export_symbols ( & mut self , tmpdir : & Path ) {
327
398
let path = tmpdir. join ( "lib.def" ) ;
328
399
let res = ( || -> io:: Result < ( ) > {
329
400
let mut f = BufWriter :: new ( File :: create ( & path) ?) ;
@@ -332,37 +403,11 @@ impl<'a> Linker for MsvcLinker<'a> {
332
403
// straight to exports.
333
404
writeln ! ( f, "LIBRARY" ) ?;
334
405
writeln ! ( f, "EXPORTS" ) ?;
335
-
336
- // Write out all our local symbols
337
- for sym in trans. reachable . iter ( ) {
338
- writeln ! ( f, " {}" , sym) ?;
339
- }
340
-
341
- // Take a look at how all upstream crates are linked into this
342
- // dynamic library. For all statically linked libraries we take all
343
- // their reachable symbols and emit them as well.
344
- let cstore = & sess. cstore ;
345
- let formats = sess. dependency_formats . borrow ( ) ;
346
- let symbols = formats[ & CrateTypeDylib ] . iter ( ) ;
347
- let symbols = symbols. enumerate ( ) . filter_map ( |( i, f) | {
348
- if * f == Linkage :: Static {
349
- Some ( ( i + 1 ) as ast:: CrateNum )
350
- } else {
351
- None
352
- }
353
- } ) . flat_map ( |cnum| {
354
- cstore. reachable_ids ( cnum)
355
- } ) . map ( |did| {
356
- cstore. item_symbol ( did)
357
- } ) ;
358
- for symbol in symbols {
359
- writeln ! ( f, " {}" , symbol) ?;
360
- }
361
-
406
+ f. write ( self . dylib_exports . as_bytes ( ) ) ?;
362
407
Ok ( ( ) )
363
408
} ) ( ) ;
364
409
if let Err ( e) = res {
365
- sess. fatal ( & format ! ( "failed to write lib.def file: {}" , e) ) ;
410
+ self . sess . fatal ( & format ! ( "failed to write lib.def file: {}" , e) ) ;
366
411
}
367
412
let mut arg = OsString :: from ( "/DEF:" ) ;
368
413
arg. push ( path) ;
0 commit comments