From 1b8e6c152c827751ee22bf8cfca6f6ca4ade2798 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 17 Dec 2016 14:11:02 -0800 Subject: [PATCH] rustbuild: Fix LC_ID_DYLIB directives on OSX Currently libraries installed by rustbuild on OSX have an incorrect `LC_ID_DYLIB` directive located in the dynamic libraries that are installed. The directive we expect looks like: @rpath/libstd.dylib Which means that if you want to find that dynamic library you should look at the dylib's other `@rpath` directives. Typically our `@rpath` directives look like `@loader_path/../lib` for the compiler as that's where the installed libraries will be located. Currently, though, rustbuild produces dylibs with the directive that looks like: /Users/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-mac/build/build/x86_64-apple-darwin/stage1-std/x86_64-apple-darwin/release/deps/libstd-713ad88203512705.dylib In other words, the build directory is encoded erroneously. The compiler already [knows how] to change this directive, but it only passes that argument when `-C rpath` is also passed. The rustbuild system, however, explicitly [does not pass] this option explicitly and instead bakes its own. This logic then also erroneously didn't pass `-Wl,-install_name` like the compiler. [knows how]: https://github.com/rust-lang/rust/blob/4a008cccaabc8b3fe65ccf5868b9d16319c9ac58/src/librustc_trans/back/linker.rs#L210-L214 [does not pass]: https://github.com/rust-lang/rust/blob/4a008cccaabc8b3fe65ccf5868b9d16319c9ac58/src/bootstrap/bin/rustc.rs#L133-L158 To fix this regression this patch introduces a new `-Z` flag, `-Z osx-rpath-install-name` which basically just forces the compiler to take the previous `-install_name` branch when creating a dynamic library. Hopefully we can sort out a better rpath story in the future, but for now this "hack" should suffice in getting our nightly builds back to the same state as before. Closes #38430 --- src/bootstrap/bin/rustc.rs | 9 +++++++++ src/librustc/session/config.rs | 2 ++ src/librustc_trans/back/linker.rs | 7 ++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 2f674a311fef4..20ff9d9af3c0e 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -158,6 +158,15 @@ fn main() { // to change a flag in a binary? if env::var("RUSTC_RPATH") == Ok("true".to_string()) { let rpath = if target.contains("apple") { + + // Note that we need to take one extra step on OSX to also pass + // `-Wl,-instal_name,@rpath/...` to get things to work right. To + // do that we pass a weird flag to the compiler to get it to do + // so. Note that this is definitely a hack, and we should likely + // flesh out rpath support more fully in the future. + if stage != "0" { + cmd.arg("-Z").arg("osx-rpath-install-name"); + } Some("-Wl,-rpath,@loader_path/../lib") } else if !target.contains("windows") { Some("-Wl,-rpath,$ORIGIN/../lib") diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index e500c08ce6e32..a415d1f991fcd 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -928,6 +928,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "print some statistics about MIR"), always_encode_mir: bool = (false, parse_bool, [TRACKED], "encode MIR of all functions into the crate metadata"), + osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], + "pass `-install_name @rpath/...` to the OSX linker"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 040a05b69a3a5..a147b598940a2 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -207,7 +207,12 @@ impl<'a> Linker for GnuLinker<'a> { if self.sess.target.target.options.is_like_osx { self.cmd.args(&["-dynamiclib", "-Wl,-dylib"]); - if self.sess.opts.cg.rpath { + // Note that the `osx_rpath_install_name` option here is a hack + // purely to support rustbuild right now, we should get a more + // principled solution at some point to force the compiler to pass + // the right `-Wl,-install_name` with an `@rpath` in it. + if self.sess.opts.cg.rpath || + self.sess.opts.debugging_opts.osx_rpath_install_name { let mut v = OsString::from("-Wl,-install_name,@rpath/"); v.push(out_filename.file_name().unwrap()); self.cmd.arg(&v);