I know how to link Rust code to a C shared library. But what if I want to link to a specific version? For example, my system contains both /lib/libnv.so.0 and /lib/libnv.so.1 . If my build script prints "cargo:rustc-link-lib=nv"
, then rust links to libnv.so.1 . How can I force it to link to libnv.so.0 instead?
You probably have a symlink from libnv.so
to libnv.so.1
. The linker knows nothing about versions. You can either change the symlink (for example by installing the dev package for libnv.so.0 rather than libnv.so.1) or make a new symlink from say libfoo.so
to libnv.so.0
in a different location and add this location to the linker search path and then use cargo:rustc-link-lib=foo
. Whichever option you choose the linker will see a file which has libnv.so.0
as SONAME
rather than libnv.so.1
and in response store libnv.so.0
in the executable rather than libnv.so.1
.
Yes, I do have an libnv.so symlink. But while manually changing it may work for me, it isn't automatable. It won't work for other users. Is there anything I can do that would be fully contained within the build.rs file?
The other option I gave should work without root permission. The new symlink can be in the OUT_DIR of the build script.
Thanks, that did the trick. FTR, this is the final build.rs code:
let out_dir = env::var("OUT_DIR").unwrap();
let link = Path::join(Path::new(&out_dir), "libnv.so");
match fs::read_link(&link) {
Ok(l) if l == link => (),
Ok(_) => {
fs::remove_file(&link).unwrap();
unix::fs::symlink("/lib/libnv.so.0", &link).unwrap();
},
Err(_) => {
unix::fs::symlink("/lib/libnv.so.0", &link).unwrap();
}
}
println!("cargo:rerun-if-env-changed=OUT_DIR");
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rustc-link-search=native={out_dir}");
// Link to libnv
println!("cargo:rustc-link-lib=nv");
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.