@@ -104,6 +104,8 @@ pub struct Compilation<'cfg> {
104104 primary_rustc_process : Option < ProcessBuilder > ,
105105
106106 target_runners : HashMap < CompileKind , Option < ( PathBuf , Vec < String > ) > > ,
107+ /// The linker to use for each host or target.
108+ target_linkers : HashMap < CompileKind , Option < PathBuf > > ,
107109}
108110
109111impl < ' cfg > Compilation < ' cfg > {
@@ -150,6 +152,13 @@ impl<'cfg> Compilation<'cfg> {
150152 . chain ( Some ( & CompileKind :: Host ) )
151153 . map ( |kind| Ok ( ( * kind, target_runner ( bcx, * kind) ?) ) )
152154 . collect :: < CargoResult < HashMap < _ , _ > > > ( ) ?,
155+ target_linkers : bcx
156+ . build_config
157+ . requested_kinds
158+ . iter ( )
159+ . chain ( Some ( & CompileKind :: Host ) )
160+ . map ( |kind| Ok ( ( * kind, target_linker ( bcx, * kind) ?) ) )
161+ . collect :: < CargoResult < HashMap < _ , _ > > > ( ) ?,
153162 } )
154163 }
155164
@@ -221,6 +230,11 @@ impl<'cfg> Compilation<'cfg> {
221230 self . target_runners . get ( & kind) . and_then ( |x| x. as_ref ( ) )
222231 }
223232
233+ /// Gets the user-specified linker for a particular host or target.
234+ pub fn target_linker ( & self , kind : CompileKind ) -> Option < PathBuf > {
235+ self . target_linkers . get ( & kind) . and_then ( |x| x. clone ( ) )
236+ }
237+
224238 /// Returns a [`ProcessBuilder`] appropriate for running a process for the
225239 /// target platform. This is typically used for `cargo run` and `cargo
226240 /// test`.
@@ -442,3 +456,39 @@ fn target_runner(
442456 )
443457 } ) )
444458}
459+
460+ /// Gets the user-specified linker for a particular host or target from the configuration.
461+ fn target_linker ( bcx : & BuildContext < ' _ , ' _ > , kind : CompileKind ) -> CargoResult < Option < PathBuf > > {
462+ // Try host.linker and target.{}.linker.
463+ if let Some ( path) = bcx
464+ . target_data
465+ . target_config ( kind)
466+ . linker
467+ . as_ref ( )
468+ . map ( |l| l. val . clone ( ) . resolve_program ( bcx. config ) )
469+ {
470+ return Ok ( Some ( path) ) ;
471+ }
472+
473+ // Try target.'cfg(...)'.linker.
474+ let target_cfg = bcx. target_data . info ( kind) . cfg ( ) ;
475+ let mut cfgs = bcx
476+ . config
477+ . target_cfgs ( ) ?
478+ . iter ( )
479+ . filter_map ( |( key, cfg) | cfg. linker . as_ref ( ) . map ( |linker| ( key, linker) ) )
480+ . filter ( |( key, _linker) | CfgExpr :: matches_key ( key, target_cfg) ) ;
481+ let matching_linker = cfgs. next ( ) ;
482+ if let Some ( ( key, linker) ) = cfgs. next ( ) {
483+ anyhow:: bail!(
484+ "several matching instances of `target.'cfg(..)'.linker` in configurations\n \
485+ first match `{}` located in {}\n \
486+ second match `{}` located in {}",
487+ matching_linker. unwrap( ) . 0 ,
488+ matching_linker. unwrap( ) . 1 . definition,
489+ key,
490+ linker. definition
491+ ) ;
492+ }
493+ Ok ( matching_linker. map ( |( _k, linker) | linker. val . clone ( ) . resolve_program ( bcx. config ) ) )
494+ }
0 commit comments