It is quite common for Rust projects to be split into two crates: a library crate and a bin crate (with the bin crate depending on the library crate)[1], so that the CLI can have additional dependencies[2] and that both can have their own independent version.
This does however pose a dilemma for projects where the library and the binary are intended to share the same name:
- For libraries the most intuitive installation procedure is if you can just run
cargo add <library>
and then import the library withuse <library>;
. - For applications the most intuitive installation procedure is
cargo install <command>
and then being able to just run<command>
.
While Rust does let libraries and binaries with the same name co-exist (via lib.name
or bin.name
), to publish both crates on crates.io, one of the crates will have to be named differently than its primary artifact.
Personally the first of the above points takes priority for me, so if I have a project foobar
, I'd name the library crate foobar
and the CLI crate foobar-cli
. This does however result in the following UX problem:
To obtain the foobar
command, users will be tempted to run cargo install foobar
, which will however inevitably fail with the error message:
$ cargo install foobar
Updating crates.io index
error: there is nothing to install in `foobar v0.1.0`, because it has no binaries
`cargo install` is only for installing programs, and can't be used with libraries.
To use a library crate, add it as a dependency in a Cargo project instead.
My problem with this error message is that it does not tell the user about the existence of the foobar-cli
crate. While cargo could check if such a crate existed, it of course should not assume anything about the purpose of crates just by their names.
So I was thinking how we could cleanly[3] solve this UX problem and thought we may want to introduce a new Cargo.toml
field package.recommended-bin-crates
so that in the above example the Cargo.toml
from the foobar
library crate could configure:
[package]
name = "foobar"
# etc.
recommended-bin-crates = ["foobar-cli"]
Which could then be picked up by the cargo install
command when it detects that the crate doesn't have any binaries, to display a message such as the following to the user:
The developers of
foobar
suggest you may want to installfoobar-cli
instead.
What do you think about this dilemma / my idea? I'd be alright with writing an RFC for such a new recommended-bin-crates
field, but I'm posting here first for some initial feedback
Prominent examples of that are
diesel
&diesel-cli
orwasm-bindgen
&wasm-bindgen-cli
. âŠī¸Since cargo currently doesn't support target-specific dependencies, see also the recently started RFC 3374. âŠī¸
The
clippy
crate uses a failing build script to makecargo install clippy
print a message about using rustup ... however I'd really rather not resort to such hacks for my own projects, especially because this could also result in some user confusion (e.g. lib.rs would display theapp
label for the library-only crate). âŠī¸