From 8a527c474806a6d462e6bac8ff2789647ce752fd Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 11 Apr 2019 16:37:31 +0900 Subject: [PATCH] Use DYLD_FALLBACK_LIBRARY_PATH for dylib_path_envvar on macOS When loading and linking a dynamic library or bundle, dlopen searches in LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, PWD, and DYLD_FALLBACK_LIBRARY_PATH. In the Mach-O format, a dynamic library has an "install path." Clients linking against the library record this path, and the dynamic linker, dyld, uses it to locate the library. dyld searches DYLD_LIBRARY_PATH *before* the install path. dyld searches DYLD_FALLBACK_LIBRARY_PATH only if it cannot find the library in the install path. Setting DYLD_LIBRARY_PATH can easily have unintended consequences. See https://users.rust-lang.org/t/subprocess-and-dynamic-library-linking-problem-interaction/7873/10 See https://trac.macports.org/ticket/57692 See https://bugzilla.mozilla.org/show_bug.cgi?id=1536486 This is the same change as was applied to cargo in https://github.com/rust-lang/cargo/pull/6355 --- src/toolchain.rs | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/toolchain.rs b/src/toolchain.rs index aadca5e5a82..049470c6a92 100644 --- a/src/toolchain.rs +++ b/src/toolchain.rs @@ -380,7 +380,7 @@ impl<'a> Toolchain<'a> { } pub fn set_ldpath(&self, cmd: &mut Command) { - let new_path = self.path.join("lib"); + let mut new_path = vec![self.path.join("lib")]; #[cfg(not(target_os = "macos"))] mod sysenv { @@ -388,9 +388,35 @@ impl<'a> Toolchain<'a> { } #[cfg(target_os = "macos")] mod sysenv { - pub const LOADER_PATH: &str = "DYLD_LIBRARY_PATH"; + // When loading and linking a dynamic library or bundle, dlopen + // searches in LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, PWD, and + // DYLD_FALLBACK_LIBRARY_PATH. + // In the Mach-O format, a dynamic library has an "install path." + // Clients linking against the library record this path, and the + // dynamic linker, dyld, uses it to locate the library. + // dyld searches DYLD_LIBRARY_PATH *before* the install path. + // dyld searches DYLD_FALLBACK_LIBRARY_PATH only if it cannot + // find the library in the install path. + // Setting DYLD_LIBRARY_PATH can easily have unintended + // consequences. + pub const LOADER_PATH: &str = "DYLD_FALLBACK_LIBRARY_PATH"; } - env_var::prepend_path(sysenv::LOADER_PATH, vec![new_path.clone()], cmd); + #[cfg(target_os = "macos")] + if env::var_os(sysenv::LOADER_PATH) + .filter(|x| x.len() > 0) + .is_none() + { + // These are the defaults when DYLD_FALLBACK_LIBRARY_PATH isn't + // set or set to an empty string. Since we are explicitly setting + // the value, make sure the defaults still work. + if let Some(home) = env::var_os("HOME") { + new_path.push(PathBuf::from(home).join("lib")); + } + new_path.push(PathBuf::from("/usr/local/lib")); + new_path.push(PathBuf::from("/usr/lib")); + } + + env_var::prepend_path(sysenv::LOADER_PATH, new_path, cmd); // Prepend CARGO_HOME/bin to the PATH variable so that we're sure to run // cargo/rustc via the proxy bins. There is no fallback case for if the