Skip to content

Commit 7e3e9c6

Browse files
recommended-bin-crates: Initial draft
1 parent cd3edd4 commit 7e3e9c6

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

text/0000-recommended-bin-crates.md

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
- Feature Name: recommended-bin-crates
2+
- Start Date: 2023-01-04
3+
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
4+
5+
# Summary
6+
[summary]: #summary
7+
8+
Add an optional `recommended-bin-crates` field to the `[package]`
9+
section of `Cargo.toml`, to enable crate authors to point out related
10+
binary crates in the error message Cargo users get when attempting to
11+
`cargo install` a crate without binaries.
12+
13+
# Motivation
14+
[motivation]: #motivation
15+
16+
Command-line tools written in Rust are often published in crates named
17+
different than the command, since that name is already occupied by a
18+
related library crate, for instance:
19+
20+
* the `diesel` command is provided by the `diesel_cli` binary crate,
21+
that depends on the `diesel` library crate
22+
23+
* the `wasm-bindgen` command is provided by the `wasm-bindgen-cli`
24+
binary crate, which is different from the `wasm-bindgen` library crate
25+
26+
While such a setup has several benefits, it currently leads to a
27+
user experience problem with Cargo: To obtain a command, users will be
28+
tempted to run `cargo install <command>`, which will however inevitably fail:
29+
30+
```
31+
$ cargo install diesel
32+
error: there is nothing to install in `diesel v2.0.3`, because it has no binaries
33+
`cargo install` is only for installing programs, and can't be used with libraries.
34+
To use a library crate, add it as a dependency in a Cargo project instead.
35+
```
36+
37+
The idea of this RFC is that the `Cargo.toml` of such
38+
a library-only crate could specify for instance:
39+
40+
```toml
41+
[package]
42+
name = "diesel"
43+
# ...
44+
recommended-bin-crates = ["diesel-cli"]
45+
```
46+
47+
which could be picked up by Cargo in order to additionally include
48+
a note such as the following in the above error message:
49+
50+
> The developers of `diesel` suggest you may want to install `diesel-cli` instead.
51+
52+
resulting in a more seamless user experience.
53+
54+
# Guide-level explanation
55+
[guide-level-explanation]: #guide-level-explanation
56+
57+
The following is written as if it was part of the [manifest page] of the Cargo Book.
58+
59+
## The `recommended-bin-crates` field
60+
61+
The `recommended-bin-crates` field is an array of names of related binary crates.
62+
63+
```toml
64+
[package]
65+
name = "foobar"
66+
# ...
67+
recommended-bin-crates = ["foobar-cli"]
68+
```
69+
70+
Specifying this field for a library-only crate, enables Cargo to print
71+
a more user-friendly error message for `cargo install`, for example:
72+
73+
```
74+
$ cargo install foobar
75+
error: there is nothing to install in `foobar v1.2.3`, because it has no binaries
76+
`cargo install` is only for installing programs, and can't be used with libraries.
77+
To use a library crate, add it as a dependency in a Cargo project instead.
78+
79+
The developers of `foobar` suggest you may want to install `foobar-cli` instead.
80+
```
81+
82+
(Notice the last line in the above output, which is enabled by the
83+
`recommended-bin-crates` field.)
84+
85+
# Reference-level explanation
86+
[reference-level-explanation]: #reference-level-explanation
87+
88+
The `cargo-install` command has already parsed the `Cargo.toml` manifest
89+
file when it prints this error message, so it would simply have to
90+
additionally check for this new field when printing the error message.
91+
92+
# Drawbacks
93+
[drawbacks]: #drawbacks
94+
95+
* It introduces yet another manifest `field`.
96+
* The crates referenced by this field could become abandoned, out-of-date or yanked.
97+
* Updating this field for a library crate requires you to bump its version.
98+
99+
# Rationale and alternatives
100+
[rationale-and-alternatives]: #rationale-and-alternatives
101+
102+
The problem addressed by this RFC can be sidestepped by publishing the
103+
library along with the binary in a single crate. This does however come
104+
with two disadvantages:
105+
106+
* Cargo currently doesn't support artifact-specific dependencies
107+
(although that may change, see [RFC 2887] & [RFC 3374]).
108+
109+
* You would have to bump the library version each time you want to
110+
publish a new version of the binary. If you want independently
111+
incrementable versions for your library and your binary, you have to
112+
publish them in separate crates.
113+
114+
The problem could also be sidestepped by publishing the command in a
115+
crate with the same name as the command and using a different name for
116+
the library crate, but this does arguably result in a worse user
117+
experience problem since `cargo add` does not fail for binary-only
118+
crates.
119+
120+
This RFC poses a simple solution to a rather annoying problem.
121+
122+
# Prior art
123+
[prior-art]: #prior-art
124+
125+
Most other package managers do not have such a problem since their
126+
install command does not mandate that the package contains binaries.
127+
128+
# Unresolved questions
129+
[unresolved-questions]: #unresolved-questions
130+
131+
* Is `recommended-bin-crates` a good name for the field?
132+
133+
# Future possibilities
134+
[future-possibilities]: #future-possibilities
135+
136+
* crates.io and/or lib.rs could additionally link crates referenced via
137+
this new field on their library web pages
138+
139+
* Clippy could gain a lint to check that the referenced crates actually
140+
exist, have not been yanked and are actually binary crates.
141+
142+
143+
[manifest page]: https://doc.rust-lang.org/cargo/reference/manifest.html
144+
[RFC 2887]: https://github.com/rust-lang/rfcs/pull/2887
145+
[RFC 3374]: https://github.com/rust-lang/rfcs/pull/3374

0 commit comments

Comments
 (0)