cargo_hakari/lib.rs
1// Copyright (c) The cargo-guppy Contributors
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! `cargo hakari` is a command-line application to manage workspace-hack crates. Use it to speed up
5//! local `cargo build` and `cargo check` commands by up to **100x**, and cumulatively by up to
6//! **1.7x** or more.
7//!
8//! For an explanation of what workspace-hack packages are and how they make your builds faster, see
9//! the [`about` module](https://docs.rs/cargo-hakari/latest/cargo_hakari/about).
10//!
11//! # Examples
12//!
13//! The `cargo-guppy` repository uses a workspace-hack crate managed by `cargo hakari`. [See the
14//! generated `Cargo.toml`.](https://github.com/guppy-rs/guppy/blob/main/workspace-hack/Cargo.toml)
15//!
16//! # Platform support
17//!
18//! * **Unix platforms**: Hakari works and is supported.
19//! * **Windows**: Hakari works and outputs file paths with forward slashes for consistency with
20//! Unix. CRLF line endings are not supported in the workspace-hack's `Cargo.toml`. Within Git
21//! repositories, `cargo hakari init` automatically does this for you. [Here's how to do it
22//! manually.](https://stackoverflow.com/a/10017566) (Pull requests to improve this are welcome.)
23//!
24//! # Installation
25//!
26//! ## Release binaries
27//!
28//! Release binaries are available on [GitHub
29//! Releases](https://github.com/guppy-rs/guppy/releases?q=cargo-hakari&expanded=true), via [`cargo
30//! binstall`](https://github.com/cargo-bins/cargo-binstall):
31//!
32//! ```sh
33//! cargo binstall cargo-hakari
34//! ```
35//!
36//! In GitHub Actions CI, use [`taiki-e/install-action`](https://github.com/taiki-e/install-action),
37//! which uses `cargo binstall` under the hood:
38//!
39//! ```yml
40//! - name: Install cargo-hakari
41//! uses: taiki-e/install-action@v2
42//! with:
43//! tool: cargo-hakari
44//! ```
45//!
46//! ## Installing from source
47//!
48//! To install or update `cargo-hakari`, run:
49//!
50//! ```sh
51//! cargo install cargo-hakari --locked
52//! ```
53//!
54//! If `$HOME/.cargo/bin` is in your `PATH`, the `cargo hakari` command will be available.
55//!
56//! # Usage
57//!
58//! ## Getting started
59//!
60//! There are four steps you *must* take for `cargo hakari` to work properly.
61//!
62//! ### 1. Check in your `Cargo.lock`
63//!
64//! For hakari to work correctly, you *must* [add your `Cargo.lock` to version
65//! control](https://doc.rust-lang.org/cargo/faq.html#why-do-binaries-have-cargolock-in-version-control-but-not-libraries),
66//! even if you don't have any binary crates. This is because patch version bumps in dependencies
67//! can add or remove features or even entire transitive dependencies.
68//!
69//! ### 2. Initialize the workspace-hack
70//!
71//! Initialize a workspace-hack crate for a workspace at path `my-workspace-hack`:
72//!
73//! ```sh
74//! cargo hakari init my-workspace-hack
75//! ```
76//!
77//! <p align="center">
78//! <img src="https://user-images.githubusercontent.com/180618/135726175-dc00dd0c-68a1-455f-a13d-0dd24f545ca6.png">
79//! </p>
80//!
81//! ### 3. Generate the `Cargo.toml`
82//!
83//! Generate or update the contents of a workspace-hack crate:
84//!
85//! ```sh
86//! cargo hakari generate
87//! ```
88//!
89//! ### 4. Add dependencies to the workspace-hack
90//!
91//! Add the workspace-hack crate as a dependency to all other workspace crates:
92//!
93//! ```sh
94//! cargo hakari manage-deps
95//! ```
96//!
97//! <p align="center">
98//! <img src="https://user-images.githubusercontent.com/180618/135725773-c71fc4cd-8b7d-4a8e-b97c-d84a2b3b3662.png">
99//! </p>
100//!
101//! ## Making hakari work well
102//!
103//! These are things that are not absolutely necessary to do, but will make `cargo hakari` work
104//! better.
105//!
106//! ### 1. Update the hakari config
107//!
108//! Open up `.config/hakari.toml`, then:
109//!
110//! * uncomment or add commonly-used developer platforms
111//! * read the note about the resolver, and strongly consider [setting `resolver =
112//! "2"`](https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver) in
113//! your workspace's `Cargo.toml`.
114//!
115//! Remember to run `cargo hakari generate` after changing the config.
116//!
117//! ### 2. Keep the workspace-hack up-to-date in CI
118//!
119//! Run the following commands in CI:
120//!
121//! ```sh
122//! cargo hakari generate --diff # workspace-hack Cargo.toml is up-to-date
123//! cargo hakari manage-deps --dry-run # all workspace crates depend on workspace-hack
124//! ```
125//!
126//! If either of these commands exits with a non-zero status, you can choose to fail CI or produce a
127//! warning message.
128//!
129//! For an example, see [this GitHub action used by
130//! `cargo-guppy`](https://github.com/guppy-rs/guppy/blob/main/.github/workflows/hakari.yml).
131//!
132//! All `cargo hakari` commands take a `--quiet` option to suppress output, though showing diff
133//! output in CI is often useful.
134//!
135//! ### 3. Consider a `[patch]` directive
136//!
137//! If your workspace is depended on as a Git or path dependency, it is **strongly recommended**
138//! that you follow the instructions in the [`[patch]` directive
139//! section](https://docs.rs/cargo-hakari/latest/cargo_hakari/patch_directive).
140//!
141//! ## Information about the workspace-hack
142//!
143//! The commands in this section provide information about components in the workspace-hack.
144//!
145//! ### Why is a dependency in the workspace-hack?
146//!
147//! Print out information about why a dependency is present in the workspace-hack:
148//!
149//! ```sh
150//! cargo hakari explain <dependency-name>
151//! ```
152//!
153//! <p align="center">
154//! <img src="https://user-images.githubusercontent.com/180618/144933657-c45cf719-ecaf-49e0-b2c7-c8d12adf11c0.png" width=550>
155//! </p>
156//!
157//! ### Does the workspace-hack ensure that each dependency is built with exactly one feature set?
158//!
159//! ```sh
160//! cargo hakari verify
161//! ```
162//!
163//! If some dependencies are built with more than one feature set, this command will print out
164//! details about them. **This is always a bug**---if you encounter it, [a bug
165//! report](https://github.com/guppy-rs/guppy/issues/new) with more information would be greatly
166//! appreciated!
167//!
168//! ## Publishing a crate
169//!
170//! If you publish crates to `crates.io` or other registries, see the [`publishing`
171//! module](https://docs.rs/cargo-hakari/latest/cargo_hakari/publishing).
172//!
173//! ## Disabling and uninstalling
174//!
175//! Disable the workspace-hack crate temporarily by removing generated lines from `Cargo.toml`.
176//! (Re-enable by running `cargo hakari generate`.)
177//!
178//! ```sh
179//! cargo hakari disable
180//! ```
181//!
182//! Remove the workspace-hack crate as a dependency from all other workspace crates:
183//!
184//! ```sh
185//! cargo hakari remove-deps
186//! ```
187//!
188//! <p align="center">
189//! <img src="https://user-images.githubusercontent.com/180618/135726181-9fe86782-6471-4a1d-a511-a6c55dffbbd7.png">
190//! </p>
191//!
192//! # Configuration
193//!
194//! `cargo hakari` is configured through `.config/hakari.toml` at the root of the workspace. Running
195//! `cargo hakari init` causes a new file to be created at this location.
196//!
197//! Example configuration:
198//!
199//! ```toml
200//! ## The name of the package used for workspace-hack unification.
201//! hakari-package = "workspace-hack"
202//! ## Cargo resolver version in use -- version 2 is highly recommended.
203//! resolver = "2"
204//!
205//! ## Format for `workspace-hack = ...` lines in other Cargo.tomls.
206//! dep-format-version = "4"
207//!
208//! ## Add triples corresponding to platforms commonly used by developers here.
209//! ## https://doc.rust-lang.org/rustc/platform-support.html
210//! platforms = [
211//! ## "x86_64-unknown-linux-gnu",
212//! ## "x86_64-apple-darwin",
213//! ## "x86_64-pc-windows-msvc",
214//! ]
215//!
216//! ## Write out exact versions rather than specifications. Set this to true if version numbers in
217//! ## `Cargo.toml` and `Cargo.lock` files are kept in sync, e.g. in some configurations of
218//! ## https://dependabot.com/.
219//! ## exact-versions = false
220//! ```
221//!
222//! For more options, including how to exclude crates from the output, see the [`config`
223//! module](https://docs.rs/cargo-hakari/latest/cargo_hakari/config).
224//!
225//! # Stability guarantees
226//!
227//! `cargo-hakari` follows semantic versioning, where the public API is the command-line interface.
228//!
229//! Within a given series, the command-line interface will be treated as append-only.
230//!
231//! The generated `Cargo.toml` will also be kept the same unless:
232//!
233//! * a new config option is added, in which case the different output will be gated on the new
234//! option, or
235//! * there is a bugfix involved.
236
237mod cargo_cli;
238mod command;
239mod docs;
240mod helpers;
241mod output;
242mod publish;
243
244pub use docs::*;
245
246// Not part of the stable API.
247#[doc(hidden)]
248pub use command::Args;