@@ -169,7 +169,12 @@ pub fn get_linker<'a>(
169
169
pub trait Linker {
170
170
fn cmd ( & mut self ) -> & mut Command ;
171
171
fn set_output_kind ( & mut self , output_kind : LinkOutputKind , out_filename : & Path ) ;
172
- fn link_dylib_by_name ( & mut self , name : & str , verbatim : bool , as_needed : bool ) ;
172
+ fn link_dylib_by_name ( & mut self , _name : & str , _verbatim : bool , _as_needed : bool ) {
173
+ bug ! ( "dylib linked with unsupported linker" )
174
+ }
175
+ fn link_dylib_by_path ( & mut self , _path : & Path , _as_needed : bool ) {
176
+ bug ! ( "dylib linked with unsupported linker" )
177
+ }
173
178
fn link_framework_by_name ( & mut self , _name : & str , _verbatim : bool , _as_needed : bool ) {
174
179
bug ! ( "framework linked with unsupported linker" )
175
180
}
@@ -320,28 +325,55 @@ impl<'a> GccLinker<'a> {
320
325
}
321
326
} else {
322
327
self . cmd . arg ( "-shared" ) ;
323
- if self . sess . target . is_like_windows {
324
- // The output filename already contains `dll_suffix` so
325
- // the resulting import library will have a name in the
326
- // form of libfoo.dll.a
327
- let implib_name =
328
- out_filename. file_name ( ) . and_then ( |file| file. to_str ( ) ) . map ( |file| {
329
- format ! (
330
- "{}{}{}" ,
331
- self . sess. target. staticlib_prefix,
332
- file,
333
- self . sess. target. staticlib_suffix
334
- )
335
- } ) ;
336
- if let Some ( implib_name) = implib_name {
337
- let implib = out_filename. parent ( ) . map ( |dir| dir. join ( & implib_name) ) ;
338
- if let Some ( implib) = implib {
339
- self . linker_arg ( & format ! ( "--out-implib={}" , ( * implib) . to_str( ) . unwrap( ) ) ) ;
328
+ if let Some ( name) = out_filename. file_name ( ) {
329
+ if self . sess . target . is_like_windows {
330
+ // The output filename already contains `dll_suffix` so
331
+ // the resulting import library will have a name in the
332
+ // form of libfoo.dll.a
333
+ let mut implib_name = OsString :: from ( & * self . sess . target . staticlib_prefix ) ;
334
+ implib_name. push ( name) ;
335
+ implib_name. push ( & * self . sess . target . staticlib_suffix ) ;
336
+ if let Some ( implib) = out_filename. parent ( ) . map ( |dir| dir. join ( & implib_name) ) {
337
+ let mut out_implib = OsString :: from ( "--out-implib=" ) ;
338
+ out_implib. push ( implib) ;
339
+ self . linker_arg ( out_implib) ;
340
340
}
341
+ } else {
342
+ // When dylibs are linked by a full path this value will get into `DT_NEEDED`
343
+ // instead of the full path, so the library can be later found in some other
344
+ // location than that specific path.
345
+ let mut soname = OsString :: from ( "-soname=" ) ;
346
+ soname. push ( name) ;
347
+ self . linker_arg ( soname) ;
341
348
}
342
349
}
343
350
}
344
351
}
352
+
353
+ fn open_as_needed ( & mut self , as_needed : bool ) {
354
+ if !as_needed {
355
+ if self . sess . target . is_like_osx {
356
+ // FIXME(81490): ld64 doesn't support these flags but macOS 11
357
+ // has -needed-l{} / -needed_library {}
358
+ // but we have no way to detect that here.
359
+ self . sess . dcx ( ) . emit_warn ( errors:: Ld64UnimplementedModifier ) ;
360
+ } else if self . is_gnu && !self . sess . target . is_like_windows {
361
+ self . linker_arg ( "--no-as-needed" ) ;
362
+ } else {
363
+ self . sess . dcx ( ) . emit_warn ( errors:: LinkerUnsupportedModifier ) ;
364
+ }
365
+ }
366
+ }
367
+
368
+ fn close_as_needed ( & mut self , as_needed : bool ) {
369
+ if !as_needed {
370
+ if self . sess . target . is_like_osx {
371
+ // See above FIXME comment
372
+ } else if self . is_gnu && !self . sess . target . is_like_windows {
373
+ self . linker_arg ( "--as-needed" ) ;
374
+ }
375
+ }
376
+ }
345
377
}
346
378
347
379
impl < ' a > Linker for GccLinker < ' a > {
@@ -443,27 +475,17 @@ impl<'a> Linker for GccLinker<'a> {
443
475
// to the linker.
444
476
return ;
445
477
}
446
- if !as_needed {
447
- if self . sess . target . is_like_osx {
448
- // FIXME(81490): ld64 doesn't support these flags but macOS 11
449
- // has -needed-l{} / -needed_library {}
450
- // but we have no way to detect that here.
451
- self . sess . dcx ( ) . emit_warn ( errors:: Ld64UnimplementedModifier ) ;
452
- } else if self . is_gnu && !self . sess . target . is_like_windows {
453
- self . linker_arg ( "--no-as-needed" ) ;
454
- } else {
455
- self . sess . dcx ( ) . emit_warn ( errors:: LinkerUnsupportedModifier ) ;
456
- }
457
- }
458
478
self . hint_dynamic ( ) ;
479
+ self . open_as_needed ( as_needed) ;
459
480
self . cmd . arg ( format ! ( "-l{}{name}" , if verbatim && self . is_gnu { ":" } else { "" } , ) ) ;
460
- if !as_needed {
461
- if self . sess . target . is_like_osx {
462
- // See above FIXME comment
463
- } else if self . is_gnu && !self . sess . target . is_like_windows {
464
- self . linker_arg ( "--as-needed" ) ;
465
- }
466
- }
481
+ self . close_as_needed ( as_needed) ;
482
+ }
483
+
484
+ fn link_dylib_by_path ( & mut self , path : & Path , as_needed : bool ) {
485
+ self . hint_dynamic ( ) ;
486
+ self . open_as_needed ( as_needed) ;
487
+ self . cmd . arg ( path) ;
488
+ self . close_as_needed ( as_needed) ;
467
489
}
468
490
469
491
fn link_framework_by_name ( & mut self , name : & str , _verbatim : bool , as_needed : bool ) {
@@ -813,6 +835,15 @@ impl<'a> Linker for MsvcLinker<'a> {
813
835
self . cmd . arg ( format ! ( "{}{}" , name, if verbatim { "" } else { ".lib" } ) ) ;
814
836
}
815
837
838
+ fn link_dylib_by_path ( & mut self , path : & Path , _as_needed : bool ) {
839
+ // When producing a dll, MSVC linker may not emit an implib file if the dll doesn't export
840
+ // any symbols, so we skip linking if the implib file is not present.
841
+ let implib_path = path. with_extension ( "dll.lib" ) ;
842
+ if implib_path. exists ( ) {
843
+ self . cmd ( ) . arg ( implib_path) ;
844
+ }
845
+ }
846
+
816
847
fn link_staticlib_by_name ( & mut self , name : & str , verbatim : bool , whole_archive : bool ) {
817
848
let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" } ;
818
849
let suffix = if verbatim { "" } else { ".lib" } ;
@@ -1039,6 +1070,10 @@ impl<'a> Linker for EmLinker<'a> {
1039
1070
self . cmd . arg ( "-l" ) . arg ( name) ;
1040
1071
}
1041
1072
1073
+ fn link_dylib_by_path ( & mut self , path : & Path , _as_needed : bool ) {
1074
+ self . cmd ( ) . arg ( path) ;
1075
+ }
1076
+
1042
1077
fn link_staticlib_by_name ( & mut self , name : & str , _verbatim : bool , _whole_archive : bool ) {
1043
1078
self . cmd . arg ( "-l" ) . arg ( name) ;
1044
1079
}
@@ -1212,6 +1247,10 @@ impl<'a> Linker for WasmLd<'a> {
1212
1247
self . cmd . arg ( "-l" ) . arg ( name) ;
1213
1248
}
1214
1249
1250
+ fn link_dylib_by_path ( & mut self , path : & Path , _as_needed : bool ) {
1251
+ self . cmd ( ) . arg ( path) ;
1252
+ }
1253
+
1215
1254
fn link_staticlib_by_name ( & mut self , name : & str , _verbatim : bool , whole_archive : bool ) {
1216
1255
if !whole_archive {
1217
1256
self . cmd . arg ( "-l" ) . arg ( name) ;
@@ -1355,10 +1394,6 @@ impl<'a> Linker for L4Bender<'a> {
1355
1394
1356
1395
fn set_output_kind ( & mut self , _output_kind : LinkOutputKind , _out_filename : & Path ) { }
1357
1396
1358
- fn link_dylib_by_name ( & mut self , _name : & str , _verbatim : bool , _as_needed : bool ) {
1359
- bug ! ( "dylibs are not supported on L4Re" ) ;
1360
- }
1361
-
1362
1397
fn link_staticlib_by_name ( & mut self , name : & str , _verbatim : bool , whole_archive : bool ) {
1363
1398
self . hint_static ( ) ;
1364
1399
if !whole_archive {
@@ -1537,6 +1572,11 @@ impl<'a> Linker for AixLinker<'a> {
1537
1572
self . cmd . arg ( format ! ( "-l{name}" ) ) ;
1538
1573
}
1539
1574
1575
+ fn link_dylib_by_path ( & mut self , path : & Path , _as_needed : bool ) {
1576
+ self . hint_dynamic ( ) ;
1577
+ self . cmd ( ) . arg ( path) ;
1578
+ }
1579
+
1540
1580
fn link_staticlib_by_name ( & mut self , name : & str , verbatim : bool , whole_archive : bool ) {
1541
1581
self . hint_static ( ) ;
1542
1582
if !whole_archive {
@@ -1738,10 +1778,6 @@ impl<'a> Linker for PtxLinker<'a> {
1738
1778
1739
1779
fn set_output_kind ( & mut self , _output_kind : LinkOutputKind , _out_filename : & Path ) { }
1740
1780
1741
- fn link_dylib_by_name ( & mut self , _name : & str , _verbatim : bool , _as_needed : bool ) {
1742
- panic ! ( "external dylibs not supported" )
1743
- }
1744
-
1745
1781
fn link_staticlib_by_name ( & mut self , _name : & str , _verbatim : bool , _whole_archive : bool ) {
1746
1782
panic ! ( "staticlibs not supported" )
1747
1783
}
@@ -1820,10 +1856,6 @@ impl<'a> Linker for LlbcLinker<'a> {
1820
1856
1821
1857
fn set_output_kind ( & mut self , _output_kind : LinkOutputKind , _out_filename : & Path ) { }
1822
1858
1823
- fn link_dylib_by_name ( & mut self , _name : & str , _verbatim : bool , _as_needed : bool ) {
1824
- panic ! ( "external dylibs not supported" )
1825
- }
1826
-
1827
1859
fn link_staticlib_by_name ( & mut self , _name : & str , _verbatim : bool , _whole_archive : bool ) {
1828
1860
panic ! ( "staticlibs not supported" )
1829
1861
}
@@ -1911,10 +1943,6 @@ impl<'a> Linker for BpfLinker<'a> {
1911
1943
1912
1944
fn set_output_kind ( & mut self , _output_kind : LinkOutputKind , _out_filename : & Path ) { }
1913
1945
1914
- fn link_dylib_by_name ( & mut self , _name : & str , _verbatim : bool , _as_needed : bool ) {
1915
- panic ! ( "external dylibs not supported" )
1916
- }
1917
-
1918
1946
fn link_staticlib_by_name ( & mut self , _name : & str , _verbatim : bool , _whole_archive : bool ) {
1919
1947
panic ! ( "staticlibs not supported" )
1920
1948
}
0 commit comments