@@ -170,6 +170,9 @@ 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
172
fn link_dylib_by_name ( & mut self , name : & str , verbatim : bool , as_needed : bool ) ;
173
+ fn link_dylib_by_path ( & mut self , path : & Path , _as_needed : bool ) {
174
+ self . cmd ( ) . arg ( path) ;
175
+ }
173
176
fn link_framework_by_name ( & mut self , _name : & str , _verbatim : bool , _as_needed : bool ) {
174
177
bug ! ( "framework linked with unsupported linker" )
175
178
}
@@ -320,28 +323,55 @@ impl<'a> GccLinker<'a> {
320
323
}
321
324
} else {
322
325
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( ) ) ) ;
326
+ if let Some ( name) = out_filename. file_name ( ) {
327
+ if self . sess . target . is_like_windows {
328
+ // The output filename already contains `dll_suffix` so
329
+ // the resulting import library will have a name in the
330
+ // form of libfoo.dll.a
331
+ let mut implib_name = OsString :: from ( & * self . sess . target . staticlib_prefix ) ;
332
+ implib_name. push ( name) ;
333
+ implib_name. push ( & * self . sess . target . staticlib_suffix ) ;
334
+ if let Some ( implib) = out_filename. parent ( ) . map ( |dir| dir. join ( & implib_name) ) {
335
+ let mut out_implib = OsString :: from ( "--out-implib=" ) ;
336
+ out_implib. push ( implib) ;
337
+ self . linker_arg ( out_implib) ;
340
338
}
339
+ } else {
340
+ // When dylibs are linked by a full path this value will get into `DT_NEEDED`
341
+ // instead of the full path, so the library can be later found in some other
342
+ // location than that specific path.
343
+ let mut soname = OsString :: from ( "-soname=" ) ;
344
+ soname. push ( name) ;
345
+ self . linker_arg ( soname) ;
341
346
}
342
347
}
343
348
}
344
349
}
350
+
351
+ fn open_as_needed ( & mut self , as_needed : bool ) {
352
+ if !as_needed {
353
+ if self . sess . target . is_like_osx {
354
+ // FIXME(81490): ld64 doesn't support these flags but macOS 11
355
+ // has -needed-l{} / -needed_library {}
356
+ // but we have no way to detect that here.
357
+ self . sess . dcx ( ) . emit_warn ( errors:: Ld64UnimplementedModifier ) ;
358
+ } else if self . is_gnu && !self . sess . target . is_like_windows {
359
+ self . linker_arg ( "--no-as-needed" ) ;
360
+ } else {
361
+ self . sess . dcx ( ) . emit_warn ( errors:: LinkerUnsupportedModifier ) ;
362
+ }
363
+ }
364
+ }
365
+
366
+ fn close_as_needed ( & mut self , as_needed : bool ) {
367
+ if !as_needed {
368
+ if self . sess . target . is_like_osx {
369
+ // See above FIXME comment
370
+ } else if self . is_gnu && !self . sess . target . is_like_windows {
371
+ self . linker_arg ( "--as-needed" ) ;
372
+ }
373
+ }
374
+ }
345
375
}
346
376
347
377
impl < ' a > Linker for GccLinker < ' a > {
@@ -443,27 +473,17 @@ impl<'a> Linker for GccLinker<'a> {
443
473
// to the linker.
444
474
return ;
445
475
}
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
476
self . hint_dynamic ( ) ;
477
+ self . open_as_needed ( as_needed) ;
459
478
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
- }
479
+ self . close_as_needed ( as_needed) ;
480
+ }
481
+
482
+ fn link_dylib_by_path ( & mut self , path : & Path , as_needed : bool ) {
483
+ self . hint_dynamic ( ) ;
484
+ self . open_as_needed ( as_needed) ;
485
+ self . cmd . arg ( path) ;
486
+ self . close_as_needed ( as_needed) ;
467
487
}
468
488
469
489
fn link_framework_by_name ( & mut self , name : & str , _verbatim : bool , as_needed : bool ) {
@@ -1537,6 +1557,11 @@ impl<'a> Linker for AixLinker<'a> {
1537
1557
self . cmd . arg ( format ! ( "-l{name}" ) ) ;
1538
1558
}
1539
1559
1560
+ fn link_dylib_by_path ( & mut self , path : & Path , _as_needed : bool ) {
1561
+ self . hint_dynamic ( ) ;
1562
+ self . cmd ( ) . arg ( path) ;
1563
+ }
1564
+
1540
1565
fn link_staticlib_by_name ( & mut self , name : & str , verbatim : bool , whole_archive : bool ) {
1541
1566
self . hint_static ( ) ;
1542
1567
if !whole_archive {
0 commit comments