@@ -17,7 +17,7 @@ use rustc_serialize::{json, Encoder};
17
17
use rustc_session:: config:: { self , CrateType , DebugInfo , LinkerPluginLto , Lto , OptLevel , Strip } ;
18
18
use rustc_session:: Session ;
19
19
use rustc_span:: symbol:: Symbol ;
20
- use rustc_target:: spec:: { LinkerFlavor , LldFlavor } ;
20
+ use rustc_target:: spec:: { LinkOutputKind , LinkerFlavor , LldFlavor } ;
21
21
22
22
/// Disables non-English messages from localized linkers.
23
23
/// Such messages may cause issues with text encoding on Windows (#35785)
@@ -101,6 +101,7 @@ impl LinkerInfo {
101
101
/// MSVC linker (e.g., `link.exe`) is being used.
102
102
pub trait Linker {
103
103
fn cmd ( & mut self ) -> & mut Command ;
104
+ fn set_output_kind ( & mut self , output_kind : LinkOutputKind , out_filename : & Path ) ;
104
105
fn link_dylib ( & mut self , lib : Symbol ) ;
105
106
fn link_rust_dylib ( & mut self , lib : Symbol , path : & Path ) ;
106
107
fn link_framework ( & mut self , framework : Symbol ) ;
@@ -113,8 +114,6 @@ pub trait Linker {
113
114
fn output_filename ( & mut self , path : & Path ) ;
114
115
fn add_object ( & mut self , path : & Path ) ;
115
116
fn gc_sections ( & mut self , keep_metadata : bool ) ;
116
- fn position_independent_executable ( & mut self ) ;
117
- fn no_position_independent_executable ( & mut self ) ;
118
117
fn full_relro ( & mut self ) ;
119
118
fn partial_relro ( & mut self ) ;
120
119
fn no_relro ( & mut self ) ;
@@ -124,8 +123,6 @@ pub trait Linker {
124
123
fn debuginfo ( & mut self , strip : Strip ) ;
125
124
fn no_crt_objects ( & mut self ) ;
126
125
fn no_default_libraries ( & mut self ) ;
127
- fn build_dylib ( & mut self , out_filename : & Path ) ;
128
- fn build_static_executable ( & mut self ) ;
129
126
fn export_symbols ( & mut self , tmpdir : & Path , crate_type : CrateType ) ;
130
127
fn subsystem ( & mut self , subsystem : & str ) ;
131
128
fn group_start ( & mut self ) ;
@@ -232,12 +229,94 @@ impl<'a> GccLinker<'a> {
232
229
let target_cpu = self . target_cpu ;
233
230
self . linker_arg ( & format ! ( "-plugin-opt=mcpu={}" , target_cpu) ) ;
234
231
}
232
+
233
+ fn build_dylib ( & mut self , out_filename : & Path ) {
234
+ // On mac we need to tell the linker to let this library be rpathed
235
+ if self . sess . target . target . options . is_like_osx {
236
+ self . cmd . arg ( "-dynamiclib" ) ;
237
+ self . linker_arg ( "-dylib" ) ;
238
+
239
+ // Note that the `osx_rpath_install_name` option here is a hack
240
+ // purely to support rustbuild right now, we should get a more
241
+ // principled solution at some point to force the compiler to pass
242
+ // the right `-Wl,-install_name` with an `@rpath` in it.
243
+ if self . sess . opts . cg . rpath || self . sess . opts . debugging_opts . osx_rpath_install_name {
244
+ self . linker_arg ( "-install_name" ) ;
245
+ let mut v = OsString :: from ( "@rpath/" ) ;
246
+ v. push ( out_filename. file_name ( ) . unwrap ( ) ) ;
247
+ self . linker_arg ( & v) ;
248
+ }
249
+ } else {
250
+ self . cmd . arg ( "-shared" ) ;
251
+ if self . sess . target . target . options . is_like_windows {
252
+ // The output filename already contains `dll_suffix` so
253
+ // the resulting import library will have a name in the
254
+ // form of libfoo.dll.a
255
+ let implib_name =
256
+ out_filename. file_name ( ) . and_then ( |file| file. to_str ( ) ) . map ( |file| {
257
+ format ! (
258
+ "{}{}{}" ,
259
+ self . sess. target. target. options. staticlib_prefix,
260
+ file,
261
+ self . sess. target. target. options. staticlib_suffix
262
+ )
263
+ } ) ;
264
+ if let Some ( implib_name) = implib_name {
265
+ let implib = out_filename. parent ( ) . map ( |dir| dir. join ( & implib_name) ) ;
266
+ if let Some ( implib) = implib {
267
+ self . linker_arg ( & format ! ( "--out-implib,{}" , ( * implib) . to_str( ) . unwrap( ) ) ) ;
268
+ }
269
+ }
270
+ }
271
+ }
272
+ }
235
273
}
236
274
237
275
impl < ' a > Linker for GccLinker < ' a > {
238
276
fn cmd ( & mut self ) -> & mut Command {
239
277
& mut self . cmd
240
278
}
279
+
280
+ fn set_output_kind ( & mut self , output_kind : LinkOutputKind , out_filename : & Path ) {
281
+ match output_kind {
282
+ LinkOutputKind :: DynamicNoPicExe => {
283
+ if !self . is_ld {
284
+ self . cmd . arg ( "-no-pie" ) ;
285
+ }
286
+ }
287
+ LinkOutputKind :: DynamicPicExe => {
288
+ // `-pie` works for both gcc wrapper and ld.
289
+ self . cmd . arg ( "-pie" ) ;
290
+ }
291
+ LinkOutputKind :: StaticNoPicExe => {
292
+ // `-static` works for both gcc wrapper and ld.
293
+ self . cmd . arg ( "-static" ) ;
294
+ if !self . is_ld {
295
+ self . cmd . arg ( "-no-pie" ) ;
296
+ }
297
+ }
298
+ LinkOutputKind :: StaticPicExe => {
299
+ if !self . is_ld {
300
+ // Note that combination `-static -pie` doesn't work as expected
301
+ // for the gcc wrapper, `-static` in that case suppresses `-pie`.
302
+ self . cmd . arg ( "-static-pie" ) ;
303
+ } else {
304
+ // `--no-dynamic-linker` and `-z text` are not strictly necessary for producing
305
+ // a static pie, but currently passed because gcc and clang pass them.
306
+ // The former suppresses the `INTERP` ELF header specifying dynamic linker,
307
+ // which is otherwise implicitly injected by ld (but not lld).
308
+ // The latter doesn't change anything, only ensures that everything is pic.
309
+ self . cmd . args ( & [ "-static" , "-pie" , "--no-dynamic-linker" , "-z" , "text" ] ) ;
310
+ }
311
+ }
312
+ LinkOutputKind :: DynamicDylib => self . build_dylib ( out_filename) ,
313
+ LinkOutputKind :: StaticDylib => {
314
+ self . cmd . arg ( "-static" ) ;
315
+ self . build_dylib ( out_filename) ;
316
+ }
317
+ }
318
+ }
319
+
241
320
fn link_dylib ( & mut self , lib : Symbol ) {
242
321
self . hint_dynamic ( ) ;
243
322
self . cmd . arg ( format ! ( "-l{}" , lib) ) ;
@@ -262,14 +341,6 @@ impl<'a> Linker for GccLinker<'a> {
262
341
fn add_object ( & mut self , path : & Path ) {
263
342
self . cmd . arg ( path) ;
264
343
}
265
- fn position_independent_executable ( & mut self ) {
266
- self . cmd . arg ( "-pie" ) ;
267
- }
268
- fn no_position_independent_executable ( & mut self ) {
269
- if !self . is_ld {
270
- self . cmd . arg ( "-no-pie" ) ;
271
- }
272
- }
273
344
fn full_relro ( & mut self ) {
274
345
self . linker_arg ( "-zrelro" ) ;
275
346
self . linker_arg ( "-znow" ) ;
@@ -280,9 +351,6 @@ impl<'a> Linker for GccLinker<'a> {
280
351
fn no_relro ( & mut self ) {
281
352
self . linker_arg ( "-znorelro" ) ;
282
353
}
283
- fn build_static_executable ( & mut self ) {
284
- self . cmd . arg ( "-static" ) ;
285
- }
286
354
287
355
fn link_rust_dylib ( & mut self , lib : Symbol , _path : & Path ) {
288
356
self . hint_dynamic ( ) ;
@@ -418,47 +486,6 @@ impl<'a> Linker for GccLinker<'a> {
418
486
}
419
487
}
420
488
421
- fn build_dylib ( & mut self , out_filename : & Path ) {
422
- // On mac we need to tell the linker to let this library be rpathed
423
- if self . sess . target . target . options . is_like_osx {
424
- self . cmd . arg ( "-dynamiclib" ) ;
425
- self . linker_arg ( "-dylib" ) ;
426
-
427
- // Note that the `osx_rpath_install_name` option here is a hack
428
- // purely to support rustbuild right now, we should get a more
429
- // principled solution at some point to force the compiler to pass
430
- // the right `-Wl,-install_name` with an `@rpath` in it.
431
- if self . sess . opts . cg . rpath || self . sess . opts . debugging_opts . osx_rpath_install_name {
432
- self . linker_arg ( "-install_name" ) ;
433
- let mut v = OsString :: from ( "@rpath/" ) ;
434
- v. push ( out_filename. file_name ( ) . unwrap ( ) ) ;
435
- self . linker_arg ( & v) ;
436
- }
437
- } else {
438
- self . cmd . arg ( "-shared" ) ;
439
- if self . sess . target . target . options . is_like_windows {
440
- // The output filename already contains `dll_suffix` so
441
- // the resulting import library will have a name in the
442
- // form of libfoo.dll.a
443
- let implib_name =
444
- out_filename. file_name ( ) . and_then ( |file| file. to_str ( ) ) . map ( |file| {
445
- format ! (
446
- "{}{}{}" ,
447
- self . sess. target. target. options. staticlib_prefix,
448
- file,
449
- self . sess. target. target. options. staticlib_suffix
450
- )
451
- } ) ;
452
- if let Some ( implib_name) = implib_name {
453
- let implib = out_filename. parent ( ) . map ( |dir| dir. join ( & implib_name) ) ;
454
- if let Some ( implib) = implib {
455
- self . linker_arg ( & format ! ( "--out-implib,{}" , ( * implib) . to_str( ) . unwrap( ) ) ) ;
456
- }
457
- }
458
- }
459
- }
460
- }
461
-
462
489
fn export_symbols ( & mut self , tmpdir : & Path , crate_type : CrateType ) {
463
490
// Symbol visibility in object files typically takes care of this.
464
491
if crate_type == CrateType :: Executable
@@ -582,24 +609,29 @@ impl<'a> Linker for MsvcLinker<'a> {
582
609
fn cmd ( & mut self ) -> & mut Command {
583
610
& mut self . cmd
584
611
}
612
+
613
+ fn set_output_kind ( & mut self , output_kind : LinkOutputKind , out_filename : & Path ) {
614
+ match output_kind {
615
+ LinkOutputKind :: DynamicNoPicExe
616
+ | LinkOutputKind :: DynamicPicExe
617
+ | LinkOutputKind :: StaticNoPicExe
618
+ | LinkOutputKind :: StaticPicExe => { }
619
+ LinkOutputKind :: DynamicDylib | LinkOutputKind :: StaticDylib => {
620
+ self . cmd . arg ( "/DLL" ) ;
621
+ let mut arg: OsString = "/IMPLIB:" . into ( ) ;
622
+ arg. push ( out_filename. with_extension ( "dll.lib" ) ) ;
623
+ self . cmd . arg ( arg) ;
624
+ }
625
+ }
626
+ }
627
+
585
628
fn link_rlib ( & mut self , lib : & Path ) {
586
629
self . cmd . arg ( lib) ;
587
630
}
588
631
fn add_object ( & mut self , path : & Path ) {
589
632
self . cmd . arg ( path) ;
590
633
}
591
634
592
- fn build_dylib ( & mut self , out_filename : & Path ) {
593
- self . cmd . arg ( "/DLL" ) ;
594
- let mut arg: OsString = "/IMPLIB:" . into ( ) ;
595
- arg. push ( out_filename. with_extension ( "dll.lib" ) ) ;
596
- self . cmd . arg ( arg) ;
597
- }
598
-
599
- fn build_static_executable ( & mut self ) {
600
- // noop
601
- }
602
-
603
635
fn gc_sections ( & mut self , _keep_metadata : bool ) {
604
636
// MSVC's ICF (Identical COMDAT Folding) link optimization is
605
637
// slow for Rust and thus we disable it by default when not in
@@ -632,14 +664,6 @@ impl<'a> Linker for MsvcLinker<'a> {
632
664
self . cmd . arg ( & format ! ( "{}.lib" , lib) ) ;
633
665
}
634
666
635
- fn position_independent_executable ( & mut self ) {
636
- // noop
637
- }
638
-
639
- fn no_position_independent_executable ( & mut self ) {
640
- // noop
641
- }
642
-
643
667
fn full_relro ( & mut self ) {
644
668
// noop
645
669
}
@@ -817,6 +841,9 @@ impl<'a> Linker for EmLinker<'a> {
817
841
fn cmd ( & mut self ) -> & mut Command {
818
842
& mut self . cmd
819
843
}
844
+
845
+ fn set_output_kind ( & mut self , _output_kind : LinkOutputKind , _out_filename : & Path ) { }
846
+
820
847
fn include_path ( & mut self , path : & Path ) {
821
848
self . cmd . arg ( "-L" ) . arg ( path) ;
822
849
}
@@ -856,14 +883,6 @@ impl<'a> Linker for EmLinker<'a> {
856
883
self . add_object ( lib) ;
857
884
}
858
885
859
- fn position_independent_executable ( & mut self ) {
860
- // noop
861
- }
862
-
863
- fn no_position_independent_executable ( & mut self ) {
864
- // noop
865
- }
866
-
867
886
fn full_relro ( & mut self ) {
868
887
// noop
869
888
}
@@ -925,14 +944,6 @@ impl<'a> Linker for EmLinker<'a> {
925
944
self . cmd . args ( & [ "-s" , "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]" ] ) ;
926
945
}
927
946
928
- fn build_dylib ( & mut self , _out_filename : & Path ) {
929
- bug ! ( "building dynamic library is unsupported on Emscripten" )
930
- }
931
-
932
- fn build_static_executable ( & mut self ) {
933
- // noop
934
- }
935
-
936
947
fn export_symbols ( & mut self , _tmpdir : & Path , crate_type : CrateType ) {
937
948
let symbols = & self . info . exports [ & crate_type] ;
938
949
@@ -1031,6 +1042,18 @@ impl<'a> Linker for WasmLd<'a> {
1031
1042
& mut self . cmd
1032
1043
}
1033
1044
1045
+ fn set_output_kind ( & mut self , output_kind : LinkOutputKind , _out_filename : & Path ) {
1046
+ match output_kind {
1047
+ LinkOutputKind :: DynamicNoPicExe
1048
+ | LinkOutputKind :: DynamicPicExe
1049
+ | LinkOutputKind :: StaticNoPicExe
1050
+ | LinkOutputKind :: StaticPicExe => { }
1051
+ LinkOutputKind :: DynamicDylib | LinkOutputKind :: StaticDylib => {
1052
+ self . cmd . arg ( "--no-entry" ) ;
1053
+ }
1054
+ }
1055
+ }
1056
+
1034
1057
fn link_dylib ( & mut self , lib : Symbol ) {
1035
1058
self . cmd . arg ( "-l" ) . sym_arg ( lib) ;
1036
1059
}
@@ -1059,16 +1082,12 @@ impl<'a> Linker for WasmLd<'a> {
1059
1082
self . cmd . arg ( path) ;
1060
1083
}
1061
1084
1062
- fn position_independent_executable ( & mut self ) { }
1063
-
1064
1085
fn full_relro ( & mut self ) { }
1065
1086
1066
1087
fn partial_relro ( & mut self ) { }
1067
1088
1068
1089
fn no_relro ( & mut self ) { }
1069
1090
1070
- fn build_static_executable ( & mut self ) { }
1071
-
1072
1091
fn link_rust_dylib ( & mut self , lib : Symbol , _path : & Path ) {
1073
1092
self . cmd . arg ( "-l" ) . sym_arg ( lib) ;
1074
1093
}
@@ -1124,10 +1143,6 @@ impl<'a> Linker for WasmLd<'a> {
1124
1143
1125
1144
fn no_default_libraries ( & mut self ) { }
1126
1145
1127
- fn build_dylib ( & mut self , _out_filename : & Path ) {
1128
- self . cmd . arg ( "--no-entry" ) ;
1129
- }
1130
-
1131
1146
fn export_symbols ( & mut self , _tmpdir : & Path , crate_type : CrateType ) {
1132
1147
for sym in self . info . exports [ & crate_type] . iter ( ) {
1133
1148
self . cmd . arg ( "--export" ) . arg ( & sym) ;
@@ -1143,8 +1158,6 @@ impl<'a> Linker for WasmLd<'a> {
1143
1158
1144
1159
fn subsystem ( & mut self , _subsystem : & str ) { }
1145
1160
1146
- fn no_position_independent_executable ( & mut self ) { }
1147
-
1148
1161
fn finalize ( & mut self ) { }
1149
1162
1150
1163
// Not needed for now with LLD
@@ -1207,6 +1220,8 @@ impl<'a> Linker for PtxLinker<'a> {
1207
1220
& mut self . cmd
1208
1221
}
1209
1222
1223
+ fn set_output_kind ( & mut self , _output_kind : LinkOutputKind , _out_filename : & Path ) { }
1224
+
1210
1225
fn link_rlib ( & mut self , path : & Path ) {
1211
1226
self . cmd . arg ( "--rlib" ) . arg ( path) ;
1212
1227
}
@@ -1273,16 +1288,12 @@ impl<'a> Linker for PtxLinker<'a> {
1273
1288
panic ! ( "frameworks not supported" )
1274
1289
}
1275
1290
1276
- fn position_independent_executable ( & mut self ) { }
1277
-
1278
1291
fn full_relro ( & mut self ) { }
1279
1292
1280
1293
fn partial_relro ( & mut self ) { }
1281
1294
1282
1295
fn no_relro ( & mut self ) { }
1283
1296
1284
- fn build_static_executable ( & mut self ) { }
1285
-
1286
1297
fn gc_sections ( & mut self , _keep_metadata : bool ) { }
1287
1298
1288
1299
fn pgo_gen ( & mut self ) { }
@@ -1295,14 +1306,10 @@ impl<'a> Linker for PtxLinker<'a> {
1295
1306
self . sess . warn ( "Windows Control Flow Guard is not supported by this linker." ) ;
1296
1307
}
1297
1308
1298
- fn build_dylib ( & mut self , _out_filename : & Path ) { }
1299
-
1300
1309
fn export_symbols ( & mut self , _tmpdir : & Path , _crate_type : CrateType ) { }
1301
1310
1302
1311
fn subsystem ( & mut self , _subsystem : & str ) { }
1303
1312
1304
- fn no_position_independent_executable ( & mut self ) { }
1305
-
1306
1313
fn group_start ( & mut self ) { }
1307
1314
1308
1315
fn group_end ( & mut self ) { }
0 commit comments