Don't build staticlib artifacts by default when a crate is used as a dependency

Problem

Example can be found at example

I defined a no_std compatible crate as bellow

[package]
name = "static-dep"
[lib]
crate-type = ["staticlib", "cdylib", "rlib"] # Can not compile successfully
# crate-type = ["rlib"] # Compile successfully

and use it in a seperate crate

[package]
name = "using"

[dependencies]
static-dep = { version = "0.1.0"}

Although I have implemented a global allocator in crate using, cargo build still fail:

warning: dropping unsupported crate type `cdylib` for target `armv7a-none-eabi`

error: no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait

error: `#[panic_handler]` function required, but not found

warning: `static-dep` (lib) generated 1 warning
error: could not compile `static-dep` (lib) due to 2 previous errors; 1 warning emitted

This is because when building the static-deps dependency, its static library will be built, and building a static library requires it to have a GlobalAllocator. I think it makes no sense to build a static library when using a library as a dependency. If you want a static library of this library, you should build the library directly instead of expecting it to be a product of a build process.

Why not cargo rustc --crate-type=<staticlib/cdylib> ?

I noticed that it's recommanded to use cargo rustc --crate-type=staticlib to replace the crate-type defined in Cargo.toml. But in some tools, like wasm-pack, they just simply use cargo build and there is no way to use customized commands. And there is no way other than specify crate-type in Cargo.toml to make wasm-pack works. Further more, the action of building a staticlib of a dependency is meaningless. Using cargo rustc --crate-type is just an incorrect but effective shortcut

Proposed Solution

When a crate is used as a dependency, do not pass dylib, staticlib, cdylib, or bin as the crate type during compilation, so that it is used only as an rlib

What happens if rlib is not in the listed crate-types? For example Bevy has crate specifying only dylib, which is used for forcing cargo to compile Bevy and its dependencies as a dylib with the goal of reducing incremental compile times.

1 Like

I think only building rlibs and dylibs would work too. Just ignore all crate types that can't be depended on as regular rust crate.

1 Like

If I'm not mistaken, whenever a crate is used as a dependency, it is compiled into an rlib, because that's how cargo works.

Yep, and I found the culprit is staticlib, cdylib and dylib will not have an impact on normal build because crate-type cdylib and dylib will be dropped automatically while trying to build no_std target (any exceptions?)

No, dependencies with crate type dylib will be compiled as dylib and linked dynamically.

1 Like

As we mentioned above, rlib, dylib and cdylib are acceptable since dylib and cdylib will be ignored by default when we are compiling to a target without std support and fallback to rlib. I've edited the tittle

See Allow limiting required crate-types of dependencies · Issue #11232 · rust-lang/cargo · GitHub

Actually, I was inspired by your comment in this issue at the very beginning. And I noticed that there hasn't been further discussion on this issue. That's why I start this discussion to gather some updated opinions on this topic