(The following answer is for unix)
This is about the way a binary that depends on a dynamic library looks for it when run. You can see it with $ ldd ./the-binary
.
Now, where does the binary look for the dynamic libraries? You can find all the information in the man page of ld.so
.
Long story short, when running_ the binary, the dynamic libraries are searched for in directories:
-
specified by the
-rpath=...
flag given, beforehand, to the linker when "compiling", -
then in the
LD_LIBRARY_PATH
environment variable, -
then in some places specified by some files in
/etc/ld_preload...
, -
and then in
/lib
and/usr/lib
.
The -L
linker parameter is of no use (it's just a sanity check, quite surprising to be honest).
Since you have specified the The reason it works with -C rpath
flag to rustc
in the Cargo.toml
file, I guess it must be the reason it worked in the deps
folder.cargo run
is that cargo
sets the LD_LIBRARY_PATH
to include the deps
folder.
But more generally, you need to add the -C link-args=-Wl,-rpath=PATH_TO_LIB_HERE
to the rust flags, either with the RUSTFLAGS
env var, or within the .cargo/config
file:
-
absolute path;
RUSTFLAGS="-L src/vendor -C link-args=-Wl,-rpath=$PWD/src/vendor/"
-
relative path (not recommended, since it is relative to the calling site, not to the binary location);
RUSTFLAGS="-L src/vendor -C link-args=-Wl,-rpath=./src/vendor/"
-
relative to the binary location with the
$ORIGIN
meta-variable.RUSTFLAGS='-L src/vendor -C link-args=-Wl,-rpath=$ORIGIN/../../src/vendor'
(note the single quotes:$ORIGIN
is not an env var but text which needs to be passed verbatim).
So, for instance, you could try to set the rpath
to $ORIGIN/
to make it work when the binary and the library are in the same dir.
Aside
Your extern
declaration is wrong: you should use ::libc::c_int
instead of i8
to represent C's integer type:
use ::libc::c_int;
#[link(name = "add")]
extern "C" {
fn add (a: c_int, b: c_int) -> c_int;
}