Must have Cargo subcommands
Cargo already comes with many commands, but just as rust itself, it’s designed to provide a stable core to be extended by faster evolving additional commands, published as separate crates.
All commands presented here can easily be installed via
$ cargo install $CRATE
into your $CARGO_HOME/bin
directory. Since Cargo 1.41 cargo install
can also update installed crates.
Must have subcommands
This is a list of crates I don’t want to miss in my daily life anymore, with exemplary use cases. Feel free to dig into the documentation of each crate, maybe other features are more relevant for you.
cargo-edit
cargo-edit
adds functionality NodeJS developers are used to from npm install
or yarn add
, i.e. adding the most recent version of a crate to your Cargo.toml (most recent by default, other versions may also be specified).
Although copy-pasting a crate’s Cargo.toml-snippet from crates.io seems to be just fine, cargo-add
comes in handy if you don’t know the (current) version of the crate. You need serde for your project? Cool, just issue cargo add serde
. You need reqwest? Just type cargo add reqwest
, no need to remember the version, it’s enough to know what crate you want.
Or do you know the major version of reqwest out of the top of your head?
Speaking of serde. You might also want serde with feature derive — so typically you need to turn
serde = "1.0.110"
into
serde = { version = "1.0.110", features = ["derive"] }
But once again cargo-edit
comes in handy1: cargo add serde --features derive
takes care of turning the shorthand version into the explicit version.
cargo-watch
cargo-watch
is almost the “classic” subcommand to have, and does what you expect — it watches your source-code for changes and executes any command. By default it executes cargo check
i.e. checks if your code compiles. Depending on your IDE this alone is worth alot — in the past, error feedback in older releases of IntelliJ Rust lagged behind a bit.
Via parameter -x
one can configure which (cargo-) command to run, so if you also want to check your tests, you might want to use cargo watch -x "check --tests"
.
Even a step further, you can also instruct cargo to execute your tests for any change via cargo watch -x test
— especially useful if you practice test driven development.
cargo-x
Once again a concept typical for NodeJS development (via package.json scripts
) is to make arbitrary complex commands available via simple aliases that can be placed into Cargo.toml
, more pecisely into the package metadata (see documentation for other options where to place such commands).
Example
This is an example taken from one of my projects, all geared towards exploratory testing/experiments:
[package.metadata.x]
reset-kafka = "kafka-consumer-groups --bootstrap-server $KAFKA_BROKER_ADDRESS_LIST --delete --group my_app --execute"
reset-db = "psql -c 'drop schema public cascade; create schema public;' my_backend && diesel migration run"
# sample command to verify authentication via X-WSSE
get-report-suites = "curl -s -X POST https://example.com -H 'Content-Type: application/json' -H \"X-Funny-Header: $(cargo run --bin funny_header_generator -q)\""
Now resetting kafka is as simple as cargo x reset-kafka
. Much better then remembering, typing or digging through history.
Should have subcommands
The must have commands are something I almost always need. Other commands are very special, so one might only install them on demand.
cargo-expand
cargo-expand
makes it simple to expand macros — which is supported by rustc, but only on nightly. So cargo-expand
requires the nightly-toolchain to be installed (can easily be done via rustup), but does not require to switch away from stable, as it calls nightly rustc in the background. It also calls rustc with all the flags necessary — flags you probably do not remember if you only need to sneak-peak into (expanded) macros from time to time.
Last thing I checked with cargo-expand
was an enum for error-handling — implemented via thiserror. The fully qualified name of this enum was kafka::error
, so I called cargo-expand
with
cargo expand --lib kafka::error
The --lib
flags limits the expansion to the current library, i.e. no expansion of macros in the “generated” code.
cargo-audit
Again, it’s obvious what cargo-audit
does: it scans your Cargo.lock for crates with known security issues. I can’t judge the quality of the security/audit/review-processes for rust crates, but the infrastructure is there, so if the shit hits the fan I’m sure there will be an advisory, thus an alarm by cargo audit.
So cargo-audit
is something you can at least put into your CI as a starting point.
cargo-tree
cargo-tree
comes in handy if you want to analyze dependencies of crates, e.g. to optimize your crate for compile-time or size. It prints the dependency-graph as a tree and also allows reverse-search (via flag -i
). See the documentation for examples.
cargo-cache
Last but not least, cargo-cache. Of course storage is cheap, but sometimes managing cargo’s global cache is necessary.
The “nuclear” option to purge the cache is running cargo cache -r all
which removes the cache completely. And no, rm -r ~/.cargo
is no proper cache-clean up, especially after reading this blog post and installing all these shiny cargo-subcommands to ~/.cargo/bin
;).
cargo-cache
's other options include compaction/gc and deletion based on age. I can imagine this to be useful for buildservers.
Honorable mention
If you need code-coverage, then tarpaulin is your goto crate. I did not use it (hey, you don’t need code coverage if you do proper TDD), but it seems to be a mature solution and the standard-solution for code coverage.
Also be sure to check the list of 3rd party subcommands, testing crates is simple, so why not give a crate a go if it sounds promising?
As of writing the
--features
flag is not yet available in a release version, so installcargo-edit
from source if it’s missing the--features
flag:cargo install --git https://github.com/killercup/cargo-edit.git cargo-edit
↩︎