1- //! Script to invoke the bundled rust-lld with the correct flavor. The flavor is selected by
2- //! feature.
1+ //! Script to invoke the bundled rust-lld with the correct flavor.
32//!
43//! lld supports multiple command line interfaces. If `-flavor <flavor>` are passed as the first
54//! two arguments the `<flavor>` command line interface is used to process the remaining arguments.
87//! In Rust with `-Z gcc-ld=lld` we have gcc or clang invoke rust-lld. Since there is no way to
98//! make gcc/clang pass `-flavor <flavor>` as the first two arguments in the linker invocation
109//! and since Windows does not support symbolic links for files this wrapper is used in place of a
11- //! symbolic link. It execs `../rust-lld -flavor ld` if the feature `ld` is enabled and
12- //! `../rust-lld -flavor ld64` if `ld64` is enabled . On Windows it spawns a `..\rust-lld.exe`
10+ //! symbolic link. It execs `../rust-lld -flavor <flavor>` by propagating the flavor argument
11+ //! passed to the wrapper as the first two arguments . On Windows it spawns a `..\rust-lld.exe`
1312//! child process.
1413
15- #[ cfg( not( any( feature = "ld" , feature = "ld64" ) ) ) ]
16- compile_error ! ( "One of the features ld and ld64 must be enabled." ) ;
17-
18- #[ cfg( all( feature = "ld" , feature = "ld64" ) ) ]
19- compile_error ! ( "Only one of the feature ld or ld64 can be enabled." ) ;
20-
21- #[ cfg( feature = "ld" ) ]
22- const FLAVOR : & str = "ld" ;
23-
24- #[ cfg( feature = "ld64" ) ]
25- const FLAVOR : & str = "ld64" ;
26-
27- use std:: env;
2814use std:: fmt:: Display ;
2915use std:: path:: { Path , PathBuf } ;
30- use std:: process;
16+ use std:: { env , process} ;
3117
32- trait ResultExt < T , E > {
18+ trait UnwrapOrExitWith < T > {
3319 fn unwrap_or_exit_with ( self , context : & str ) -> T ;
3420}
3521
36- impl < T , E > ResultExt < T , E > for Result < T , E >
37- where
38- E : Display ,
39- {
22+ impl < T > UnwrapOrExitWith < T > for Option < T > {
4023 fn unwrap_or_exit_with ( self , context : & str ) -> T {
41- match self {
42- Ok ( t) => t,
43- Err ( e) => {
44- eprintln ! ( "lld-wrapper: {}: {}" , context, e) ;
45- process:: exit ( 1 ) ;
46- }
47- }
24+ self . unwrap_or_else ( || {
25+ eprintln ! ( "lld-wrapper: {}" , context) ;
26+ process:: exit ( 1 ) ;
27+ } )
4828 }
4929}
5030
51- trait OptionExt < T > {
52- fn unwrap_or_exit_with ( self , context : & str ) -> T ;
53- }
54-
55- impl < T > OptionExt < T > for Option < T > {
31+ impl < T , E : Display > UnwrapOrExitWith < T > for Result < T , E > {
5632 fn unwrap_or_exit_with ( self , context : & str ) -> T {
57- match self {
58- Some ( t) => t,
59- None => {
60- eprintln ! ( "lld-wrapper: {}" , context) ;
61- process:: exit ( 1 ) ;
62- }
63- }
33+ self . unwrap_or_else ( |err| {
34+ eprintln ! ( "lld-wrapper: {}: {}" , context, err) ;
35+ process:: exit ( 1 ) ;
36+ } )
6437 }
6538}
6639
@@ -81,14 +54,28 @@ fn get_rust_lld_path(current_exe_path: &Path) -> PathBuf {
8154}
8255
8356/// Returns the command for invoking rust-lld with the correct flavor.
57+ /// LLD only accepts the flavor argument at the first two arguments, so move it there.
8458///
8559/// Exits on error.
8660fn get_rust_lld_command ( current_exe_path : & Path ) -> process:: Command {
8761 let rust_lld_path = get_rust_lld_path ( current_exe_path) ;
8862 let mut command = process:: Command :: new ( rust_lld_path) ;
63+
64+ let mut flavor = None ;
65+ let args = env:: args_os ( )
66+ . skip ( 1 )
67+ . filter ( |arg| match arg. to_str ( ) . and_then ( |s| s. strip_prefix ( "-rustc-lld-flavor=" ) ) {
68+ Some ( suffix) => {
69+ flavor = Some ( suffix. to_string ( ) ) ;
70+ false
71+ }
72+ None => true ,
73+ } )
74+ . collect :: < Vec < _ > > ( ) ;
75+
8976 command. arg ( "-flavor" ) ;
90- command. arg ( FLAVOR ) ;
91- command. args ( env :: args_os ( ) . skip ( 1 ) ) ;
77+ command. arg ( flavor . unwrap_or_exit_with ( "-rustc-lld-flavor=<flavor> is not passed" ) ) ;
78+ command. args ( args ) ;
9279 command
9380}
9481
@@ -101,20 +88,14 @@ fn exec_lld(mut command: process::Command) {
10188
10289#[ cfg( not( unix) ) ]
10390fn exec_lld ( mut command : process:: Command ) {
104- // Windows has no exec(), spawn a child process and wait for it
91+ // Windows has no exec(), spawn a child process and wait for it.
10592 let exit_status = command. status ( ) . unwrap_or_exit_with ( "error running rust-lld child process" ) ;
106- if !exit_status. success ( ) {
107- match exit_status. code ( ) {
108- Some ( code) => {
109- // return the original lld exit code
110- process:: exit ( code)
111- }
112- None => {
113- eprintln ! ( "lld-wrapper: rust-lld child process exited with error: {}" , exit_status, ) ;
114- process:: exit ( 1 ) ;
115- }
116- }
117- }
93+ let code = exit_status
94+ . code ( )
95+ . ok_or ( exit_status)
96+ . unwrap_or_exit_with ( "rust-lld child process exited with error" ) ;
97+ // Return the original lld exit code.
98+ process:: exit ( code) ;
11899}
119100
120101fn main ( ) {
0 commit comments