I need to compile a shared C library, that is then getting used in a Command
call to another process. I wanted to make it portable by using the cc
crate instead of invoking gcc
directly in my build.rs
.
However, I can't find any pointers on how to find the path to the generated library, since cc
's main focus seems to be linking the Rust program with the generated library (not my case).
Ideally, I'd like to be able to get the path independently of build settings (target directory, debug/release mode etc.) as a Path
that I can use in my Rust program. How can I do that?
As a sidenote, even though I am using .shared_flag(true)
when building with cc
, but the generated file is still a .a
. I assume this is just a convention, and the file is still a shared library?
I think by default, cc
just put the output library in env var OUT_DIR
, but you can overwrite it. as for the actual file name, it follows the system convention, for instance, if the library name is foo
, on Windows, it should be named foo.lib
or foo.dll
, on Linux, it should be named libfoo.a
or libfoo.so
.
Since OUT_DIR
is set during compilation only, how can I access the path at runtime?
if you only want to test your program with cargo run
, the value of OUT_DIR
can be obtained using the std::env!()
macro, which expands to a &'static str
constant:
const OUT_DIR: &'static str = env!("OUT_DIR");
let path = Path::new(OUT_DIR).join("libfoo.so");
let lib = load_shared_library(path);
however, the OUT_DIR
resides within the cargo build target directory. if you want use it when your program is installed into the system, you'll have to use some external packager/installer tool, since cargo install
only concerns the program binary, it will not do anything about other resource files.
1 Like
One way would be to embed at compile time compiled library into your own executable using include_bytes!
. And at runtime extract it to filesystem and use it as a normal file.
Just in case, this is the solution I ended up following.
This is not really an issue with cc
per se, but more of an issue of "how to package the generated .so
with the Rust binary".
As mentioned in the other answers, there are multiple ways to do this, but at the end I settled for embedding the C code as a static string in the Rust source code, and storing the resulting .so
in the "output dir" that my Rust program had to create anyway for other needs.
Another solution is to use tempfile
and store it in a temporary directory, since it is only needed at runtime (it can be deleted after the Rust program is done using it).