Skip to content

Commit

Permalink
rustbuild: Fix --enable-rpath usage
Browse files Browse the repository at this point in the history
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
  • Loading branch information
alexcrichton committed Apr 12, 2016
1 parent c0221c8 commit 11ef3a9
Showing 1 changed file with 55 additions and 18 deletions.
73 changes: 55 additions & 18 deletions src/bootstrap/rustc.rs
Expand Up @@ -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()
Expand All @@ -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.
Expand Down Expand Up @@ -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!
Expand Down

0 comments on commit 11ef3a9

Please sign in to comment.