[rust-dev] Impending change in RPATH behavior when linking to Rust dynamic libraries

Brian Anderson banderson at mozilla.com
Tue Jul 8 15:57:27 PDT 2014


Very soon now the way rustc links crates dynamically is going to 
change[1], and it will impact the way you work with Rust in some 
important cases. The TL;DR is that rustc will no longer encode RPATH 
information in the binaries it produces, so the dynamic linker will be 
less likely to find the dynamic library (.so, .dylib) dependencies; in 
some scenarios people will need to use LD_LIBRARY_PATH or rely on 
higher-level tooling to arrange for libraries to be discovered by the 
dynamic linker at runtime.

[1]: https://github.com/rust-lang/rust/pull/14832

# Background

When the OS loads an executable, the dynamic linker searches some set of 
paths for it's dynamic library dependencies. If it doesn't find them, 
the program doesn't run, and for the most part the dynamic linker only 
searches a few system-defined locations, meaning that you're uninstalled 
development libraries won't be discovered by default. This is a common 
minor annoyance that is often solved by setting `LD_LIBRARY_PATH` to 
include the directories containing the dependencies.

Long ago Rust tried to solve this annoyance with RPATH. With RPATH you 
encode potential directories for the dynamic linker to search for 
dependencies *inside* the dependent libraries. rustc by default puts a 
few strategically-crafted RPATHs in its binaries that for the most part 
make the dynamic loading 'just work'.

Over time though we've concluded that we should not be doing this.

Firstly, this mechanism just doesn't work on Windows. For a while we 
tried to come up with a hack to simulate the behavior on Windows, but if 
there are any possibilities there they are very ugly and out of place in 
a language like Rust that tries not to do too much magic behind the 
scenes. As it stands now, the models on Unix and Windows are very 
different, which is a difficult discrepancy to justify.

Secondly, using RPATH is widely considered a bad practice. The primary 
risk with RPATH is that an attacker will place a substitute library on a 
known RPATH, injecting malicious code. I believe there are other 
considerations as well.

Finally, this behavior is inconsistent with other low-level languages, 
and inconsistent with the direction we've been moving in for e.g. 
library versioning. In general the user, or tools higher in the stack, 
should be in control over how they use their binaries, and Rust 
shouldn't be enforcing too much policy after compile-time.

So we're turning it off. The previous behavior can be restored by 
passing --rpath to rustc, or re-enabled for the Rust distribution itself 
by passing --enable-rpath to configure.

# Impact

Because static linking is the default in Rust, *by default* this change 
should have no impact on casual and new users unless they are explicitly 
opting in to dynamic linking.

Dynamic libraries installed as part of the Rust distribution should 
continue to be discovered correctly by the dynamic linker, modulo some 
potential bugs.

*Running rustc directly from the build directory will no longer work by 
default*. To do this either set LD_LIBRARY_PATH or pass --enable-rpath 
to the configure script.

Installing rustc to non-default locations will result in an installation 
that puts some important libraries in a location the dynamic linker 
won't find, will need to be compensated for with LD_LIBRARY_PATH.

Rust executables that link to dynamic Rust libraries outside of the 
system paths will not run without LD_LIBRARY_PATH.

Thanks. Have a nice day.

More information about the Rust-dev mailing list