#2 Rust - Cargo Package Manager
Tags: rust, programming
Published: 2024-02-04 14:09:34

## Diving Into Rust - Understanding Cargo and Dependencies

Hey there 👋

In the [previous post](https://dev.to/sarthaksavvy/entering-the-rust-universe-396a), we got an introduction to Rust and how to install Rust in our system. 

We also saw that `cargo` is at the core of setting up and managing a Rust project. In this post, we will dive deeper into `cargo` and understand why we need dependencies for projects. 

Suppose you wanted to write a Rust program that would generate random numbers and then use these numbers for some subsequent functionality. 

There are two ways to go about this - write all the functions from scratch, and take longer time to ship a working project OR use pre-built functions and packages to make our work easier and save time.

The second approach makes sense, doesn’t it? Because our core focus should be on building new functionalities, and not reinventing the wheel!

And that’s exactly why we need dependencies in projects. 

Someone has already written the necessary functions and packaged it in an industry-standard manner, and it is only wise that we utilise these packages. 

Now, there has to be a place where all these packages come from. Similar to `npmjs` registry, where all `node` packages are registered, stored and retrieved, Rust also has something called [`crates.io`](https://crates.io/) where many helpful packages and dependencies are registered. 



![Rust Cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8wyigrxpqmzoq2g8qkd5.png)


This registry is very useful, and as you can see, there are thousands of “crates” available. Crates are nothing but packages and dependencies. If you are familiar with other languages where such package management is used, then using `Crates.io` should be fairly straightforward. 

Let us take an example package here. Following the Rust documentation site, we need to install a package called `ferris-says`. Now, there are two ways to install packages to your Rust project -

### 1. Using Cargo -

Open the terminal in your project directory run the command `cargo add package_name` where `package_name` is the name of the package you need from Crates registry.

![Rust cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/irodckm60r1mzznv23xh.png)



### 2. Adding configuration line in `Cargo.toml` -

Under the `[dependencies]` header, we just add the name of the package and specify the version number, like this on line number 9- 


![Rust cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whtzkjr86ve15dbffvav.png)



For this example, let’s go with the command line option and see what happens - 


![Rust Cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gqg65i8p1bgutm74s2n0.png)



In a flash of a second, the operation is done, and the package is added!

The CLI gives a very crisp log of the sequence as the package installation happens. It first says that the `cargo` is updating the `crates.io` index (retrieval of package), and then adds `ferris-says` to dependencies. In the middle of this, it also displays the Features that were added with the package - something called `clippy` - which is a crate that contains a list of lints that are not available in the inbuilt Rust compiler lint list. These lints help improve our `cargo`. 

And finally, it displays the final log that the `crates.io` index has been updated and we can immediately see that in the `Cargo.toml` file, under `[dependencies]` header, the crate name with the version number is added. 

## What is Cargo.lock in Rust?

As you can see in the file structure, as soon as you ran the project, Rust “builds” the project, indexing all the dependencies we just configured in `Cargo.toml` file, and then generates a `Cargo.lock` file. 
This file contains a more detailed version of the `Cargo.toml` file and is meant to be used when we deploy our Rust app in different environments. 


![Rust Cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8bskerc6h70o8p5nf7u4.png)



Few things to note about the `Cargo.lock` file - 

- As it mentions at the top, this file is not intended for manual editing unless absolutely necessary and if you have enough knowledge to play around with it.
- Also, this file is automatically generated by Cargo, so even if you delete this file, there is nothing to worry; simply running the app again will ensure that this file is generated again. 
- It can be seen that the file contains very detailed information about the app and various dependencies including names, version numbers, and checksum codes. This ensures that the app and its dependencies are secure and that it works seamlessly across different production environments as well. 

## Advantage of manually adding the dependencies

If you noticed, there is a tab in the Crates.io website in the `ferris-says` package page, called “6 versions”. This means that from the time of its release in the Crates registry to the present moment, there have been 6 versions of the `ferris-says` released. And when you install it using the `cargo add` command, it adds the latest version by default. 


![Rust Cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9kilkqhnkorye9bm28h0.png)



In case you wanted to add a specific version or rollback to a previous version of the package for various reasons, you can do so by simply editing the package name in the `Cargo.toml` file under `[dependencies]` header. 


![Rust Cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wigfgae1s408gloehnpu.png)



This applies to not only editing the installed packages names, but also adding new packages manually with the desired version numbers, and running the app with the command `cargo run`. This will ensure that new packages with the exact specified version are installed, and also modifies the versions for existing packages in the `Cargo.lock` file as well, and then outputs the result - 


![Rust Cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/93ppjsrphvv3t33tptrq.png)



You can verify whether the version change has taken place by checking the `Cargo.lock` file too - 


![Rust Cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ai9rhs53c70fwmg5ezy3.png)



You can see here that the package version number has changed from `0.3.1` to `0.2.1` now. 

## How to use packages in Rust?

Until now, we saw how to install or modify packages in Rust. Now to actually use them in our application code, we need to specify in our `main.rs` file or any other Rust file that we intend to “use” the package, and also what functions specifically from the package we want to use. 

Since we are learning through the documentation, let’s go with the given example in the docs. And, remember, the docs use the latest versions so we have to change our `ferris_says` version back to the latest one. 

This is the example code from the docs - 


![Rust Cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rqnz7ful826zmcejd2ab.png)



As you can see, the first line says `use ferris_says::say` - where `use` is the keyword to specify that we want to use a package, and then the package name `ferris_says`, followed by the double colon `::` which is also known as the “path separator” and finally the name of the function we want to use from the package, namely `say`. When we run this program with `cargo run`, we get the following beautiful output - 


![Rust cargo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nkc9ck815iyqfbuaam40.png)



CLI outputs are so pleasing to look at, aren’t they 😁

Do not worry about the syntax or many of the keywords yet! We are doing to dive into these things very soon. 

Until then, keep yourself Rusty 🦀