Rust is nice to learn, although the learning curve is quite a steep. Let’s start here with some basics on cargo
and rust
. You can download rust from Rust-Lang.org so we would just dive straight into working with rust
.
Cargo
cargo
is the tool we’ll use to create, manage and compile projects. It’s sort of like Makefile
or CMakeLists.txt
but just a lot more nicer and easier to understand. The first command we’ll use is the new
command which creates a new project for us including the manifest file called Cargo.toml
.
$ cargo new hello-world
So this creates a new directory having the sources in the src
directory. Also if you see the name of the project is hello-world
in the generated Cargo.toml
We can change the name of the project and in this case it’ll be the name of the binary which is generated, so let’s take a look at Cargo.toml
.
[package]
name = "hello-world"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
We can change the name of the package here and that’ll be the name of the binary which is generated when we build this project. The project is called as crate
in the rust world. This particular hello-world crate is a binary project, i.e. one that doesn’t create libraries but only a binary. To create a library as well as a binary for the same project you need create a project using the --lib
OR add a lib.rs
in the src
directory.
$ cargo new --lib hello-world
Directory Structure
Cargo creates a directory structure that it understands and applies some hueristics on it. For example, adding the --lib
flag to cargo doesn’t change anything in the Cargo.toml
however it adds a lib.rs
file in the src
directory. Cargo
understands this and builds a library as well as a binary with the name as specified in the Cargo.toml
.
.
├── Cargo.lock
├── Cargo.toml
└── src
├── lib.rs
└── main.rs
1 directory, 4 files
The above is a listing of the current directory of the hello-world
project. But when you build using cargo build
then this creates a bunch of other files, quite a lot actually. The final output is present in the debug
directory and if you use the --release
flag then output would be in the release
directory as shown below
├── Cargo.lock
├── Cargo.toml
├── src
│ ├── lib.rs
│ └── main.rs
└── target
├── CACHEDIR.TAG
└── release
3 directories, 5 files
When you’ve a lib.rs
as well as main.rs
then both the binary and the library file would be created in the target directory. The library created is a static library by default, however if required we can also generate a shared library by changing the type of crate in Cargo.toml
as shown below
[lib]
crate-type= ["lib", "dylib"]
tests
This is a special directory recognized by cargo
and it assumes that all tests are housed in this directory. So when we call cargo tests
we tell cargo
to run the tests in this directory. However the tests still required to be marked
as tests. An example is shown here just for completion,
.
├── Cargo.lock
├── Cargo.toml
├── src
│ └── lib.rs
└── tests
└── unit.rs
About modules and crates
cargo
only knows that it needs to compile main.rs
and lib.rs
if present. Obviously not all of our code is going to be within a single file, so other files ending in .rs
are separate modules. cargo
has no clue about them thus we need to use
them in either main
or lib
so that cargo
can find these modules. There are two ways to do this,
- using the
use
statement - using the
mod
statement.
The difference between them is, mod
is used for code which you’ve access to, for example when writing your own projects
.
use
is used when you want to have access to code that’s coming externally and you’re just using it NOT pulling it in your code verbatim.
crate
is the toplevel module for each project, so it can contain modules and sub-modules. We’ll see more on this in some later blogs.
Until then have fun!