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