[rust-dev] Impending change in RPATH behavior when linking to Rust dynamic libraries
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, 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.
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.
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
*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