Linking to a specific version of a shared library

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");