Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

cargo is the Rust package manager, and is as well used to manage a Rust project as to install applications (crates) from the official repository.

The different actions provided by cargo are accessed through a set of sub-commands. See Table 1 for a list of the main sub-commands. To get the full list of sub-commands, run the following command:

Table 1:Main sub-commands of cargo

Sub-command

Shortcut

Description

add

Add dependencies to a Cargo.toml manifest file.

build

Compile a local package and all of its dependencies.

check

Check a local package and all of its dependencies for errors.

clean

Remove artifacts that cargo has generated in the past.

clippy

Check a package to catch common mistakes and improve your Rust code.

config

Inspect configuration values.

doc

d

Build a package’s documentation.

fix

Automatically fix lint warnings reported by rustc.

init

Create a new cargo package in a new or existing directory.

install

Install a Rust binary.

new

Create a new cargo package in a new directory.

remove

rm

Remove dependencies from a Cargo.toml manifest file.

run

r

Run a binary or example of the local package.

search

Search packages in the registry. Default registry is crates.io.

test

t

Execute all unit and integration tests and build examples of a local package.

tree

Display a tree visualization of a dependency graph.

uninstall

Remove a Rust binary.

version

Show version information.

3.4.1Installing an application

Rust public packages are called crates and provide binaries as well as libraries. Very useful Rust applications are available today on the official crate repository (https://crates.io/). We present in Table 2 a list of some of them. Most of them are replacement for standard Unix commands (e.g.: ls, find, cat, tree) that run faster and propose colourful outputs.

Table 2:Useful Rust applications

Crate

Command

Description

bat

bat

Replacement for cat.

bottom

btm

Replacement for top.

du-dust

dust

Replacement for du and ncdu.

eza

eza

Replacement for ls.

fd-find

fd

Replacement for find.

hexler

hexler

Replacement for hexdump.

procs

procs

Replacement for ps.

ripgrep

rg

Replacement for grep.

minijinja-cli

minijinja-cli

Rendering of MiniJinja/Jinja2 templates.

rustlings

rustlings

An application to learn Rust through exercises.

See Install a crate with Cargo to learn how to search for a crate and how to install it.

3.4.2Initializing a project

3.4.2.1Creating a new project from scratch

This is easily done with Cargo. To initialize a new project inside a new directory named foo, we run:

    Creating binary (application) package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

This will create a project file Cargo.toml and a source file src/main.rs that contains a default main() function:

foo
├── Cargo.toml
└── src
    └── main.rs

The project file defines a project name, a project version and the edition year of the cargo tool to use for managing this project:

[package]
name = "foo"
version = "0.1.0"
edition = "2024"

[dependencies]

If we look at the hidden files inside the project folder, we find that two Git related files have also been created:

.  ..  .git  .gitignore	 Cargo.toml  src

The .git folder means a Git database has been created. The .gitignore file contains a single line that makes Git ignore the target folder that is used by Cargo for its building outputs:

/target

Note that, however, the created Git database is left empty. All created files are list as untracked. This is up to us to include them or not inside the Git repository:

/tmp/tmp.Ic2WIzFr1b/foo /tmp/tmp.Ic2WIzFr1b
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.gitignore
	Cargo.toml
	src/

nothing added to commit but untracked files present (use "git add" to track)

3.4.3Building the project

To compile a whole project, we use the build sub-command:

   Compiling foo v0.1.0 (/tmp/tmp.Ic2WIzFr1b/foo)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.22s

To build in release (i.e.: no debug information) mode:

   Compiling foo v0.1.0 (/tmp/tmp.Ic2WIzFr1b/foo)
    Finished `release` profile [optimized] target(s) in 0.11s

3.4.4Running the application

To run the application, we use the run sub-command:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/foo`
Hello, world!

If there are multiple binaries in the project, we use the --bin option to set the binary to run:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/foo`
Hello, world!

To pass, argument to our binary, we would set them after a double dash --:

3.4.5Adding dependencies

To use external dependencies (e.g.: packages from crates.io), like in the following example with the colour package, we need first to declare it with cargo:

use colour::*;

fn main() {
  magenta_ln!("My coloured message.");
}

To declare the dependency, we use the add sub-command:

    Updating crates.io index
warning: failed to write cache, path: /usr/local/cargo/registry/index/index.crates.io-1949cf8c6b5b557f/.cache/co/lo/colour, error: Permission denied (os error 13)
      Adding colour v2.1.0 to dependencies
    Updating crates.io index
warning: failed to write cache, path: /usr/local/cargo/registry/index/index.crates.io-1949cf8c6b5b557f/.cache/co/lo/colour, error: Permission denied (os error 13)
     Locking 4 packages to latest Rust 1.95.0 compatible versions
      Adding colour v2.1.0
      Adding winapi v0.3.9
      Adding winapi-i686-pc-windows-gnu v0.4.0
      Adding winapi-x86_64-pc-windows-gnu v0.4.0

The dependencies section now contains a line for the colour package with a version requirement:

[package]
name = "foo"
version = "0.1.0"
edition = "2024"

[dependencies]
colour = "2.1.0"

Cargo also creates a lock file that contains the version used for each dependency. Here is an excerpt from the Cargo.lock file:

[[package]]
name = "colour"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b536eebcabe54980476d120a182f7da2268fe02d22575cca99cee5fdda178280"
dependencies = [
 "winapi",
]

[[package]]
name = "foo"
version = "0.1.0"
dependencies = [
 "colour",
]

[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
 "winapi-i686-pc-windows-gnu",

Running the application, will trigger the installation of the dependencies, as well as compilation, before running:

    Updating crates.io index
warning: failed to write cache, path: /usr/local/cargo/registry/index/index.crates.io-1949cf8c6b5b557f/.cache/co/lo/colour, error: Permission denied (os error 13)
 Downloading crates ...
  Downloaded colour v2.1.0
error: failed to open `/usr/local/cargo/registry/cache/index.crates.io-1949cf8c6b5b557f/colour-2.1.0.crate`

Caused by:
  Permission denied (os error 13)
Fetching long content....

see solution

3.4.6Running tests

We suppose we have implemented some test inside the tests folder:

Running this test, is as simple as running the test sub-command. Compiling of both the application and the tests will be triggered prior to running the tests:

3.4.7Checking the project

The check sub-command checks for errors inside the local packages and its dependencies. To do that, it runs a compiling up to, but excluding, the code generation. This means that most of compiling errors will be detected, but not all. However, it performs faster that the build sub-command, and thus is interesting for quick error checking:

3.4.8Linting the project

The clippy sub-command catches common mistakes, and gives advice to correct them. It helps us improve the quality of our code.

In the following example, we define a Book structure:

The program compiles perfectly:

However, clippy finds some issues in it:

In this other example, plain clippy misses the possible style improvement:

Nothing is pointed out by clippy:

To get the hint, we need to use the pedantic mode:

3.4.9Fixing automatically linting issues

The fix sub-command is able to solve automatically some of the warnings pointed out by the Rust compiler.

In the following example we have introduced a useless mut (mutable) specifier:

The check sub-command catches the mistake:

Running the fix sub-command will solve the issue for us:

The mut keyword has been removed: