Skip to content

Commit 3dd88f6

Browse files
committed
Auto merge of #32903 - alexcrichton:fix-rpath, r=brson
rustbuild: Fix --enable-rpath usage 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
2 parents 9cf6fba + 11ef3a9 commit 3dd88f6

File tree

1 file changed

+55
-18
lines changed

1 file changed

+55
-18
lines changed

src/bootstrap/rustc.rs

+55-18
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)