Learning Rust - Introduction to Cargo and project structure
Tags: rust
Published: 2020-01-09 15:01:55

**Introduction**

So far, all the Rust code we have written is self-contained and small enough to fit in a single, isolated source file that can be compiled directly using `rustc`.
While this is a great way to explore the most basic constructs of a language, or simply to experiment with new concepts "in isolation", there are scenarios that demand some sort of code structure that makes it infeasible to keep a single source file.

We will see how Rust aids us in managing a larger project, how to structure it, and we will learn about Cargo which is Rust's package manager. Cargo downloads your Rust package’s dependencies, compiles your packages, makes distributable packages, and uploads them to crates.io, the Rust community’s package registry. 

**Installing Rust and Cargo**

By navigating to the official website for the language, or, checking [the book](https://doc.rust-lang.org/cargo/getting-started/installation.html) we can simply follow the instructions there to install both the cargo package manager and Rust, in one go. Under Linux/MacOS, this does the trick:

```
$ curl https://sh.rustup.rs -sSf | sh
```

This will install both cargo and rust, and we can start managing our Rust code using cargo. Let's see how to setup a basic program via cargo and how to compile it and run it, and lastly, we will touch upon why we need cargo when working with larger rust projects.

**Prepare a binary program using cargo**

Rust (well, cargo) makes a distinction between binary programs and libraries.

The default behavior of cargo is to generate a binary program when called with no flags. As such:

`cargo new hello_world`

will create a new **package** that will hold a binary program. If we had passed the `--lib` argument, we'd make a library instead.

Let's see what this generates for us:

```
$ cd hello_world
$ tree .
.
├── Cargo.toml
└── src
    └── main.rs

1 directory, 2 files
```

So, we can see one directory and two files have been generated.

The directory name is `src` and this is a Rust convention to say that, inside this directory we will have Rust application code. 

As in many other languages, `main.rs` is the entry point for a more complex Rust application, and `cargo` uses these conventions to work.

If we had libraries, or had ran the command with the `--lib` flag, it would go inside a `lib` directory, again, by convention.

**Exploring Cargo.toml**

The other auto-generated file is called `Cargo.toml` and it's a special file, in the sense that we can see it as a **manifest**, and it contains all of the metadata that Cargo needs to compile our package.

```rust
[package]
name = "hello_world"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2018"

[dependencies]
```

We have two main sections in our Cargo file: `package` and `dependencies`.

The `package` section contains information about our project, and it can be seen as simple meta-information, such as, project name, author's names, version, etc. This is auto-generated but can be completed and later maintained by the developer(s).

The `dependencies` section contains dependencies for our project, which are called `crates` in Rust terminology.

These can be external crates, retrieved from a central repository such as [crates.io](https://crates.io) or it can be user-defined crates containing specific functions.

Any Rust project created and/or managed via cargo, knows all it needs to, via the `Cargo.toml` file. This is a dynamic file that grows and changes together with your project, and it has some noteworthy goals as to why it exists in the first place:

- Introduces two metadata files with various bits of package information.
- Fetches and builds your package’s dependencies.
- Invokes rustc or another build tool with the correct parameters to build your package.
- Introduces conventions to make working with Rust packages easier. 

**Building and compiling with Cargo**

We can use Cargo both as a package manager as well as a build system for our Rust programs, and we can also compile and run our programs using it, which we can and should do.

 *Simple compile, followed by manual run*

Using `cargo build` in the root directory will compile the project, which can then be run manually by going into the target and debug folder and run the generated executable from there:

```
$ ./target/debug/hello_world
Hello, world!
```

*All in one go*

To do all in one go, we can do:

`cargo run` 

which will compile and then run the program.

**Conclusion**

Next, we'll see how to create our own modules and structure our project with them.