Rust Cargo – Tutorial and Best Crates

Rust Cargo

What is Rust Cargo?

Cargo is Rust’s build system and package manager.

[lwptoc]

What are it's roles?

Rust Developers use Cargo to Manage their Rust projects because Cargo handles a lot of tasks for you such as:

  1. Building your code
  2. Downloading the libraries your code depends on
  3. Building those libraries. (We call libraries your code needs dependencies.)

Must all Rust Programs use Cargo?

No, the simplest Rust programs, like the one we’ve written so far, don’t have any dependencies. So if we had built the “Hello, world!” project with Cargo, it would only use the part of Cargo that handles building your code.

However, as you write more complex Rust programs, you’ll add dependencies, and if you start a project using Cargo, adding dependencies will be much easier to do.

How do you check if Cargo is installed?

If you installed Rust through some other means, check whether Cargo is installed by entering the following into your terminal:

$ cargo --version

If you see a version number, you have it! If you see an error, such as command not found, look at the documentation for your method of installation to determine how to install Cargo separately.

How to create a project with Cargo

Here's how:

$ cargo new hello_cargo
$ cd hello_cargo

The first command creates a new directory called hello_cargo. We’ve named our project hello_cargo, and Cargo creates its files in a directory of the same name.

Go into the hello_cargo directory and list the files. You’ll see that Cargo has generated two files and one directory for us: a Cargo.toml file and a src directory with a main.rs file inside.

It has also initialized a new Git repository along with a .gitignore file. Git files won’t be generated if you run cargo new within an existing Git repository; you can override this behavior by using cargo new --vcs=git.

If you open Cargo.toml in your text editor it will roughly look like this:

[package]
name = "hello_cargo"
version = "0.1.0"
authors = ["Your Name <[email protected]>"]
edition = "2018"

[dependencies]

This file is in the TOML (Tom’s Obvious, Minimal Language) format, which is Cargo’s configuration format.

The first line, [package], is a section heading that indicates that the following statements are configuring a package. As we add more information to this file, we’ll add other sections.

The next four lines set the configuration information Cargo needs to compile your program: the name, the version, who wrote it, and the edition of Rust to use. Cargo gets your name and email information from your environment, so if that information is not correct, fix the information now and then save the file. We’ll talk about the edition key in Appendix E.

The last line, [dependencies], is the start of a section for you to list any of your project’s dependencies. In Rust, packages of code are referred to as crates. We won’t need any other crates for this project, but we will in the first project in Chapter 2, so we’ll use this dependencies section then.

How do you build a Cargo Project?

Build a project like this with cargo:

$ cargo build

You'll see a result like this:

   Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs

This command creates an executable file in target/debug/hello_cargo (or target\debug\hello_cargo.exe on Windows) rather than in your current directory.

How do you run a Cargo Project?

You can run the executable with this command:

To run the executable:

$ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows
Hello, world!

We just built a project with cargo build and ran it with ./target/debug/hello_cargo, but we can also use cargo run to compile the code and then run the resulting executable all in one command:

$ cargo run

You'll see a result like this:

    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running target/debug/hello_cargo
Hello, world!

How to build For Release

When your project is finally ready for release, you can use cargo build --release to compile it with optimizations. This command will create an executable in target/release instead of target/debug. The optimizations make your Rust code run faster, but turning them on lengthens the time it takes for your program to compile. This is why there are two different profiles: one for development, when you want to rebuild quickly and often, and another for building the final program you’ll give to a user that won’t be rebuilt repeatedly and that will run as fast as possible. If you’re benchmarking your code’s running time, be sure to run cargo build --release and benchmark with the executable in target/release.

Let us now look at a simple example:

In this tutorial you will learn about Cargo via simple examples.

Example 1: Hello Cargo

This is a simple Rust cargo example.

Step 1: Create Project

  1. Open your Rust IDE.
  2. In the menu go to File --> Create New Project.

Step 2: Add Dependencies

Go to your Cargo.toml and modify it as follows:

# toml = Tom's obvious, minimal language
# toml is Cargo's configuration format.
# this is where you specify details about your package.

# see more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[package]
name = "hello-cargo"                    # what's the name of this package?
version = "0.1.0"                       # what's the version of this package?
authors = ["Inanc Gumus <[email protected]>"]  # who wrote this package?
edition = "2018"                        # rust edition
# see: https://doc.rust-lang.org/edition-guide/editions/index.html

# this package doesn't depend on other packages (crates),
# so this is empty.
[dependencies]

# Use these settings for optimized output

