8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
+ use cc:: windows_registry;
11
12
use super :: archive:: { ArchiveBuilder , ArchiveConfig } ;
12
13
use super :: bytecode:: RLIB_BYTECODE_EXTENSION ;
13
14
use super :: linker:: Linker ;
@@ -35,7 +36,6 @@ use llvm;
35
36
use std:: ascii;
36
37
use std:: char;
37
38
use std:: env;
38
- use std:: ffi:: OsString ;
39
39
use std:: fmt;
40
40
use std:: fs;
41
41
use std:: io;
@@ -58,9 +58,7 @@ pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_o
58
58
// The third parameter is for env vars, used on windows to set up the
59
59
// path for MSVC to find its DLLs, and gcc to find its bundled
60
60
// toolchain
61
- pub fn get_linker ( sess : & Session ) -> ( PathBuf , Command , Vec < ( OsString , OsString ) > ) {
62
- let envs = vec ! [ ( "PATH" . into( ) , command_path( sess) ) ] ;
63
-
61
+ pub fn get_linker ( sess : & Session ) -> ( PathBuf , Command ) {
64
62
// If our linker looks like a batch script on Windows then to execute this
65
63
// we'll need to spawn `cmd` explicitly. This is primarily done to handle
66
64
// emscripten where the linker is `emcc.bat` and needs to be spawned as
@@ -75,60 +73,57 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString)
75
73
return Command :: bat_script ( linker)
76
74
}
77
75
}
78
- Command :: new ( linker)
79
- } ;
80
-
81
- if let Some ( ref linker) = sess. opts . cg . linker {
82
- ( linker. clone ( ) , cmd ( linker) , envs)
83
- } else if sess. target . target . options . is_like_msvc {
84
- let ( cmd, envs) = msvc_link_exe_cmd ( sess) ;
85
- ( PathBuf :: from ( "link.exe" ) , cmd, envs)
86
- } else if let LinkerFlavor :: Lld ( f) = sess. linker_flavor ( ) {
87
- let linker = PathBuf :: from ( & sess. target . target . options . linker ) ;
88
- let cmd = Command :: lld ( & linker, f) ;
89
- ( linker, cmd, envs)
90
- } else {
91
- let linker = PathBuf :: from ( & sess. target . target . options . linker ) ;
92
- let cmd = cmd ( & linker) ;
93
- ( linker, cmd, envs)
94
- }
95
- }
76
+ match sess. linker_flavor ( ) {
77
+ LinkerFlavor :: Lld ( f) => Command :: lld ( linker, f) ,
78
+ _ => Command :: new ( linker) ,
96
79
97
- #[ cfg( windows) ]
98
- pub fn msvc_link_exe_cmd ( sess : & Session ) -> ( Command , Vec < ( OsString , OsString ) > ) {
99
- use cc:: windows_registry;
80
+ }
81
+ } ;
100
82
101
- let target = & sess. opts . target_triple ;
102
- let tool = windows_registry:: find_tool ( target, "link.exe" ) ;
83
+ let msvc_tool = windows_registry:: find_tool ( & sess. opts . target_triple , "link.exe" ) ;
103
84
104
- if let Some ( tool) = tool {
105
- let mut cmd = Command :: new ( tool. path ( ) ) ;
106
- cmd. args ( tool. args ( ) ) ;
107
- for & ( ref k, ref v) in tool. env ( ) {
108
- cmd. env ( k, v) ;
109
- }
110
- let envs = tool. env ( ) . to_vec ( ) ;
111
- ( cmd, envs)
112
- } else {
113
- debug ! ( "Failed to locate linker." ) ;
114
- ( Command :: new ( "link.exe" ) , vec ! [ ] )
115
- }
116
- }
85
+ let linker_path = sess. opts . cg . linker . as_ref ( ) . map ( |s| & * * s)
86
+ . or ( sess. target . target . options . linker . as_ref ( ) . map ( |s| s. as_ref ( ) ) )
87
+ . unwrap_or ( match sess. linker_flavor ( ) {
88
+ LinkerFlavor :: Msvc => {
89
+ msvc_tool. as_ref ( ) . map ( |t| t. path ( ) ) . unwrap_or ( "link.exe" . as_ref ( ) )
90
+ }
91
+ LinkerFlavor :: Em if cfg ! ( windows) => "emcc.bat" . as_ref ( ) ,
92
+ LinkerFlavor :: Em => "emcc" . as_ref ( ) ,
93
+ LinkerFlavor :: Gcc => "cc" . as_ref ( ) ,
94
+ LinkerFlavor :: Ld => "ld" . as_ref ( ) ,
95
+ LinkerFlavor :: Lld ( _) => "lld" . as_ref ( ) ,
96
+ } ) ;
117
97
118
- #[ cfg( not( windows) ) ]
119
- pub fn msvc_link_exe_cmd ( _sess : & Session ) -> ( Command , Vec < ( OsString , OsString ) > ) {
120
- ( Command :: new ( "link.exe" ) , vec ! [ ] )
121
- }
98
+ let mut cmd = cmd ( linker_path) ;
122
99
123
- fn command_path ( sess : & Session ) -> OsString {
124
100
// The compiler's sysroot often has some bundled tools, so add it to the
125
101
// PATH for the child.
126
102
let mut new_path = sess. host_filesearch ( PathKind :: All )
127
103
. get_tools_search_paths ( ) ;
128
- if let Some ( path) = env:: var_os ( "PATH" ) {
129
- new_path. extend ( env:: split_paths ( & path) ) ;
104
+ let mut msvc_changed_path = false ;
105
+ if sess. target . target . options . is_like_msvc {
106
+ if let Some ( ref tool) = msvc_tool {
107
+ cmd. args ( tool. args ( ) ) ;
108
+ for & ( ref k, ref v) in tool. env ( ) {
109
+ if k == "PATH" {
110
+ new_path. extend ( env:: split_paths ( v) ) ;
111
+ msvc_changed_path = true ;
112
+ } else {
113
+ cmd. env ( k, v) ;
114
+ }
115
+ }
116
+ }
130
117
}
131
- env:: join_paths ( new_path) . unwrap ( )
118
+
119
+ if !msvc_changed_path {
120
+ if let Some ( path) = env:: var_os ( "PATH" ) {
121
+ new_path. extend ( env:: split_paths ( & path) ) ;
122
+ }
123
+ }
124
+ cmd. env ( "PATH" , env:: join_paths ( new_path) . unwrap ( ) ) ;
125
+
126
+ ( linker_path. to_path_buf ( ) , cmd)
132
127
}
133
128
134
129
pub fn remove ( sess : & Session , path : & Path ) {
@@ -618,9 +613,7 @@ fn link_natively(sess: &Session,
618
613
let flavor = sess. linker_flavor ( ) ;
619
614
620
615
// The invocations of cc share some flags across platforms
621
- let ( pname, mut cmd, envs) = get_linker ( sess) ;
622
- // This will set PATH on windows
623
- cmd. envs ( envs) ;
616
+ let ( pname, mut cmd) = get_linker ( sess) ;
624
617
625
618
let root = sess. target_filesearch ( PathKind :: Native ) . get_lib_path ( ) ;
626
619
if let Some ( args) = sess. target . target . options . pre_link_args . get ( & flavor) {
0 commit comments