The following compiles fine:
[package]
name = "foo"
version = "0.1.0"
edition = "2024"
[dependencies]
[lib]
name = "foo"
path = "lib.rs"
[[bin]]
name = "bar"
path = "main.rs"
// main.rs
use foo::test;
fn main () {
test();
println!("Yay!");
}
// lib.rs
pub fn test() {}
However, when I add the key crate-type = ["staticlib"]
to the [lib]
table in Cargo.toml
, I get:
error[E0432]: unresolved import `foo`
--> main.rs:1:5
|
1 | use foo::test;
| ^^^ use of undeclared crate or module `foo`
For more information about this error, try `rustc --explain E0432`.
error: could not compile `foo` (bin "bar") due to 1 previous error
warning: build failed, waiting for other jobs to finish...
Why exactly is Cargo getting upset here? I'd expect not much to be different at the codegen stage, and when linking it could still find the necessary objects in the static library. Then again, I'm nowhere near an expert on Rust.
1 Like
Just a guess, but since you're linking with a Rust binary as well as producing a static lib, I'd try:
crate-type = ["lib", "staticlib"]
1 Like
Sure, that works. Using a static lib is part of a design choice that I should probably rethink... (Edit: It seems LTO achieves what I was going for.) I'm still curious why the original didn't work.
1 Like
When you specified crate-type = ["staticlib"]
you override the default of lib
, which is what allows the library to be usable in other Rust crates, like your main
. Specifying lib
along with staticlib
makes it available again.
1 Like
Naming of these things is such a mess.
Library crates in Rust are also static libraries. The lib
crate type that generates an .rlib
file is a static library. It's almost the same thing as .a
static library, with just extra metadata for Rust.
The staticlib
crate type is also a static library, but intentionally not used for Rust. It's meant for C only, so when it's not used in your Rust binary that's not a bug or limitation, but the main purpose of this type.
And static libraries are very different from standalone/redistributable .so
/.dll
libraries (which Rust calls cdylib
).
Static libraries are just a bunch of object files saved together, but they're not a standalone thing, but more like temporary files of an unfinished compilation. They still need linking, and implicitly depend on the build settings and everything else that will be added at the linking stage. So in either case it's the binary build that does the linking, and doesn't depend on the static library after linking.
Yeah, something like "solib" or even "dll" instead of "cdylib" would have been more explicit, and maybe "alib" for "staticlib". But we're stuck with what we have.
"dynamic library" is a common "generic" name for .so/.dll, so contracting it to dylib
and adding a c
prefix for the c-abi version is sensible enough. In contrast against lib
/ staticlib
for the rust and c-abi versions of static linking it looks positively self-documenting. I assume it would be too much trouble to rename staticlib
to clib
at this point.
1 Like