@@ -170,6 +170,9 @@ pub trait Linker {
170170 fn cmd ( & mut self ) -> & mut Command ;
171171 fn set_output_kind ( & mut self , output_kind : LinkOutputKind , out_filename : & Path ) ;
172172 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+ }
173176 fn link_framework_by_name ( & mut self , _name : & str , _verbatim : bool , _as_needed : bool ) {
174177 bug ! ( "framework linked with unsupported linker" )
175178 }
@@ -320,28 +323,55 @@ impl<'a> GccLinker<'a> {
320323 }
321324 } else {
322325 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) ;
340338 }
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) ;
341346 }
342347 }
343348 }
344349 }
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+ }
345375}
346376
347377impl < ' a > Linker for GccLinker < ' a > {
@@ -443,27 +473,17 @@ impl<'a> Linker for GccLinker<'a> {
443473 // to the linker.
444474 return ;
445475 }
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- }
458476 self . hint_dynamic ( ) ;
477+ self . open_as_needed ( as_needed) ;
459478 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) ;
467487 }
468488
469489 fn link_framework_by_name ( & mut self , name : & str , _verbatim : bool , as_needed : bool ) {
@@ -1537,6 +1557,11 @@ impl<'a> Linker for AixLinker<'a> {
15371557 self . cmd . arg ( format ! ( "-l{name}" ) ) ;
15381558 }
15391559
1560+ fn link_dylib_by_path ( & mut self , path : & Path , _as_needed : bool ) {
1561+ self . hint_dynamic ( ) ;
1562+ self . cmd ( ) . arg ( path) ;
1563+ }
1564+
15401565 fn link_staticlib_by_name ( & mut self , name : & str , verbatim : bool , whole_archive : bool ) {
15411566 self . hint_static ( ) ;
15421567 if !whole_archive {
0 commit comments