Changing external crate's linkage to C library from dynamic to static


#1

Example: I’m using rust-sqlite3 which (by rustc’s default) dynamically links against libsqlite3-xyz.{so,dll}.

How do I change this to static linking, preferably depending on the platform?

I’ve tried a build.rs with:

if cfg!(windows) {
    println!("cargo:rustc-link-lib=static=sqlite3");
}

and the flag gets passed to rustc correctly, but still sqlite3 is dynamically linked, most probably because the option doesn’t override what’s in the external crate.


#2

rust-sqlite actually doesn’t do any hinting on whether to prefer static or dynamic, as far as I can tell.

http://doc.crates.io/manifest.html#building-dynamic-or-static-libraries

The available options are dylib, rlib, and staticlib. You should only use this option in a project. Cargo will always compile packages (dependencies) based on the requirements of the project that includes them.

So it looks like if your crate is a library and you compile it as a static lib, it will link all dependencies statically. If you’re building an executable, you can put the stuff that links to rust-sqlite in a library and configure it to link statically, then have your executable call into it.

There’s also target-triple overrides covered under http://doc.crates.io/manifest.html#the-dependencies-section, but it doesn’t say how to force dynamic/static.


#3

To change the linkage of a native library to an upstream crate it’ll require that the crate has both a build script and a links manifest key, and if those are in place you can provide an override to specify your own custom place and location to link it. Note, though, that this only works if the library is linked via a build script, whereas in rust-sqlite3 it looks like it’s linked in the source which isn’t something that can be retroactively changed unfortunately.