]> git.lizzy.rs Git - rust.git/commitdiff
rustbuild: Fix --enable-rpath usage
authorAlex Crichton <alex@alexcrichton.com>
Tue, 12 Apr 2016 05:54:10 +0000 (22:54 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 12 Apr 2016 05:54:10 +0000 (22:54 -0700)
This commit fixes the `--enable-rpath` configure flag in rustbuild to work
despite the compile-time directories being different than the runtime
directories. This unfortunately means that we can't use `-C rpath` out of the
box but hopefully the portability story here isn't too bad as
`src/librustc_back/rpath.rs` isn't *too* complicated.

Closes #32886

src/bootstrap/rustc.rs

index d403d76bb1400469a289b3e8bcba592c4238f9b0..1ebf27b51adb42e1e0868571dde4eb93553a3450 100644 (file)
@@ -36,16 +36,15 @@ fn main() {
     let args = env::args_os().skip(1).collect::<Vec<_>>();
     // Detect whether or not we're a build script depending on whether --target
     // is passed (a bit janky...)
-    let is_build_script = args.iter()
-                              .position(|i| i.to_str() == Some("--target"))
-                              .is_none();
+    let target = args.windows(2).find(|w| &*w[0] == "--target")
+                                .and_then(|w| w[1].to_str());
 
     // Build scripts always use the snapshot compiler which is guaranteed to be
     // able to produce an executable, whereas intermediate compilers may not
     // have the standard library built yet and may not be able to produce an
     // executable. Otherwise we just use the standard compiler we're
     // bootstrapping with.
-    let rustc = if is_build_script {
+    let rustc = if target.is_none() {
         env::var_os("RUSTC_SNAPSHOT").unwrap()
     } else {
         env::var_os("RUSTC_REAL").unwrap()
@@ -55,7 +54,7 @@ fn main() {
     cmd.args(&args)
        .arg("--cfg").arg(format!("stage{}", env::var("RUSTC_STAGE").unwrap()));
 
-    if is_build_script {
+    if target.is_none() {
         // Build scripts are always built with the snapshot compiler, so we need
         // to be sure to set up the right path information for the OS dynamic
         // linker to find the libraries in question.
@@ -85,19 +84,57 @@ fn main() {
 
     // Set various options from config.toml to configure how we're building
     // code.
-    if env::var("RUSTC_DEBUGINFO") == Ok("true".to_string()) {
-        cmd.arg("-g");
-    }
-    if env::var("RUSTC_RPATH") == Ok("true".to_string()) {
-        cmd.arg("-Crpath");
-    }
-    let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") {
-        Ok(s) => if s == "true" {"y"} else {"n"},
-        Err(..) => "n",
-    };
-    cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions));
-    if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") {
-        cmd.arg("-C").arg(format!("codegen-units={}", s));
+    if let Some(target) = target {
+        if env::var("RUSTC_DEBUGINFO") == Ok("true".to_string()) {
+            cmd.arg("-g");
+        }
+        let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") {
+            Ok(s) => if s == "true" {"y"} else {"n"},
+            Err(..) => "n",
+        };
+        cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions));
+        if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") {
+            cmd.arg("-C").arg(format!("codegen-units={}", s));
+        }
+
+        // Dealing with rpath here is a little special, so let's go into some
+        // detail. First off, `-rpath` is a linker option on Unix platforms
+        // which adds to the runtime dynamic loader path when looking for
+        // dynamic libraries. We use this by default on Unix platforms to ensure
+        // that our nightlies behave the same on Windows, that is they work out
+        // of the box. This can be disabled, of course, but basically that's why
+        // we're gated on RUSTC_RPATH here.
+        //
+        // Ok, so the astute might be wondering "why isn't `-C rpath` used
+        // here?" and that is indeed a good question to task. This codegen
+        // option is the compiler's current interface to generating an rpath.
+        // Unfortunately it doesn't quite suffice for us. The flag currently
+        // takes no value as an argument, so the compiler calculates what it
+        // should pass to the linker as `-rpath`. This unfortunately is based on
+        // the **compile time** directory structure which when building with
+        // Cargo will be very different than the runtime directory structure.
+        //
+        // All that's a really long winded way of saying that if we use
+        // `-Crpath` then the executables generated have the wrong rpath of
+        // something like `$ORIGIN/deps` when in fact the way we distribute
+        // rustc requires the rpath to be `$ORIGIN/../lib`.
+        //
+        // So, all in all, to set up the correct rpath we pass the linker
+        // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it
+        // fun to pass a flag to a tool to pass a flag to pass a flag to a tool
+        // to change a flag in a binary?
+        if env::var("RUSTC_RPATH") == Ok("true".to_string()) {
+            let rpath = if target.contains("apple") {
+                Some("-Wl,-rpath,@loader_path/../lib")
+            } else if !target.contains("windows") {
+                Some("-Wl,-rpath,$ORIGIN/../lib")
+            } else {
+                None
+            };
+            if let Some(rpath) = rpath {
+                cmd.arg("-C").arg(format!("link-args={}", rpath));
+            }
+        }
     }
 
     // Actually run the compiler!