Say I created a static library libfoo.a using crate-type = ["staticlib"]. How would I use this in another rust project (aka rustc bar.rs --extern foo=libfoo.a)?
(I tried setting crate-type = ["rlib"] and using it like specified here, but I get (libloading is a dependency of foo)
error[E0463]: can't find crate for `libloading` which `foo` depends on)
My use case is as follows -
- Crate
foo implements several structs, traits and functions. I wish to compile this down to a single file (like the .so file generated in C++). Note that this crate contains several dependencies managed by cargo.
- Crate
bar then links to this file (rustc bar.rs -L libfoo.xyz).
The problem here is that libfoo.rlib/libfoo.so doesn't include the dependencies of crate foo, and thus I get: error[E0463]: can't find crate for `libloading` which `foo` depends on.
One way around this is rustc bar.rs -L /path/to/foo/target/release/deps -L libfoo.xyz which compiles bar successfully.
Is it possible to archive the required dependencies into a single file?
*.so would contain all the dependencies necessary. How are you using it from bar?
Minimal reproducible example:
// Cargo.toml
[package]
name = "testing"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["dylib"]
[dependencies]
rand = "0.8.5"
// src/lib.rs
pub fn print_rand() {
let x: f64 = rand::random();
println!("Hello, world: {}", x);
}
Running cargo build --release creates file target/release/libtesting.so.
// temp.rs
extern crate testing;
fn main() {
testing::print_rand();
}
Running rustc temp.rs --extern testing=./target/release/libtesting.so gives:
error[E0463]: can't find crate for `rand` which `testing` depends on
--> tmp.rs:1:1
|
1 | extern crate testing;
| ^^^^^^^^^^^^^^^^^^^^^ can't find crate
error: aborting due to previous error
For more information about this error, try `rustc --explain E0463`.
The staticlib and cdylib crate types are primarily intended as self-contained binaries that can be used via their C API. It's quite possible for one Rust crate to use another Rust crate through its C API (e.g. by writing extern bindings and using FFI-safe types), but unless you have exotic constraints (e.g. can only use pre-compiled libraries for IP/distribution reasons) this is probably not the path you want to go down.
Normally, you'll use cargo to build your application and add an entry to the [dependencies] section of your Cargo.toml file. The Dependencies chapter of The Cargo Book explains a bit about adding dependencies, but if you want to use something that hasn't been published to crates.io you can use a path dependency.
[package]
name = "temp"
[dependencies]
testing = { path "./path/to/testing" }
Cargo will then make sure your dependency is compiled to a rlib so it can be linked to your library. You can see the actual calls to rustc by running cargo build --verbose.
If you do have particular circumstances which mean you can't just add the crate to your Cargo.toml and must depend on a *.a or *.so file, you should be able to treat it like any other native library and follow various FFI guides on how to achieve the linking part (e.g. The Nomicon has a chapter on FFI).
That clears it. Thanks a lot Michael!