@@ -36,16 +36,15 @@ fn main() {
3636 let args = env:: args_os ( ) . skip ( 1 ) . collect :: < Vec < _ > > ( ) ;
3737 // Detect whether or not we're a build script depending on whether --target
3838 // 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 ( ) ) ;
4241
4342 // Build scripts always use the snapshot compiler which is guaranteed to be
4443 // able to produce an executable, whereas intermediate compilers may not
4544 // have the standard library built yet and may not be able to produce an
4645 // executable. Otherwise we just use the standard compiler we're
4746 // bootstrapping with.
48- let rustc = if is_build_script {
47+ let rustc = if target . is_none ( ) {
4948 env:: var_os ( "RUSTC_SNAPSHOT" ) . unwrap ( )
5049 } else {
5150 env:: var_os ( "RUSTC_REAL" ) . unwrap ( )
@@ -55,7 +54,7 @@ fn main() {
5554 cmd. args ( & args)
5655 . arg ( "--cfg" ) . arg ( format ! ( "stage{}" , env:: var( "RUSTC_STAGE" ) . unwrap( ) ) ) ;
5756
58- if is_build_script {
57+ if target . is_none ( ) {
5958 // Build scripts are always built with the snapshot compiler, so we need
6059 // to be sure to set up the right path information for the OS dynamic
6160 // linker to find the libraries in question.
@@ -85,19 +84,57 @@ fn main() {
8584
8685 // Set various options from config.toml to configure how we're building
8786 // 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+ }
101138 }
102139
103140 // Actually run the compiler!
0 commit comments