-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
Short description
Rust linking system has one big problem now, that blocks possibility to have a given rust package to be installed and to be developed on the same system.
tl;dr: when you have a library installed system wide and you are developing package that contains this library (and uses other system wide installed libs) you'll have problems with linking because of
error: multiple dylib candidates for `hello_world` found
Example projects
Consider the minimal example, think we have those projects:
- A library
- A project that has executables + libraries
A library project looks like this:
jauhien@zcj linking % cat hello_lib/hello_lib.rs
#![crate_type = "dylib"]
pub fn hello(name: &str) -> String {
"Hello, ".to_string() + name + "!".to_string()
}
A project with binary and library looks like this:
jauhien@zcj linking % cat hello_world/hello_world.rs
#![crate_type = "dylib"]
extern crate hello_lib;
use hello_lib::hello;
pub fn hello_name(name: &str, surname: &str) -> String {
hello((name.to_string() + " " + surname).as_slice())
}
jauhien@zcj linking % cat hello_world/hello.rs
#![crate_type = "bin"]
extern crate hello_world;
use hello_world::hello_name;
fn main() {
println!("{}", hello_name("Test", "Test"))
}
Steps to reproduce the error
I use 'image' directory as root here.
-
Compile and install hello_lib library
jauhien@zcj hello_lib % rustc hello_lib.rs jauhien@zcj hello_lib % cp libhello_lib.so ../image/usr/lib
-
Compile and install hello_world project that uses hello_lib
jauhien@zcj hello_world % rustc hello_world.rs -L ../image/usr/lib jauhien@zcj hello_world % rustc hello.rs -L . -L ../image/usr/lib jauhien@zcj hello_world % cp libhello_world.so ../image/usr/lib jauhien@zcj hello_world % cp hello ../image/usr/bin
Test if it works:
jauhien@zcj hello_world % LD_LIBRARY_PATH=../image/usr/lib ../image/usr/bin/hello Hello, Test Test!
-
Continue developing of hello_world project and try to recompile it
jauhien@zcj hello_world % rustc hello_world.rs -L ../image/usr/lib jauhien@zcj hello_world % rustc hello.rs -L . -L ../image/usr/lib hello.rs:3:1: 3:26 error: multiple dylib candidates for `hello_world` found hello.rs:3 extern crate hello_world; ^~~~~~~~~~~~~~~~~~~~~~~~~ hello.rs:3:1: 3:26 note: candidate #1: /home/jauhien/work/rust/linking/hello_world/libhello_world.so hello.rs:3 extern crate hello_world; ^~~~~~~~~~~~~~~~~~~~~~~~~ hello.rs:3:1: 3:26 note: candidate #2: /home/jauhien/work/rust/linking/image/usr/lib/libhello_world.so hello.rs:3 extern crate hello_world; ^~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error
Conclusions
So we have problem with current linking system. It is bad because
- it makes not possible to develop rust software on the machine that has already installed version of this software (as rust infrastructure will grow, nearly every project will use libraries from system)
- it leads to problems with packaging rust software (and rust compiler itself), see e.g. Build with --llvm-root=$DIR fails when Rust is already installed into $DIR #13421, https://github.com/Heather/gentoo-rust/issues/19 and Cannot link to third-party Rust libraries in the same prefix
rustc
was installed to #13733
I think that this issue can be solved if some algorithm that chooses which dynamic library to use depending on the order of -L flags is introduced to linking code. That means, e.g. use libraries found under the earliest -L path and ignore others.