@@ -36,16 +36,15 @@ fn main() {
36
36
let args = env:: args_os ( ) . skip ( 1 ) . collect :: < Vec < _ > > ( ) ;
37
37
// Detect whether or not we're a build script depending on whether --target
38
38
// is passed (a bit janky...)
39
- let is_build_script = args. iter ( )
40
- . position ( |i| i. to_str ( ) == Some ( "--target" ) )
41
- . is_none ( ) ;
39
+ let target = args. windows ( 2 ) . find ( |w| & * w[ 0 ] == "--target" )
40
+ . and_then ( |w| w[ 1 ] . to_str ( ) ) ;
42
41
43
42
// Build scripts always use the snapshot compiler which is guaranteed to be
44
43
// able to produce an executable, whereas intermediate compilers may not
45
44
// have the standard library built yet and may not be able to produce an
46
45
// executable. Otherwise we just use the standard compiler we're
47
46
// bootstrapping with.
48
- let rustc = if is_build_script {
47
+ let rustc = if target . is_none ( ) {
49
48
env:: var_os ( "RUSTC_SNAPSHOT" ) . unwrap ( )
50
49
} else {
51
50
env:: var_os ( "RUSTC_REAL" ) . unwrap ( )
@@ -55,7 +54,7 @@ fn main() {
55
54
cmd. args ( & args)
56
55
. arg ( "--cfg" ) . arg ( format ! ( "stage{}" , env:: var( "RUSTC_STAGE" ) . unwrap( ) ) ) ;
57
56
58
- if is_build_script {
57
+ if target . is_none ( ) {
59
58
// Build scripts are always built with the snapshot compiler, so we need
60
59
// to be sure to set up the right path information for the OS dynamic
61
60
// linker to find the libraries in question.
@@ -85,19 +84,57 @@ fn main() {
85
84
86
85
// Set various options from config.toml to configure how we're building
87
86
// code.
88
- if env:: var ( "RUSTC_DEBUGINFO" ) == Ok ( "true" . to_string ( ) ) {
89
- cmd. arg ( "-g" ) ;
90
- }
91
- if env:: var ( "RUSTC_RPATH" ) == Ok ( "true" . to_string ( ) ) {
92
- cmd. arg ( "-Crpath" ) ;
93
- }
94
- let debug_assertions = match env:: var ( "RUSTC_DEBUG_ASSERTIONS" ) {
95
- Ok ( s) => if s == "true" { "y" } else { "n" } ,
96
- Err ( ..) => "n" ,
97
- } ;
98
- cmd. arg ( "-C" ) . arg ( format ! ( "debug-assertions={}" , debug_assertions) ) ;
99
- if let Ok ( s) = env:: var ( "RUSTC_CODEGEN_UNITS" ) {
100
- cmd. arg ( "-C" ) . arg ( format ! ( "codegen-units={}" , s) ) ;
87
+ if let Some ( target) = target {
88
+ if env:: var ( "RUSTC_DEBUGINFO" ) == Ok ( "true" . to_string ( ) ) {
89
+ cmd. arg ( "-g" ) ;
90
+ }
91
+ let debug_assertions = match env:: var ( "RUSTC_DEBUG_ASSERTIONS" ) {
92
+ Ok ( s) => if s == "true" { "y" } else { "n" } ,
93
+ Err ( ..) => "n" ,
94
+ } ;
95
+ cmd. arg ( "-C" ) . arg ( format ! ( "debug-assertions={}" , debug_assertions) ) ;
96
+ if let Ok ( s) = env:: var ( "RUSTC_CODEGEN_UNITS" ) {
97
+ cmd. arg ( "-C" ) . arg ( format ! ( "codegen-units={}" , s) ) ;
98
+ }
99
+
100
+ // Dealing with rpath here is a little special, so let's go into some
101
+ // detail. First off, `-rpath` is a linker option on Unix platforms
102
+ // which adds to the runtime dynamic loader path when looking for
103
+ // dynamic libraries. We use this by default on Unix platforms to ensure
104
+ // that our nightlies behave the same on Windows, that is they work out
105
+ // of the box. This can be disabled, of course, but basically that's why
106
+ // we're gated on RUSTC_RPATH here.
107
+ //
108
+ // Ok, so the astute might be wondering "why isn't `-C rpath` used
109
+ // here?" and that is indeed a good question to task. This codegen
110
+ // option is the compiler's current interface to generating an rpath.
111
+ // Unfortunately it doesn't quite suffice for us. The flag currently
112
+ // takes no value as an argument, so the compiler calculates what it
113
+ // should pass to the linker as `-rpath`. This unfortunately is based on
114
+ // the **compile time** directory structure which when building with
115
+ // Cargo will be very different than the runtime directory structure.
116
+ //
117
+ // All that's a really long winded way of saying that if we use
118
+ // `-Crpath` then the executables generated have the wrong rpath of
119
+ // something like `$ORIGIN/deps` when in fact the way we distribute
120
+ // rustc requires the rpath to be `$ORIGIN/../lib`.
121
+ //
122
+ // So, all in all, to set up the correct rpath we pass the linker
123
+ // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it
124
+ // fun to pass a flag to a tool to pass a flag to pass a flag to a tool
125
+ // to change a flag in a binary?
126
+ if env:: var ( "RUSTC_RPATH" ) == Ok ( "true" . to_string ( ) ) {
127
+ let rpath = if target. contains ( "apple" ) {
128
+ Some ( "-Wl,-rpath,@loader_path/../lib" )
129
+ } else if !target. contains ( "windows" ) {
130
+ Some ( "-Wl,-rpath,$ORIGIN/../lib" )
131
+ } else {
132
+ None
133
+ } ;
134
+ if let Some ( rpath) = rpath {
135
+ cmd. arg ( "-C" ) . arg ( format ! ( "link-args={}" , rpath) ) ;
136
+ }
137
+ }
101
138
}
102
139
103
140
// Actually run the compiler!
0 commit comments