Ferio
Ferio

Reputation: 516

How do I properly link to a Rust dynamic library from C?

I have a Cargo project named foo that produces a libfoo-<random-hash>.dylib. How do I link against it? clang only finds it if I rename it to libfoo.dylib but libfoo-<random-hash>.dylib is needed for running the program. My workaround is to manually copy and rename the lib but this can’t be the proper procedure.

My procedure to compile and run the C program is:

$ cargo build
$ cp target/debug/libfoo-*.dylib target/debug/libfoo.dylib
$ clang -lfoo -L target/debug -o bar bar.c
$ LD_LIBRARY_PATH=target/debug ./bar

Upvotes: 4

Views: 2014

Answers (2)

phg
phg

Reputation: 315

Since Rust 1.11, Cargo supports the cdylib artifact type for this exact purpose:

[lib]
name            = "foo"
crate-type      = ["rlib", "cdylib"]

This definition yields a ./target/{release,debug}/libfoo.so with all the Rust dependencies statically linked in so it can be linked into C projects right away.

Upvotes: 1

user395760
user395760

Reputation:

The hash serves a purpose: It gives a link error in case of a version mismatch (especially important with cross-crate inlining). It also allows one binaries to link to two versions of a crate (e.g., because your application uses two libraries that internally use different versions). But in the C world, nobody cares about that. If you don't care either, or care more about making it easy to link to your library, just rename the shared object to get rid of the hash.

Note that the hash is added by Cargo. If you build by directly invoking rustc, no hash is added — but nobody wants that. AFAIK Cargo doesn't offer an option to omit the hash, but you might want to try asking the developers or filing an issue.

Alternatively, you could extract the full library name (including hash) from the file name, and instruct clang to link to that. Then you get the above advantages, but it makes the build process of everyone who wants to link to your library more complicated.

Upvotes: 2

Related Questions