# [profile.release]
# opt-level = 'z'     # Optimize for size.
# lto = true          # Enable Link Time Optimization
# codegen-units = 1   # Reduce number of codegen units to increase optimizations.
# panic = 'abort'     # Abort on panic

Step 3: Write Code

Next create a file known as main.rs and add the following code:

fn main() {
    println!("Hello, world!");
}

Run

Copy the code, build and run.

Reference

Here are the reference links:

Number Link
1. Download Example
2. Follow code author
3. Code: Apache 2.0 License

Best Rust Cargo third Party Libraries

Rustaceans have created several third party libraries related to cargo. You may want to enhance your cargo usage or simply find these abstractions more productive. Thus let's examine them.

(a). cargo edit

This tool extends Cargo to allow you to add, remove, and upgrade dependencies by modifying your Cargo.toml file from the command line.

Currently available subcommands:

Installation

Ensure that you have a fairly recent version of rust/cargo installed. On Ubuntu you would also need to install libssl-dev and pkg-config packages.

$ cargo install cargo-edit

If you wish to use a bundled version of openssl:

$ cargo install cargo-edit --features vendored-openssl

Compiler support: requires rustc 1.44+

(Please check cargo's documentation to learn how cargo install works and how to set up your system so it finds binaries installed by cargo.)

Install a sub-set of the commands with cargo install -f --no-default-features --features "<COMMANDS>", where <COMMANDS> is a space-separated list of commands; i.e. add rm upgrade for the full set.

Available Subcommands

cargo add

Add new dependencies to your Cargo.toml. When no version is specified, cargo add will try to query the latest version's number from crates.io.

Examples

$ # Add a specific version
$ cargo add [email protected] --dev
$ # Query the latest version from crates.io and adds it as build dependency
$ cargo add gcc --build
$ # Add a non-crates.io crate
$ cargo add local_experiment --path=lib/trial-and-error/
$ # Add a non-crates.io crate; the crate name will be found automatically
$ cargo add lib/trial-and-error/
$ # Add a crates.io crate with a local development path
$ cargo add my_helper --vers=1.3.1 --path=lib/my-helper/
$ # Add a renamed dependency
$ cargo add thiserror --rename error

Usage

$ cargo add -h
cargo-add
Add dependency to a Cargo.toml manifest file

USAGE:
    cargo add [FLAGS] [OPTIONS] <crate>...

FLAGS:
        --allow-prerelease       Include prerelease versions when fetching from crates.io (e.g. '0.6.0-alpha')
    -B, --build                  Add crate as build dependency
    -D, --dev                    Add crate as development dependency
    -h, --help                   Prints help information
        --no-default-features    Set default-features = false for the added dependency
        --offline                Run without accessing the network
        --optional               Add as an optional dependency (for use in features)
    -q, --quiet                  Do not print any output in case of success
    -s, --sort                   Sort dependencies even if currently unsorted
    -V, --version                Prints version information

OPTIONS:
        --branch <branch>           Specify a git branch to download the crate from
        --features <features>...    Space-separated list of features to add. For an alternative approach to enabling
                                    features, consider installing the cargo-feature utility
        --git <uri>                 Specify a git repository to download the crate from
        --manifest-path <path>      Path to the manifest to add a dependency to
        --path <path>               Specify the path the crate should be loaded from
    -p, --package <pkgid>           Package id of the crate to add this dependency to
        --registry <registry>       Registry to use
    -r, --rename <rename>           Rename a dependency in Cargo.toml, https://doc.rust-
                                    lang.org/cargo/reference/specifying-
                                    dependencies.html#renaming-dependencies-in-cargotoml Only works
                                    when specifying a single dependency
        --target <target>           Add as dependency to the given target platform
        --upgrade <method>          Choose method of semantic version upgrade.  Must be one of "none" (exact version,
                                    = modifier), "patch" (~ modifier), "minor" (^ modifier), "all" (>=), or
                                    "default" (no modifier) [default: default]  [possible values: none, patch, minor,
                                    all, default]
        --vers <uri>                Specify the version to grab from the registry(crates.io). You can also specify
                                    version as part of name, e.g cargo add [email protected]

ARGS:
    <crate>...    Crates to be added

This command allows you to add a dependency to a Cargo.toml manifest file. If <crate> is a github
or gitlab repository URL, or a local path, cargo add will try to automatically get the crate name
and set the appropriate --git or --path value.

Please note that Cargo treats versions like '1.2.3' as '^1.2.3' (and that '^1.2.3' is specified
as '>=1.2.3 and <2.0.0'). By default, cargo add will use this format, as it is the one that the
crates.io registry suggests. One goal of cargo add is to prevent you from using wildcard
dependencies (version set to '*').

cargo rm

Remove dependencies from your Cargo.toml.

Examples

$ # Remove a dependency
$ cargo rm regex
$ # Remove a development dependency
$ cargo rm regex --dev
$ # Remove a build dependency
$ cargo rm regex --build

Usage

$ cargo rm -h
cargo-rm
Remove a dependency from a Cargo.toml manifest file

USAGE:
    cargo rm [FLAGS] [OPTIONS] <crates>...

FLAGS:
    -B, --build      Remove crate as build dependency
    -D, --dev        Remove crate as development dependency
    -h, --help       Prints help information
    -q, --quiet      Do not print any output in case of success
    -V, --version    Prints version information

OPTIONS:
        --manifest-path <path>    Path to the manifest to remove a dependency from
    -p, --package <package>       Specify the package in the workspace to add a dependency to (see cargo help pkgid)

ARGS:
    <crates>...    Crates to be removed

cargo upgrade

Upgrade dependencies in your Cargo.toml to their latest versions.

To specify a version to upgrade to, provide the dependencies in the <crate name>@<version> format, e.g. cargo upgrade [email protected]~0.9.0 [email protected]>=0.9,<2.0.

This command differs from cargo update, which updates the dependency versions recorded in the local lock file (Cargo.lock).

Examples

# Upgrade all dependencies for the current crate
$ cargo upgrade
# Upgrade docopt (to ~0.9) and serde (to >=0.9,<2.0)
$ cargo upgrade [email protected]~0.9 [email protected]>=0.9,<2.0
# Upgrade regex (to the latest version) across all crates in the workspace
$ cargo upgrade regex --workspace
# Upgrade all dependencies except docopt and serde
$ cargo upgrade --exclude docopt serde

Usage

$ cargo upgrade -h
cargo-upgrade
Upgrade dependencies as specified in the local manifest file (i.e. Cargo.toml)

USAGE:
    cargo upgrade [FLAGS] [OPTIONS] [dependency]...

FLAGS:
        --workspace           Upgrade all packages in the workspace
        --allow-prerelease    Include prerelease versions when fetching from crates.io (e.g. 0.6.0-alpha')
        --dry-run             Print changes to be made without making them
    -h, --help                Prints help information
        --offline             Run without accessing the network
        --skip-compatible     Only update a dependency if the new version is semver incompatible
        --to-lockfile         Upgrade all packages to the version in the lockfile
    -V, --version             Prints version information

OPTIONS:
        --exclude <exclude>...    Crates to exclude and not upgrade
        --manifest-path <path>    Path to the manifest to upgrade
    -p, --package <package>       Specify the package in the workspace to add a dependency to (see cargo help pkgid)

ARGS:
    <dependency>...    Crates to be upgraded

This command differs from cargo update, which updates the dependency versions recorded in the
local lock file (Cargo.lock).

If <dependency>(s) are provided, only the specified dependencies will be upgraded. The version to
upgrade to for each can be specified with e.g. [email protected] or [email protected]>=0.9,<2.0.

Dev, build, and all target dependencies will also be upgraded. Only dependencies from crates.io are
supported. Git/path dependencies will be ignored.

All packages in the workspace will be upgraded if the --workspace flag is supplied.
The --workspace flag may be supplied in the presence of a virtual manifest.

If the '--to-lockfile' flag is supplied, all dependencies will be upgraded to the currently locked
version as recorded in the Cargo.lock file. This flag requires that the Cargo.lock file is
up-to-date. If the lock file is missing, or it needs to be updated, cargo-upgrade will exit with an
error. If the '--to-lockfile' flag is supplied then the network won't be accessed.

Reference

Find full reference here.

(b). cargo-make

Rust task runner and build tool.

The cargo-make task runner enables to define and configure sets of tasks and run them as a flow.
A task is a command, script, rust code or other sub tasks to execute.
Tasks can have dependencies which are also tasks that will be executed before the task itself.
With a simple toml based configuration file, you can define a multi platform build script that can run build, test, generate documentation, run bench tests, run security validations and more, executed by running a single command.

Installation

In order to install, just run the following command

cargo install --force cargo-make

This will install cargo-make in your ~/.cargo/bin.
Make sure to add ~/.cargo/bin directory to your PATH variable.

You will have two executables available: cargo-make and makers

  • cargo-make - This is a cargo plugin invoked using cargo make ...
  • makers - A standalone executable which provides same features and cli arguments as cargo-make but is invoked directly and not as a cargo plugin.

See Cli Options section for full CLI instructions.

Binary Release

Binary releases are available in the github releases page.
The following binaries are available for each release:

  • x86_64-unknown-linux-musl
  • x86_64-apple-darwin
  • x86_64-pc-windows-msvc
  • arm-unknown-linux-gnueabihf

Usage

When using cargo-make, all tasks are defined and configured via toml files.
Below are simple instructions to get you started off quickly.

Simple Example

In order to run a set of tasks, you first must define them in a toml file.
For example, if we would like to have a script which:

  • Formats the code
  • Cleans old target directory
  • Runs build
  • Runs tests

We will create a toml file as follows:

[tasks.format]
install_crate = "rustfmt"
command = "cargo"
args = ["fmt", "--", "--emit=files"]

[tasks.clean]
command = "cargo"
args = ["clean"]

[tasks.build]
command = "cargo"
args = ["build"]
dependencies = ["clean"]

[tasks.test]
command = "cargo"
args = ["test"]
dependencies = ["clean"]

[tasks.my-flow]
dependencies = [
    "format",
    "build",
    "test"
]

We would execute the flow with the following command:

cargo make --makefile simple-example.toml my-flow

The output would look something like this:

[cargo-make] INFO - cargo make 0.33.0
[cargo-make] INFO - Build File: simple-example.toml
[cargo-make] INFO - Task: my-flow
[cargo-make] INFO - Setting Up Env.
[cargo-make] INFO - Running Task: format
[cargo-make] INFO - Execute Command: "cargo" "fmt" "--" "--emit=files"
[cargo-make] INFO - Running Task: clean
[cargo-make] INFO - Execute Command: "cargo" "clean"
[cargo-make] INFO - Running Task: build
[cargo-make] INFO - Execute Command: "cargo" "build"
   Compiling bitflags v0.9.1
   Compiling unicode-width v0.1.4
   Compiling quote v0.3.15
   Compiling unicode-segmentation v1.1.0
   Compiling strsim v0.6.0
   Compiling libc v0.2.24
   Compiling serde v1.0.8
   Compiling vec_map v0.8.0
   Compiling ansi_term v0.9.0
   Compiling unicode-xid v0.0.4
   Compiling synom v0.11.3
   Compiling rand v0.3.15
   Compiling term_size v0.3.0
   Compiling atty v0.2.2
   Compiling syn v0.11.11
   Compiling textwrap v0.6.0
   Compiling clap v2.25.0
   Compiling serde_derive_internals v0.15.1
   Compiling toml v0.4.2
   Compiling serde_derive v1.0.8
   Compiling cargo-make v0.1.2 (file:///home/ubuntu/workspace)
    Finished dev [unoptimized + debuginfo] target(s) in 79.75 secs
[cargo-make] INFO - Running Task: test
[cargo-make] INFO - Execute Command: "cargo" "test"
   Compiling cargo-make v0.1.2 (file:///home/ubuntu/workspace)
    Finished dev [unoptimized + debuginfo] target(s) in 5.1 secs
     Running target/debug/deps/cargo_make-d5f8d30d73043ede

running 10 tests
test log::tests::create_info ... ok
test log::tests::get_level_error ... ok
test log::tests::create_verbose ... ok
test log::tests::get_level_info ... ok
test log::tests::get_level_other ... ok
test log::tests::get_level_verbose ... ok
test installer::tests::is_crate_installed_false ... ok
test installer::tests::is_crate_installed_true ... ok
test command::tests::validate_exit_code_error ... ok
test log::tests::create_error ... ok

test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

[cargo-make] INFO - Running Task: my-flow
[cargo-make] INFO - Build done in 72 seconds.

Reference

Find complete documentation and source code here.

(c). cargo-geiger

A program that lists statistics related to the usage of unsafe Rust code in a Rust crate and all its dependencies.

This cargo plugin were originally based on the code from two other projects: https://github.com/icefoxen/cargo-osha and https://github.com/sfackler/cargo-tree.

Installation

Try to find and use a system-wide installed OpenSSL library:

cargo install cargo-geiger

Or, build and statically link OpenSSL as part of the cargo-geiger executable:

cargo install cargo-geiger --features vendored-openssl

Usage

  1. Navigate to the same directory as the Cargo.toml you want to analyze.
  2. cargo geiger

Output example

Example output

Why even care about unsafe Rust usage?

When and why to use unsafe Rust is out of scope for this project; it is simply a tool that provides information to aid auditing and hopefully to guide dependency selection. It is, however, the opinion of the author of this project that libraries choosing to abstain from unsafe Rust usage when possible should be promoted.

This project is an attempt to create pressure against unnecessary usage of unsafe Rust in public Rust libraries.

Reference

Find compltere documentation here.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *